module AWS.EC2.Instance
( describeInstances
, runInstances
, RunInstancesParam(..)
, defaultRunInstancesParam
, terminateInstances
, startInstances
, stopInstances
, rebootInstances
, getConsoleOutput
, getPasswordData
, describeInstanceStatus
) where
import Data.Text (Text)
import Data.ByteString (ByteString)
import Data.XML.Types (Event)
import Data.Conduit
import Control.Monad.Trans.Control (MonadBaseControl)
import Control.Applicative
import AWS.EC2.Types
import AWS.EC2.Params
import AWS.EC2.Utils
import AWS.EC2.Class
import AWS.EC2.Query
import AWS.EC2.Parser
import AWS.Util
describeInstances
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> [Filter]
-> EC2 m (Source m Reservation)
describeInstances instances filters = do
ec2QuerySource "DescribeInstances" params $
itemConduit "reservationSet" reservationSink
where
params =
[ ArrayParams "InstanceId" instances
, FilterParams filters
]
reservationSink :: MonadThrow m
=> GLSink Event m Reservation
reservationSink =
reservation
<$> getT "reservationId"
<*> getT "ownerId"
<*> groupSetSink
<*> instanceSetSink
<*> getMT "requesterId"
groupSetSink :: MonadThrow m => GLSink Event m [Group]
groupSetSink = itemsSet "groupSet" $ group
<$> getT "groupId"
<*> getT "groupName"
instanceSetSink :: MonadThrow m
=> GLSink Event m [Instance]
instanceSetSink = itemsSet "instancesSet" $
ec2Instance
<$> getT "instanceId"
<*> getT "imageId"
<*> instanceStateSink "instanceState"
<*> getT "privateDnsName"
<*> getT "dnsName"
<*> getT "reason"
<*> getMT "keyName"
<*> getT "amiLaunchIndex"
<*> productCodeSink
<*> getT "instanceType"
<*> getF "launchTime" textToTime
<*> element "placement" (
placement
<$> getT "availabilityZone"
<*> getT "groupName"
<*> getT "tenancy"
)
<*> getMT "kernelId"
<*> getMT "ramdiskId"
<*> getMT "platform"
<*> element "monitoring" (getF "state" instanceMonitoringState)
<*> getMT "subnetId"
<*> getMT "vpcId"
<*> getMT "privateIpAddress"
<*> getMT "ipAddress"
<*> getM "sourceDestCheck" (textToBool <$>)
<*> groupSetSink
<*> stateReasonSink
<*> getF "architecture" architecture
<*> getF "rootDeviceType" rootDeviceType
<*> getMT "rootDeviceName"
<*> itemsSet "blockDeviceMapping" (
instanceBlockDeviceMapping
<$> getT "deviceName"
<*> element "ebs" (
instanceEbsBlockDevice
<$> getT "volumeId"
<*> getF "status" attachmentStatus
<*> getF "attachTime" textToTime
<*> getF "deleteOnTermination" textToBool
)
)
<*> getM "instanceLifecycle" instanceLifecycle
<*> getMT "spotInstanceRequestId"
<*> getF "virtualizationType" virtualizationType
<*> getT "clientToken"
<*> resourceTagSink
<*> getF "hypervisor" hypervisor
<*> networkInterfaceSink
<*> elementM "iamInstanceProfile" (
iamInstanceProfile
<$> getT "arn"
<*> getT "id"
)
<*> getF "ebsOptimized" textToBool
instanceStateSink :: MonadThrow m
=> Text -> GLSink Event m InstanceState
instanceStateSink label = element label $
codeToState
<$> getF "code" textToInt
<* getT "name"
networkInterfaceSink :: MonadThrow m
=> GLSink Event m [InstanceNetworkInterface]
networkInterfaceSink = itemsSet "networkInterfaceSet" $
instanceNetworkInterface
<$> getT "networkInterfaceId"
<*> getT "subnetId"
<*> getT "vpcId"
<*> getM "description" orEmpty
<*> getT "ownerId"
<*> getT "status"
<*> getT "privateIpAddress"
<*> getMT "privateDnsName"
<*> getF "sourceDestCheck" textToBool
<*> groupSetSink
<*> element "attachment" (
networkInterfaceAttachment
<$> getT "attachmentId"
<*> getF "deviceIndex" textToInt
<*> getT "status"
<*> getF "attachTime" textToTime
<*> getF "deleteOnTermination" textToBool
)
<*> niAssociationSink
<*> itemsSet "privateIpAddressesSet" (
instancePrivateIpAddress
<$> getT "privateIpAddress"
<*> getF "primary" textToBool
<*> niAssociationSink
)
niAssociationSink :: MonadThrow m
=> GLSink Event m (Maybe NetworkInterfaceAssociation)
niAssociationSink = elementM "association" $
networkInterfaceAssociation
<$> getT "publicIp"
<*> getT "ipOwnerId"
describeInstanceStatus
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> Bool
-> [Filter]
-> Maybe Text
-> EC2 m (Source m InstanceStatus)
describeInstanceStatus instanceIds isAll filters token =
ec2QuerySource' "DescribeInstanceStatus" params token instanceStatusSet
where
params =
[ ArrayParams "InstanceId" instanceIds
, ValueParam "IncludeAllInstances" $ boolToText isAll
, FilterParams filters
]
instanceStatusSet :: MonadThrow m
=> GLConduit Event m InstanceStatus
instanceStatusSet = do
itemConduit "instanceStatusSet" $
instanceStatus
<$> getT "instanceId"
<*> getT "availabilityZone"
<*> itemsSet "eventsSet" (
instanceStatusEvent
<$> getF "code" instanceStatusEventCode
<*> getT "description"
<*> getM "notBefore" (textToTime <$>)
<*> getM "notAfter" (textToTime <$>)
)
<*> instanceStateSink "instanceState"
<*> instanceStatusTypeSink "systemStatus"
<*> instanceStatusTypeSink "instanceStatus"
instanceStatusTypeSink :: MonadThrow m
=> Text -> GLSink Event m InstanceStatusType
instanceStatusTypeSink name = element name $
instanceStatusType
<$> getF "status" instanceStatusTypeStatus
<*> itemsSet "details" (
instanceStatusDetail
<$> getT "name"
<*> getT "status"
<*> getM "impairedSince" (textToTime <$>)
)
startInstances
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> EC2 m (Source m InstanceStateChange)
startInstances instanceIds =
ec2QuerySource "StartInstances" params instanceStateChangeSet
where
params = [ArrayParams "InstanceId" instanceIds]
instanceStateChangeSet
:: (MonadResource m, MonadBaseControl IO m)
=> Conduit Event m InstanceStateChange
instanceStateChangeSet = itemConduit "instancesSet" $ do
instanceStateChange
<$> getT "instanceId"
<*> instanceStateSink "currentState"
<*> instanceStateSink "previousState"
stopInstances
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> Bool
-> EC2 m (Source m InstanceStateChange)
stopInstances instanceIds force =
ec2QuerySource "StopInstances" params instanceStateChangeSet
where
params =
[ ArrayParams "InstanceId" instanceIds
, ValueParam "Force" $ boolToText force]
rebootInstances
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> EC2 m Bool
rebootInstances instanceIds =
ec2Query "RebootInstances" params $ getF "return" textToBool
where
params = [ArrayParams "InstanceId" instanceIds]
terminateInstances
:: (MonadResource m, MonadBaseControl IO m)
=> [Text]
-> EC2 m (Source m InstanceStateChange)
terminateInstances instanceIds =
ec2QuerySource "TerminateInstances" params
instanceStateChangeSet
where
params = [ArrayParams "InstanceId" instanceIds]
runInstances
:: (MonadResource m, MonadBaseControl IO m)
=> RunInstancesParam
-> EC2 m Reservation
runInstances param =
ec2Query "RunInstances" params reservationSink
where
mk name = maybe [] (\a -> [ValueParam name a])
params =
[ ValueParam "ImageId" $ riImageId param
, ValueParam "MinCount" $ toText $ riMinCount param
, ValueParam "MaxCount" $ toText $ riMaxCount param
, ArrayParams "SecurityGroupId" $ riSecurityGroupIds param
, ArrayParams "SecurityGroup" $ riSecurityGroups param
, blockDeviceMappingParams $ riBlockDeviceMappings param
] ++ (uncurry mk =<<
[ ("KeyName", riKeyName param) , ("UserData", bsToText <$> riUserData param)
, ("InstanceType", riInstanceType param)
, ("Placement.AvailabilityZone",
riAvailabilityZone param)
, ("Placement.GroupName", riPlacementGroup param)
, ("Placement.Tenancy", riTenancy param)
, ("KernelId", riKernelId param)
, ("RamdiskId", riRamdiskId param)
, ("Monitoring.Enabled",
boolToText <$> riMonitoringEnabled param)
, ("SubnetId", riSubnetId param)
, ("DisableApiTermination",
boolToText <$> riDisableApiTermination param)
, ("InstanceInitiatedShutdownBehavior",
sbToText <$> riShutdownBehavior param)
, ("ClientToken", riClientToken param)
, ("IamInstanceProfile.Arn",
iipArn <$> riIamInstanceProfile param)
, ("IamInstanceProfile.Name",
iipId <$> riIamInstanceProfile param)
, ("EbsOptimized", boolToText <$> riEbsOptimized param)
])
data RunInstancesParam = RunInstancesParam
{ riImageId :: Text
, riMinCount :: Int
, riMaxCount :: Int
, riKeyName :: Maybe Text
, riSecurityGroupIds :: [Text]
, riSecurityGroups :: [Text]
, riUserData :: Maybe ByteString
, riInstanceType :: Maybe Text
, riAvailabilityZone :: Maybe Text
, riPlacementGroup :: Maybe Text
, riTenancy :: Maybe Text
, riKernelId :: Maybe Text
, riRamdiskId :: Maybe Text
, riBlockDeviceMappings :: [BlockDeviceMappingParam]
, riMonitoringEnabled :: Maybe Bool
, riSubnetId :: Maybe Text
, riDisableApiTermination :: Maybe Bool
, riShutdownBehavior :: Maybe ShutdownBehavior
, riPrivateIpAddresses :: [Text]
, riClientToken :: Maybe Text
, riNetworkInterface :: [NetworkInterfaceParam]
, riIamInstanceProfile :: Maybe IamInstanceProfile
, riEbsOptimized :: Maybe Bool
}
deriving (Show)
defaultRunInstancesParam
:: Text
-> Int
-> Int
-> RunInstancesParam
defaultRunInstancesParam iid minCount maxCount = RunInstancesParam
{ riImageId = iid
, riMinCount = minCount
, riMaxCount = maxCount
, riKeyName = Nothing
, riSecurityGroupIds = []
, riSecurityGroups = []
, riUserData = Nothing
, riInstanceType = Nothing
, riAvailabilityZone = Nothing
, riPlacementGroup = Nothing
, riTenancy = Nothing
, riKernelId = Nothing
, riRamdiskId = Nothing
, riBlockDeviceMappings = []
, riMonitoringEnabled = Nothing
, riSubnetId = Nothing
, riDisableApiTermination = Nothing
, riShutdownBehavior = Nothing
, riPrivateIpAddresses = []
, riClientToken = Nothing
, riNetworkInterface = []
, riIamInstanceProfile = Nothing
, riEbsOptimized = Nothing
}
sbToText :: ShutdownBehavior -> Text
sbToText SBStop = "stop"
sbToText SBTerminate = "terminate"
getConsoleOutput
:: (MonadResource m, MonadBaseControl IO m)
=> Text
-> EC2 m ConsoleOutput
getConsoleOutput iid =
ec2Query "GetConsoleOutput" [ValueParam "InstanceId" iid] $
consoleOutput
<$> getT "instanceId"
<*> getF "timestamp" textToTime
<*> getT "output"
getPasswordData
:: (MonadResource m, MonadBaseControl IO m)
=> Text
-> EC2 m PasswordData
getPasswordData iid =
ec2Query "GetPasswordData" [ValueParam "InstanceId" iid] $
passwordData
<$> getT "instanceId"
<*> getF "timestamp" textToTime
<*> getT "passwordData"