module Stackctl.Spec.Generate ( Generate (..) , GenerateSpec (..) , GenerateTemplate (..) , generate , TemplateFormat (..) ) where import Stackctl.Prelude import Stackctl.AWS import Stackctl.AWS.Scope import Stackctl.Action import Stackctl.Config (HasConfig) import Stackctl.DirectoryOption import Stackctl.Spec.Discover (buildSpecPath) import Stackctl.StackSpec import Stackctl.StackSpecPath import Stackctl.StackSpecYaml data Generate = Generate { gDescription :: Maybe StackDescription , gDepends :: Maybe [StackName] , gActions :: Maybe [Action] , gParameters :: Maybe [Parameter] , gCapabilities :: Maybe [Capability] , gTags :: Maybe [Tag] , gSpec :: GenerateSpec , gTemplate :: GenerateTemplate , gOverwrite :: Bool } data GenerateSpec = -- | Generate at an inferred name GenerateSpec StackName | -- | Generate to a given path GenerateSpecTo StackName FilePath data GenerateTemplate = -- | Generate at an inferred name GenerateTemplate TemplateBody TemplateFormat | -- | Generate to the given path GenerateTemplateTo TemplateBody FilePath | -- | Assume template exists UseExistingTemplate FilePath data TemplateFormat = TemplateFormatYaml | TemplateFormatJson generate :: ( MonadMask m , MonadUnliftIO m , MonadLogger m , MonadReader env m , HasConfig env , HasAwsScope env , HasDirectoryOption env ) => Generate -> m FilePath generate Generate {..} = do let (stackName, stackPath) = case gSpec of GenerateSpec name -> (name, unpack (unStackName name) <> ".yaml") GenerateSpecTo name path -> (name, path) (mTemplateBody, templatePath) = case gTemplate of GenerateTemplate body format -> ( Just body , case format of TemplateFormatYaml -> unpack (unStackName stackName) <> ".yaml" TemplateFormatJson -> unpack (unStackName stackName) <> ".json" ) GenerateTemplateTo body path -> (Just body, path) UseExistingTemplate path -> (Nothing, path) specYaml = StackSpecYaml { ssyDescription = gDescription , ssyTemplate = templatePath , ssyDepends = gDepends , ssyActions = gActions , ssyParameters = parametersYaml . mapMaybe parameterYaml <$> gParameters , ssyCapabilities = gCapabilities , ssyTags = tagsYaml . map TagYaml <$> gTags } dir <- view $ directoryOptionL . to unDirectoryOption specPath <- buildSpecPath stackName stackPath stackSpec <- buildStackSpec dir specPath specYaml withThreadContext ["stackName" .= stackSpecStackName stackSpec] $ do writeStackSpec gOverwrite stackSpec mTemplateBody pure $ stackSpecPathFilePath specPath