Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: add AWS EC2 instance memory and storage size #27

Merged
merged 1 commit into from
May 3, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/Clompse/Programs/ListServers.hs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ listServersForCloudConnection (CloudConnectionAws conn) = do
serversLightsail <- case eServersLightsail of
Left e -> _log (" ERROR (AWS Lightsail): " <> Z.Text.tshow e) >> pure []
Right servers -> pure servers
pure (fmap (uncurry Providers.ec2InstanceToServer) serversEc2 <> fmap (uncurry Providers.lightsailInstanceToServer) serversLightsail)
pure (fmap Providers.ec2InstanceToServer serversEc2 <> fmap (uncurry Providers.lightsailInstanceToServer) serversLightsail)
listServersForCloudConnection (CloudConnectionDo conn) = do
eServers <- runExceptT (Providers.Do.doListDroplets conn)
case eServers of
Expand Down
95 changes: 69 additions & 26 deletions src/Clompse/Providers/Aws.hs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@ import qualified Amazonka.Auth as Aws.Auth
import qualified Amazonka.Data as Aws.Data
import qualified Amazonka.Data.Time as Aws.Data.Time
import qualified Amazonka.EC2 as Aws.Ec2
import qualified Amazonka.EC2.DescribeInstanceTypes as Aws.Ec2.DescribeInstanceTypes
import qualified Amazonka.EC2.Lens as Aws.Ec2.Lens
import qualified Amazonka.EC2.Types as Aws.Ec2.Types
import qualified Amazonka.EC2.Types.CpuOptions as Aws.Ec2.Types.CpuOptions
import qualified Amazonka.EC2.Types.InstanceTypeInfo as Aws.Ec2.Types.InstanceTypeInfo
import qualified Amazonka.Lightsail as Aws.Lightsail
import qualified Amazonka.Lightsail.Lens as Aws.Lightsail.Lens
import qualified Amazonka.Lightsail.Types as Aws.Lightsail.Types
Expand All @@ -25,14 +26,16 @@ import qualified Clompse.Types as Types
import Conduit ((.|))
import qualified Control.Concurrent.Async.Pool as Async
import qualified Control.Lens as L
import Control.Monad (join)
import Control.Monad.Except (MonadError (throwError), runExceptT)
import Control.Monad.IO.Class (MonadIO (liftIO))
import qualified Data.Aeson as Aeson
import qualified Data.Conduit as C
import qualified Data.Conduit.List as CL
import qualified Data.HashMap.Strict as HM
import Data.Int (Int16, Int32)
import qualified Data.List as L
import Data.Maybe (catMaybes, fromMaybe, mapMaybe, maybeToList)
import Data.Maybe (fromMaybe, mapMaybe, maybeToList)
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import GHC.Float (double2Int)
Expand Down Expand Up @@ -120,11 +123,17 @@ _ec2RegionInfoToRegion i =
-- *** Instances


type Ec2InstanceList = [Ec2InstanceListItem]


type Ec2InstanceListItem = (Aws.Region, Aws.Ec2.Instance, Maybe Int, Maybe Integer, Maybe Integer)


awsEc2ListAllInstances
:: MonadIO m
=> MonadError AwsError m
=> AwsConnection
-> m [(Aws.Region, Aws.Ec2.Instance)]
-> m Ec2InstanceList
awsEc2ListAllInstances cfg = do
regions <- awsEc2ListAllRegions cfg
res <- liftIO . Async.withTaskGroup 4 $ \tg -> Async.mapTasks tg (fmap (runExceptT . awsEc2ListAllInstancesForRegion cfg) regions)
Expand All @@ -138,15 +147,51 @@ awsEc2ListAllInstancesForRegion
=> MonadError AwsError m
=> AwsConnection
-> Aws.Region
-> m [(Aws.Region, Aws.Ec2.Instance)]
-> m Ec2InstanceList
awsEc2ListAllInstancesForRegion cfg reg = do
env <- (\x -> x {Aws.region = reg}) <$> _envFromConnection cfg
let prog =
Aws.paginate env Aws.Ec2.newDescribeInstances
.| CL.concatMap (L.view $ Aws.Ec2.Lens.describeInstancesResponse_reservations . L._Just)
.| CL.concatMap (L.view $ Aws.Ec2.Lens.reservation_instances . L._Just)
.| CL.consume
fmap (fmap (reg,)) . liftIO . Aws.runResourceT . C.runConduit $ prog
resIs <- liftIO . Aws.runResourceT . C.runConduit $ prog
let instanceTypes = fmap (L.view Aws.Ec2.Lens.instance_instanceType) resIs
resTs <- awsEc2InstanceTypeHw cfg reg instanceTypes
pure $ fmap (mkItem resTs) resIs
where
mkItem resTs i = do
let it = i L.^. Aws.Ec2.Lens.instance_instanceType
case HM.lookup it resTs of
Nothing -> (reg, i, Nothing, Nothing, Nothing)
Just (cpu, ram, disk) -> (reg, i, cpu, ram, disk)


