stackctl-1.4.2.2: src/Stackctl/Spec/Capture.hs
module Stackctl.Spec.Capture
( CaptureOptions (..)
, parseCaptureOptions
, runCapture
) where
import Stackctl.Prelude
import Options.Applicative
import Stackctl.AWS
import Stackctl.AWS.Scope
import Stackctl.Config (HasConfig)
import Stackctl.DirectoryOption (HasDirectoryOption)
import Stackctl.Spec.Generate
import Stackctl.StackSpec
import System.FilePath.Glob
data CaptureOptions = CaptureOptions
{ scoAccountName :: Maybe Text
, scoTemplatePath :: Maybe FilePath
, scoStackPath :: Maybe FilePath
, scoDepends :: Maybe [StackName]
, scoTemplateFormat :: TemplateFormat
, scoStackName :: Pattern
}
-- brittany-disable-next-binding
parseCaptureOptions :: Parser CaptureOptions
parseCaptureOptions =
CaptureOptions
<$> optional
( strOption
( short 'n'
<> long "account-name"
<> metavar "NAME"
<> help "Account name to use in generated files"
)
)
<*> optional
( strOption
( short 't'
<> long "template-path"
<> metavar "PATH"
<> help "Write Template to PATH. Default is based on STACK"
)
)
<*> optional
( strOption
( short 'p'
<> long "path"
<> metavar "PATH"
<> help "Write specification to PATH. Default is based on STACK"
)
)
<*> optional
( some
( StackName
<$> strOption
( long "depend"
<> metavar "STACK"
<> help "Add a dependency on STACK"
)
)
)
<*> flag
TemplateFormatYaml
TemplateFormatJson
( long "no-flip"
<> help "Don't flip JSON templates to Yaml"
)
<*> strArgument
( metavar "STACK"
<> help "Name of deployed Stack to capture"
)
runCapture
:: ( MonadMask m
, MonadUnliftIO m
, MonadResource m
, MonadLogger m
, MonadReader env m
, HasAwsScope env
, HasAwsEnv env
, HasConfig env
, HasDirectoryOption env
)
=> CaptureOptions
-> m ()
runCapture CaptureOptions {..} = do
let
setScopeName scope =
maybe scope (\name -> scope {awsAccountName = name}) scoAccountName
generate' stack template path templatePath = do
let
stackName = StackName $ stack ^. stack_stackName
templateBody = templateBodyFromValue template
void
$ local (awsScopeL %~ setScopeName)
$ generate
Generate
{ gDescription = stackDescription stack
, gDepends = scoDepends
, gActions = Nothing
, gParameters = parameters stack
, gCapabilities = capabilities stack
, gTags = tags stack
, gSpec = case path of
Nothing -> GenerateSpec stackName
Just sp -> GenerateSpecTo stackName sp
, gTemplate = case templatePath of
Nothing -> GenerateTemplate templateBody scoTemplateFormat
Just tp -> GenerateTemplateTo templateBody tp
, gOverwrite = False
}
results <- awsCloudFormationGetStackNamesMatching scoStackName
case results of
[] -> do
logError
$ "No Active Stacks match "
<> pack (decompile scoStackName)
:# []
exitFailure
[stackName] -> do
stack <- awsCloudFormationDescribeStack stackName
template <- awsCloudFormationGetTemplate stackName
generate' stack template scoStackPath scoTemplatePath
stackNames -> do
logInfo "Capturing multiple matching Stacks"
for_ scoStackPath $ \_ -> logWarn "--path option ignored"
for_ scoTemplatePath $ \_ -> logWarn "--template-path option ignored"
for_ stackNames $ \stackName -> do
stack <- awsCloudFormationDescribeStack stackName
template <- awsCloudFormationGetTemplate stackName
generate' stack template Nothing Nothing