{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Kerry.Builder.AmazonEC2 (
Credentials(..)
, AWS(..)
, fromAWS
, SourceAmi(..)
, AWSAmiOwner(..)
, SourceAmiFilterKey(..)
, BlockDeviceMapping(..)
, blockDeviceMapping
, EBS(..)
, ebs
, fromEBS
) where
import Data.Aeson ((.=))
import qualified Data.Aeson as Aeson
import qualified Data.Aeson.Types as Aeson
import qualified Data.Map as Map
import Kerry.Internal.Prelude
import Kerry.Internal.Serial
data Credentials =
AWSProfile Text
| EnvironmentVariables
deriving (Eq, Ord, Show)
data AWS x =
AWS {
awsRegion :: Text
, awsCredentials :: Credentials
, awsBuilder :: x
} deriving (Eq, Ord, Show)
fromAWS :: (a -> [Aeson.Pair]) -> AWS a -> [Aeson.Pair]
fromAWS fromBuilder (AWS region creds builder) =
join [
["region" .= region]
, case creds of
AWSProfile profile ->
["profile" .= profile]
EnvironmentVariables ->
[]
, fromBuilder builder
]
data SourceAmi =
SourceAmiId Text
| SourceAmiFilter (Map SourceAmiFilterKey Text) AWSAmiOwner Bool
deriving (Eq, Ord, Show)
data AWSAmiOwner =
Accounts [Text]
| Self
| Alias Text
deriving (Eq, Ord, Show)
data SourceAmiFilterKey =
Architecture
| BlockDeviceMappingDeleteOnTermination
| BlockDeviceMappingDeviceName
| BlockDeviceMappingSnapshotId
| BlockDeviceMappingVolumeSize
| BlockDeviceMappingVolumeType
| BlockDevice
| Description
| EnaSupport
| Hypervisor
| ImageId
| ImageType
| IsPublic
| KernelId
| ManifestLocation
| Name
| OwnerAlias
| OwnerId
| Platform
| ProductCode
| ProductCodeType
| RamdiskId
| RootDeviceName
| RootDeviceType
| State
| StateReasonCode
| StateReasonMessage
| SriovNetSupport
| Tag Text
| TagKey
| VirtualizationType
deriving (Eq, Ord, Show)
renderSourceAmiFilterKey :: SourceAmiFilterKey -> Text
renderSourceAmiFilterKey = \case
Architecture ->
"architecture"
BlockDeviceMappingDeleteOnTermination ->
"block-device-mapping.delete-on-termination"
BlockDeviceMappingDeviceName ->
"block-device-mapping.device-name"
BlockDeviceMappingSnapshotId ->
"block-device-mapping.snapshot-id"
BlockDeviceMappingVolumeSize ->
"block-device-mapping.volume-size"
BlockDeviceMappingVolumeType ->
"block-device-mapping.volume-type"
BlockDevice ->
"block-device-mapping.encrypted"
Description ->
"description"
EnaSupport ->
"ena-support"
Hypervisor ->
"hypervisor"
ImageId ->
"image-id"
ImageType ->
"image-type"
IsPublic ->
"is-public"
KernelId ->
"kernel-id"
ManifestLocation ->
"manifest-location"
Name ->
"name"
OwnerAlias ->
"owner-alias"
OwnerId ->
"owner-id"
Platform ->
"platform"
ProductCode ->
"product-code"
ProductCodeType ->
"product-code.type"
RamdiskId ->
"ramdisk-id"
RootDeviceName ->
"root-device-name"
RootDeviceType ->
"root-device-type"
State ->
"state"
StateReasonCode ->
"state-reason-code"
StateReasonMessage ->
"state-reason-message"
SriovNetSupport ->
"sriov-net-support"
Tag key ->
"tag:" <> key
TagKey ->
"tag-key"
VirtualizationType ->
"virtualization-type"
data BlockDeviceMapping =
BlockDeviceMapping {
blockDeviceMappingName :: Text
, blockDeviceMappingVolumeType :: Text
, blockDeviceMappingIOPS :: Maybe Int
, blockDeviceMappingVolumeSize :: Int
, blockDeviceMappingDeleteOnTermination :: Bool
, blockDeviceMappingEncrypted :: Bool
, blockDeviceMappingKMS :: Maybe Text
, blockDeviceMappingSnapshotId :: Maybe Text
, blockDeviceMappingVirtualName :: Maybe Text
, blockDeviceMappingNoDevice :: Maybe Bool
} deriving (Eq, Ord, Show)
blockDeviceMapping :: Text -> Text -> Int -> Bool -> BlockDeviceMapping
blockDeviceMapping name vtype vsize delete =
BlockDeviceMapping {
blockDeviceMappingName = name
, blockDeviceMappingVolumeType = vtype
, blockDeviceMappingIOPS = Nothing
, blockDeviceMappingVolumeSize = vsize
, blockDeviceMappingDeleteOnTermination = delete
, blockDeviceMappingEncrypted = False
, blockDeviceMappingKMS = Nothing
, blockDeviceMappingSnapshotId = Nothing
, blockDeviceMappingVirtualName = Nothing
, blockDeviceMappingNoDevice = Nothing
}
data EBS =
EBS {
ebsAmiName :: Text
, ebsSourceAmi :: SourceAmi
, ebsInstanceType :: Text
, ebsAmiDescription :: Maybe Text
, ebsAmiRegions :: Maybe [Text]
, ebsAmiUsers :: Maybe [Text]
, ebsAssociatePublicIpAddress :: Maybe Bool
, ebsAvailabilityZone :: Maybe Text
, ebsIAMInstanceProfile :: Maybe Text
, ebsInsecureSkipTLSVerify :: Maybe Bool
, ebsLaunchBlockDeviceMappings :: [BlockDeviceMapping]
, ebsRunTags :: Map Text Text
, ebsSubnetId :: Maybe Text
, ebsTags :: Map Text Text
, ebsVpcId :: Maybe Text
} deriving (Eq, Ord, Show)
ebs :: Text -> SourceAmi -> Text -> EBS
ebs name sourceami instancetype =
EBS {
ebsAmiName = name
, ebsSourceAmi = sourceami
, ebsInstanceType = instancetype
, ebsAmiDescription = Nothing
, ebsAmiRegions = Nothing
, ebsAmiUsers = Nothing
, ebsAssociatePublicIpAddress = Nothing
, ebsAvailabilityZone = Nothing
, ebsIAMInstanceProfile = Nothing
, ebsInsecureSkipTLSVerify = Nothing
, ebsLaunchBlockDeviceMappings = []
, ebsRunTags = mempty
, ebsSubnetId = Nothing
, ebsTags = mempty
, ebsVpcId = Nothing
}
fromEBS :: EBS -> [Aeson.Pair]
fromEBS e = join [
["type" .= t "amazon-ebs"]
, ["ami_name" .= ebsAmiName e]
, [fromSourceAmi $ ebsSourceAmi e]
, ["instance_type" .= ebsInstanceType e]
, "ami_description" .=? ebsAmiDescription e
, "ami_regions" .=? ebsAmiRegions e
, "ami_users" .=? ebsAmiUsers e
, "associate_public_ip_address" .=? ebsAssociatePublicIpAddress e
, "availability_zone" .=? ebsAvailabilityZone e
, "iam_instance_profile" .=? ebsIAMInstanceProfile e
, "insecure_skip_tls_verify" .=? ebsInsecureSkipTLSVerify e
, "launch_block_device_mappings" .=? list (fromBlockDeviceMapping <$> ebsLaunchBlockDeviceMappings e)
, ["run_tags" .= fromMap (ebsRunTags e)]
, "subnet_id" .=? ebsSubnetId e
, ["tags" .= fromMap (ebsTags e)]
, "vpc_id" .=? ebsVpcId e
]
fromSourceAmi :: SourceAmi -> Aeson.Pair
fromSourceAmi = \case
SourceAmiId x ->
"source_ami" .= x
SourceAmiFilter filters owner recent ->
"source_ami_filter" .= Aeson.object [
"filters" .= fromMap (Map.mapKeys renderSourceAmiFilterKey filters)
, "owners" .= case owner of
Accounts as ->
Aeson.toJSON as
Self ->
Aeson.String "self"
Alias a ->
Aeson.String a
, "most_recent" .= recent
]
fromBlockDeviceMapping :: BlockDeviceMapping -> Aeson.Value
fromBlockDeviceMapping b =
Aeson.object $ join [[
"device_name" .= blockDeviceMappingName b
, "volume_type" .= blockDeviceMappingVolumeType b
, "volume_size" .= blockDeviceMappingVolumeSize b
, "delete_on_termination" .= blockDeviceMappingDeleteOnTermination b
, "encrypted" .= blockDeviceMappingEncrypted b
]
, "iops" .=? blockDeviceMappingIOPS b
, "kms_key_id" .=? blockDeviceMappingKMS b
, "snapshot_id" .=? blockDeviceMappingSnapshotId b
, "virtual_name" .=? blockDeviceMappingVirtualName b
, "no_device" .=? blockDeviceMappingNoDevice b
]