awsEc2InstanceTypeHw
:: MonadIO m
=> MonadError AwsError m
=> AwsConnection
-> Aws.Region
-> [Aws.Ec2.InstanceType]
-> m (HM.HashMap Aws.Ec2.InstanceType (Maybe Int, Maybe Integer, Maybe Integer))
awsEc2InstanceTypeHw cfg reg its = do
env <- (\x -> x {Aws.region = reg}) <$> _envFromConnection cfg
let prog =
Aws.paginate env (Aws.Ec2.newDescribeInstanceTypes L.& Aws.Ec2.DescribeInstanceTypes.describeInstanceTypes_instanceTypes L.?~ its)
.| CL.concatMap (L.view $ Aws.Ec2.Lens.describeInstanceTypesResponse_instanceTypes . L._Just)
.| CL.consume
resTs <- liftIO . Aws.runResourceT . C.runConduit $ prog
pure $ HM.fromList (mapMaybe mkRes resTs)
where
mkRes :: Aws.Ec2.InstanceTypeInfo -> Maybe (Aws.Ec2.InstanceType, (Maybe Int, Maybe Integer, Maybe Integer))
mkRes [email protected]' {..} =
case instanceType of
Nothing -> Nothing
Just it ->
let cpu = join $ i L.^? Aws.Ec2.Lens.instanceTypeInfo_vCpuInfo L.^? L._Just . L._Just . Aws.Ec2.Lens.vCpuInfo_defaultVCpus
ram = join $ i L.^? Aws.Ec2.Lens.instanceTypeInfo_memoryInfo L.^? L._Just . L._Just . Aws.Ec2.Lens.memoryInfo_sizeInMiB
disk = join $ i L.^? Aws.Ec2.Lens.instanceTypeInfo_instanceStorageInfo L.^? L._Just . L._Just . Aws.Ec2.Lens.instanceStorageInfo_totalSizeInGB
in Just (it, (cpu, ram, disk))


-- *** Security Groups
Expand Down Expand Up @@ -177,23 +222,21 @@ awsEc2ListAllSecurityGroupsForRegion cfg reg = do
liftIO . Aws.runResourceT . C.runConduit $ prog


-- *** Instances with Security Groups


awsEc2ListAllInstancesWithSecurityGroups
:: MonadIO m
=> MonadError AwsError m
=> AwsConnection
-> m [(Aws.Region, Aws.Ec2.Instance, [Aws.Ec2.SecurityGroup])]
awsEc2ListAllInstancesWithSecurityGroups cfg = do
instancesWithRegions <- awsEc2ListAllInstances cfg
securityGroups <- awsEc2ListAllSecurityGroups cfg
pure (fmap (\(r, i) -> (r, i, findSecurityGroups securityGroups i)) instancesWithRegions)
where
findSecurityGroups sgs i =
let sids = catMaybes $ foldMap (fmap (L.^. Aws.Ec2.Lens.groupIdentifier_groupId)) (i L.^. Aws.Ec2.Lens.instance_securityGroups)
in concatMap (\gi -> filter (\sg -> sg L.^. Aws.Ec2.Lens.securityGroup_groupId == gi) sgs) sids
-- -- *** Instances with Security Groups

-- awsEc2ListAllInstancesWithSecurityGroups
-- :: MonadIO m
-- => MonadError AwsError m
-- => AwsConnection
-- -> m [(Aws.Region, Aws.Ec2.Instance, [Aws.Ec2.SecurityGroup])]
-- awsEc2ListAllInstancesWithSecurityGroups cfg = do
-- instancesWithRegions <- awsEc2ListAllInstances cfg
-- securityGroups <- awsEc2ListAllSecurityGroups cfg
-- pure (fmap (\(r, i) -> (r, i, findSecurityGroups securityGroups i)) instancesWithRegions)
-- where
-- findSecurityGroups sgs i =
-- let sids = catMaybes $ foldMap (fmap (L.^. Aws.Ec2.Lens.groupIdentifier_groupId)) (i L.^. Aws.Ec2.Lens.instance_securityGroups)
-- in concatMap (\gi -> filter (\sg -> sg L.^. Aws.Ec2.Lens.securityGroup_groupId == gi) sgs) sids

-- ** AWS Lightsail

Expand Down Expand Up @@ -271,14 +314,14 @@ awsLightsailListAllInstancesForRegion cfg reg = do
-- ** EC2


ec2InstanceToServer :: Aws.Region -> Aws.Ec2.Instance -> Types.Server
ec2InstanceToServer region [email protected]' {..} =
ec2InstanceToServer :: (Aws.Region, Aws.Ec2.Instance, Maybe Int, Maybe Integer, Maybe Integer) -> Types.Server
ec2InstanceToServer (region, [email protected]' {..}, mCpu, mRam, mDisks) =
Types.Server
{ Types._serverId = instanceId
, Types._serverName = awsEc2InstanceName i
, Types._serverCpu = fromIntegral <$> (Aws.Ec2.Types.CpuOptions.coreCount =<< cpuOptions)
, Types._serverRam = Nothing
, Types._serverDisk = Nothing
, Types._serverCpu = fromIntegral <$> mCpu
, Types._serverRam = fromIntegral <$> mRam
, Types._serverDisk = fromIntegral <$> mDisks
, Types._serverState = ec2InstanceToServerState state
, Types._serverCreatedAt = Just (Aws.Data.Time.fromTime launchTime)
, Types._serverProvider = Types.ProviderAws
Expand Down