diff --git a/cli/commands/scaffold/action.go b/cli/commands/scaffold/action.go index 208c792e2..932a50c54 100644 --- a/cli/commands/scaffold/action.go +++ b/cli/commands/scaffold/action.go @@ -116,6 +116,11 @@ func Run(ctx context.Context, opts *options.TerragruntOptions, moduleURL, templa } }() + outputDir := opts.ScaffoldOutputFolder + if outputDir == "" { + outputDir = opts.WorkingDir + } + // scaffold only in empty directories if empty, err := util.IsDirectoryEmpty(opts.WorkingDir); !empty || err != nil { if err != nil { @@ -149,7 +154,7 @@ func Run(ctx context.Context, opts *options.TerragruntOptions, moduleURL, templa return errors.New(err) } - opts.Logger.Infof("Scaffolding a new Terragrunt module %s to %s", moduleURL, opts.WorkingDir) + opts.Logger.Infof("Scaffolding a new Terragrunt module %s to %s", moduleURL, outputDir) if _, err := getter.GetAny(ctx, tempDir, moduleURL); err != nil { return errors.New(err) @@ -188,9 +193,9 @@ func Run(ctx context.Context, opts *options.TerragruntOptions, moduleURL, templa opts.Logger.Warnf("The %s variable is already set in the var flag(s). The --%s flag will be ignored.", rootFileName, NoIncludeRootFlagName) } - opts.Logger.Infof("Running boilerplate generation to %s", opts.WorkingDir) + opts.Logger.Infof("Running boilerplate generation to %s", outputDir) boilerplateOpts := &boilerplate_options.BoilerplateOptions{ - OutputFolder: opts.WorkingDir, + OutputFolder: outputDir, OnMissingKey: boilerplate_options.DefaultMissingKeyAction, OnMissingConfig: boilerplate_options.DefaultMissingConfigAction, Vars: vars, @@ -205,7 +210,7 @@ func Run(ctx context.Context, opts *options.TerragruntOptions, moduleURL, templa return errors.New(err) } - opts.Logger.Infof("Running fmt on generated code %s", opts.WorkingDir) + opts.Logger.Infof("Running fmt on generated code %s", outputDir) if err := hclfmt.Run(opts); err != nil { return errors.New(err) diff --git a/cli/commands/scaffold/command.go b/cli/commands/scaffold/command.go index 63cc87753..033728dd0 100644 --- a/cli/commands/scaffold/command.go +++ b/cli/commands/scaffold/command.go @@ -17,6 +17,7 @@ const ( RootFileNameFlagName = "root-file-name" NoIncludeRootFlagName = "no-include-root" + OutputFolderFlagName = "output-folder" VarFlagName = "var" VarFileFlagName = "var-file" ) @@ -54,6 +55,12 @@ func NewFlags(opts *options.TerragruntOptions, prefix flags.Prefix) cli.Flags { Usage: "Do not include root unit in scaffolding done by catalog.", }), + flags.NewFlag(&cli.GenericFlag[string]{ + Name: OutputFolderFlagName, + Destination: &opts.ScaffoldOutputFolder, + Usage: "Output folder for scaffold output.", + }), + flags.NewFlag(&cli.SliceFlag[string]{ Name: VarFlagName, EnvVars: tgPrefix.EnvVars(VarFlagName), diff --git a/docs/_docs/02_features/05-catalog.md b/docs/_docs/02_features/05-catalog.md index 34bd9754f..633e4f290 100644 --- a/docs/_docs/02_features/05-catalog.md +++ b/docs/_docs/02_features/05-catalog.md @@ -16,7 +16,7 @@ Launch the user interface for searching and managing your module catalog. Example: ```bash -terragrunt catalog [--no-include-root] [--root-file-name] +terragrunt catalog [--no-include-root] [--root-file-name] [--output-folder] ``` [![screenshot](/assets/img/screenshots/catalog-screenshot.png){: width="50%" }](https://terragrunt.gruntwork.io/assets/img/screenshots/catalog-screenshot.png) @@ -52,3 +52,4 @@ The following `catalog` flags control behavior of the underlying `scaffold` comm - `--no-include-root` - Do not include the root configuration file in any generated `terragrunt.hcl` during scaffolding. - `--root-file-name` - The name of the root configuration file to include in any generated `terragrunt.hcl` during scaffolding. This value also controls the name of the root configuration file to search for when trying to determine Catalog urls. +- `--output-folder` - Location for generated `terragrunt.hcl`. If flag is not provided current working directory is selected. diff --git a/options/options.go b/options/options.go index 933053ea3..83b453a9a 100644 --- a/options/options.go +++ b/options/options.go @@ -313,6 +313,9 @@ type TerragruntOptions struct { // Name of the root Terragrunt configuration file, if used. ScaffoldRootFileName string + // Path to folder of scaffold output + ScaffoldOutputFolder string + // Root directory for graph command. GraphRoot string diff --git a/test/integration_scaffold_test.go b/test/integration_scaffold_test.go index ad5b0c5e3..69800e998 100644 --- a/test/integration_scaffold_test.go +++ b/test/integration_scaffold_test.go @@ -189,3 +189,15 @@ func TestScaffold3rdPartyModule(t *testing.T) { _, _, err = helpers.RunTerragruntCommandWithOutput(t, "terragrunt hclvalidate --terragrunt-non-interactive --terragrunt-working-dir "+tmpEnvPath) require.NoError(t, err) } + +func TestScaffoldOutputFolderFlag(t *testing.T) { + t.Parallel() + + tmpEnvPath := t.TempDir() + + outputFolder := tmpEnvPath + "/foo/bar" + _, stderr, err := helpers.RunTerragruntCommandWithOutput(t, fmt.Sprintf("terragrunt --terragrunt-non-interactive --terragrunt-working-dir %s scaffold %s --output-folder %s", tmpEnvPath, testScaffoldModuleURL, outputFolder)) + require.NoError(t, err) + assert.Contains(t, stderr, "Scaffolding completed") + assert.FileExists(t, outputFolder+"/terragrunt.hcl") +}