groot-0.0.1.0: src/Groot/CLI/Cluster/Inspect.hs
{-# LANGUAGE OverloadedStrings #-}
module Groot.CLI.Cluster.Inspect
( ClusterInspectOpts
, clusterInspectOpts
, runClusterInspect
) where
import Control.Lens
import Control.Monad.IO.Class
import Control.Monad.Trans.Reader
import Data.Conduit
import qualified Data.Conduit.List as CL
import qualified Data.HashMap.Lazy as Map
import Data.Maybe
import Data.Monoid
import Data.String
import Data.Text (Text)
import Network.AWS
import qualified Network.AWS.EC2 as EC2
import qualified Network.AWS.ECS as ECS
import Options.Applicative (Parser)
import qualified Options.Applicative as Opts
import Groot.Core
import Groot.Internal.PrettyPrint (Doc, defaultIndent, (<+>))
import qualified Groot.Internal.PrettyPrint as Doc
import Groot.Types
data InspectFlag =
ShowInstanceAttrs
deriving (Eq, Show)
showInstanceAttrsOpt :: Parser InspectFlag
showInstanceAttrsOpt = Opts.flag' ShowInstanceAttrs
( Opts.long "show-instance-attrs"
<> Opts.help "displays instance attributes" )
inspectFlagOpts :: Parser [InspectFlag]
inspectFlagOpts = Opts.many showInstanceAttrsOpt
data ClusterInspectOpts = ClusterInspectOpts ClusterRef [InspectFlag]
deriving (Eq, Show)
clusterInspectOpts :: Parser ClusterInspectOpts
clusterInspectOpts = ClusterInspectOpts
<$> clusterRefArg
<*> inspectFlagOpts
clusterRefArg :: Parser ClusterRef
clusterRefArg = fromString <$> Opts.argument Opts.str (Opts.metavar "CLUSTER_NAME")
pprintCluster :: ECS.Cluster -> [(ECS.ContainerInstance, Maybe EC2.Instance)] -> [InspectFlag] -> Doc
pprintCluster cluster nodes flags = Doc.vsep [
Doc.bold . Doc.dullblue $ maybe mempty Doc.pretty $ cluster ^. ECS.cClusterName
, Doc.indent defaultIndent (Doc.vsep $ catMaybes [
Doc.field Doc.status "Status:" <$> cluster ^. ECS.cStatus
, Doc.field' "Active Services:" <$> cluster ^. ECS.cActiveServicesCount
, Doc.field' "Running Tasks:" <$> cluster ^. ECS.cRunningTasksCount
, Doc.field' "Pending Tasks:" <$> cluster ^. ECS.cPendingTasksCount
, Doc.listField ppInstance "Nodes:" nodes
])
]
where showInstanceAttrs = elem ShowInstanceAttrs flags
ppInstance :: (ECS.ContainerInstance, Maybe EC2.Instance) -> Doc
ppInstance (ecsInst, ec2Inst) = Doc.vsep [
Doc.bold . Doc.dullblue $ maybe mempty Doc.pretty $ ecsInst ^. ECS.ciEc2InstanceId
, Doc.indent defaultIndent (Doc.vsep $ catMaybes [
Doc.field Doc.status "Status:" <$> ecsInst ^. ECS.ciStatus
, Doc.field' "Connected:" <$> ecsInst ^. ECS.ciAgentConnected
, Doc.field' "Private IP:" <$> (ec2Inst >>= view EC2.insPrivateIPAddress)
, Doc.field' "Running Tasks:" <$> ecsInst ^. ECS.ciRunningTasksCount
, Doc.field' "Pending Tasks:" <$> ecsInst ^. ECS.ciPendingTasksCount
, Doc.field Doc.defaultTime "Registered At:" <$> ecsInst ^. ECS.ciRegisteredAt
, if showInstanceAttrs then Doc.listField ppInstanceAttr "Attributes:" $ ecsInst ^. ECS.ciAttributes
else Nothing
])
]
ppInstanceAttr :: ECS.Attribute -> Doc
ppInstanceAttr attr = Doc.hsep $ catMaybes [
Just (Doc.bold . Doc.dullblue . Doc.pretty $ attr ^. ECS.aName)
, (\x -> Doc.pretty ("=" :: Text) <+> Doc.pretty x) <$> attr ^. ECS.aValue
]
runClusterInspect :: ClusterInspectOpts -> GrootM IO ()
runClusterInspect (ClusterInspectOpts clusterRef flags) = do
env <- ask
(cluster, nodes) <- runResourceT . runAWS env $ do
clus <- getCluster clusterRef
fromCluster <- runConduit $ fetchInstances clusterRef =$ CL.consume
ids <- pure $ fmap EC2InstanceId $ catMaybes $ (view ECS.ciEc2InstanceId) <$> fromCluster
fromEc2 <- runConduit $ findEc2Instances ids =$ CL.consume
return (clus, pairInstances fromCluster fromEc2)
liftIO . Doc.putDoc $ pprintCluster cluster nodes flags
where pairInstances :: [ECS.ContainerInstance] -> [EC2.Instance] -> [(ECS.ContainerInstance, Maybe EC2.Instance)]
pairInstances ecsInsts ec2Insts =
let ec2InstanceMap = Map.fromList $ (\x -> (x ^. EC2.insInstanceId, x)) <$> ec2Insts
in fmap (\x -> (x, (flip Map.lookup) ec2InstanceMap =<< (x ^. ECS.ciEc2InstanceId))) ecsInsts