stackctl-1.6.0.0: src/Stackctl/Spec/List.hs
module Stackctl.Spec.List
( ListOptions (..)
, parseListOptions
, runList
) where
import Stackctl.Prelude
import Blammo.Logging.Logger (pushLoggerLn)
import qualified Data.Text as T
import Options.Applicative
import Stackctl.AWS
import Stackctl.AWS.Scope
import Stackctl.Colors
import Stackctl.Config (HasConfig)
import Stackctl.DirectoryOption (HasDirectoryOption (..))
import Stackctl.FilterOption (HasFilterOption)
import Stackctl.Spec.Discover
import Stackctl.StackSpec
newtype ListOptions = ListOptions
{ loLegend :: Bool
}
parseListOptions :: Parser ListOptions
parseListOptions =
ListOptions
<$> ( not
<$> switch
( mconcat
[ long "no-legend"
, help "Don't print indicators legend at the end"
]
)
)
runList
:: ( MonadUnliftIO m
, MonadMask m
, MonadAWS m
, MonadLogger m
, MonadReader env m
, HasAwsScope env
, HasLogger env
, HasConfig env
, HasDirectoryOption env
, HasFilterOption env
)
=> ListOptions
-> m ()
runList ListOptions {..} = do
colors@Colors {..} <- getColorsLogger
forEachSpec_ $ \spec -> do
let
path = stackSpecFilePath spec
name = stackSpecStackName spec
mStackStatus <-
fmap (^. stack_stackStatus)
<$> awsCloudFormationDescribeStackMaybe name
let
indicator = maybe NotDeployed statusIndicator mStackStatus
formatted :: Text
formatted =
" "
<> indicatorIcon colors indicator
<> " "
<> cyan (unStackName name)
<> " => "
<> magenta (pack path)
pushLoggerLn formatted
let legendItem i = indicatorIcon colors i <> " " <> indicatorDescription i
when loLegend
$ pushLoggerLn
$ "\nLegend:\n "
<> T.intercalate ", " (map legendItem [minBound .. maxBound])
data Indicator
= Deployed
| DeployFailed
| NotDeployed
| Reviewing
| Deploying
| Unknown
deriving stock (Bounded, Enum)
indicatorIcon :: Colors -> Indicator -> Text
indicatorIcon Colors {..} = \case
Deployed -> green "✓"
DeployFailed -> red "✗"
NotDeployed -> yellow "_"
Reviewing -> yellow "∇"
Deploying -> cyan "⋅"
Unknown -> magenta "?"
indicatorDescription :: Indicator -> Text
indicatorDescription = \case
Deployed -> "deployed"
DeployFailed -> "failed or rolled back"
NotDeployed -> "doesn't exist"
Reviewing -> "reviewing"
Deploying -> "deploying"
Unknown -> "unknown"
statusIndicator :: StackStatus -> Indicator
statusIndicator = \case
StackStatus_REVIEW_IN_PROGRESS -> Reviewing
StackStatus_ROLLBACK_COMPLETE -> DeployFailed
x | statusSuffixed "_IN_PROGRESS" x -> Deploying
x | statusSuffixed "_FAILED" x -> DeployFailed
x | statusSuffixed "_ROLLBACK_COMPLETE" x -> DeployFailed
x | statusSuffixed "_COMPLETE" x -> Deployed
_ -> Unknown
where
statusSuffixed x = (x `T.isSuffixOf`) . fromStackStatus