@@ -10,6 +10,7 @@ import (
1010 "strings"
1111
1212 "github.com/gruntwork-io/terragrunt/cli/commands/hcl/format"
13+ "github.com/gruntwork-io/terragrunt/cli/flags/shared"
1314 "github.com/gruntwork-io/terragrunt/config"
1415 "github.com/gruntwork-io/terragrunt/pkg/log"
1516 "github.com/gruntwork-io/terragrunt/shell"
@@ -106,7 +107,31 @@ const (
106107 rootFileName = "RootFileName"
107108)
108109
110+ // NewBoilerplateOptions creates a new BoilerplateOptions struct
111+ func NewBoilerplateOptions (
112+ templateFolder ,
113+ outputFolder string ,
114+ vars map [string ]any ,
115+ terragruntOpts * options.TerragruntOptions ,
116+ ) * boilerplate_options.BoilerplateOptions {
117+ return & boilerplate_options.BoilerplateOptions {
118+ TemplateFolder : templateFolder ,
119+ OutputFolder : outputFolder ,
120+ OnMissingKey : boilerplate_options .DefaultMissingKeyAction ,
121+ OnMissingConfig : boilerplate_options .DefaultMissingConfigAction ,
122+ Vars : vars ,
123+ ShellCommandAnswers : map [string ]bool {},
124+ NoShell : terragruntOpts .NoShell ,
125+ NoHooks : terragruntOpts .NoHooks ,
126+ NonInteractive : terragruntOpts .NonInteractive ,
127+ DisableDependencyPrompt : terragruntOpts .NoDependencyPrompt ,
128+ }
129+ }
130+
109131func Run (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , moduleURL , templateURL string ) error {
132+ // Apply catalog configuration settings, with CLI flags taking precedence
133+ applyCatalogConfigToScaffold (ctx , l , opts )
134+
110135 // download remote repo to local
111136 var dirsToClean []string
112137 // clean all temp dirs
@@ -186,27 +211,25 @@ func Run(ctx context.Context, l log.Logger, opts *options.TerragruntOptions, mod
186211 if _ , found := vars [enableRootInclude ]; ! found {
187212 vars [enableRootInclude ] = ! opts .ScaffoldNoIncludeRoot
188213 } else {
189- l .Warnf ("The %s variable is already set in the var flag(s). The --%s flag will be ignored." , enableRootInclude , NoIncludeRootFlagName )
214+ l .Warnf (
215+ "The %s variable is already set in the var flag(s). The --%s flag will be ignored." ,
216+ enableRootInclude ,
217+ shared .NoIncludeRootFlagName ,
218+ )
190219 }
191220
192221 if _ , found := vars [rootFileName ]; ! found {
193222 vars [rootFileName ] = opts .ScaffoldRootFileName
194223 } else {
195- l .Warnf ("The %s variable is already set in the var flag(s). The --%s flag will be ignored." , rootFileName , NoIncludeRootFlagName )
224+ l .Warnf (
225+ "The %s variable is already set in the var flag(s). The --%s flag will be ignored." ,
226+ rootFileName ,
227+ shared .NoIncludeRootFlagName ,
228+ )
196229 }
197230
198231 l .Infof ("Running boilerplate generation to %s" , outputDir )
199- boilerplateOpts := & boilerplate_options.BoilerplateOptions {
200- OutputFolder : outputDir ,
201- OnMissingKey : boilerplate_options .DefaultMissingKeyAction ,
202- OnMissingConfig : boilerplate_options .DefaultMissingConfigAction ,
203- Vars : vars ,
204- DisableShell : true ,
205- DisableHooks : true ,
206- NonInteractive : opts .NonInteractive ,
207- DisableDependencyPrompt : opts .NoDependencyPrompt ,
208- TemplateFolder : boilerplateDir ,
209- }
232+ boilerplateOpts := NewBoilerplateOptions (boilerplateDir , outputDir , vars , opts )
210233
211234 emptyDep := variables.Dependency {}
212235 if err := templates .ProcessTemplate (boilerplateOpts , boilerplateOpts , emptyDep ); err != nil {
@@ -224,22 +247,72 @@ func Run(ctx context.Context, l log.Logger, opts *options.TerragruntOptions, mod
224247 return nil
225248}
226249
250+ // applyCatalogConfigToScaffold applies catalog configuration settings to scaffold options.
251+ // CLI flags take precedence over config file settings.
252+ func applyCatalogConfigToScaffold (ctx context.Context , l log.Logger , opts * options.TerragruntOptions ) {
253+ catalogCfg , err := config .ReadCatalogConfig (ctx , l , opts )
254+ if err != nil {
255+ // Don't fail if catalog config can't be read - it's optional
256+ l .Debugf ("Could not read catalog config for scaffold: %v" , err )
257+ return
258+ }
259+
260+ if catalogCfg == nil {
261+ return
262+ }
263+
264+ // Apply config settings only if CLI flags weren't explicitly set
265+ // Since both NoShell and NoHooks default to false, we apply the config value
266+ // only if it's true (enabling the restriction)
267+ if catalogCfg .NoShell != nil && * catalogCfg .NoShell && ! opts .NoShell {
268+ l .Debugf ("Applying catalog config: no_shell = true" )
269+
270+ opts .NoShell = true
271+ }
272+
273+ if catalogCfg .NoHooks != nil && * catalogCfg .NoHooks && ! opts .NoHooks {
274+ l .Debugf ("Applying catalog config: no_hooks = true" )
275+
276+ opts .NoHooks = true
277+ }
278+ }
279+
227280// generateDefaultTemplate - write default template to provided dir
228281func generateDefaultTemplate (boilerplateDir string ) (string , error ) {
229282 const ownerWriteGlobalReadPerms = 0644
230- if err := os .WriteFile (util .JoinPath (boilerplateDir , config .DefaultTerragruntConfigPath ), []byte (DefaultTerragruntTemplate ), ownerWriteGlobalReadPerms ); err != nil {
283+ if err := os .WriteFile (
284+ util .JoinPath (
285+ boilerplateDir ,
286+ config .DefaultTerragruntConfigPath ,
287+ ),
288+ []byte (DefaultTerragruntTemplate ),
289+ ownerWriteGlobalReadPerms ,
290+ ); err != nil {
231291 return "" , errors .New (err )
232292 }
233293
234- if err := os .WriteFile (util .JoinPath (boilerplateDir , "boilerplate.yml" ), []byte (DefaultBoilerplateConfig ), ownerWriteGlobalReadPerms ); err != nil {
294+ if err := os .WriteFile (
295+ util .JoinPath (
296+ boilerplateDir ,
297+ "boilerplate.yml" ,
298+ ),
299+ []byte (DefaultBoilerplateConfig ),
300+ ownerWriteGlobalReadPerms ,
301+ ); err != nil {
235302 return "" , errors .New (err )
236303 }
237304
238305 return boilerplateDir , nil
239306}
240307
241308// downloadTemplate - parse URL, download files, and handle subfolders
242- func downloadTemplate (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , templateURL string , tempDir string ) (string , error ) {
309+ func downloadTemplate (
310+ ctx context.Context ,
311+ l log.Logger ,
312+ opts * options.TerragruntOptions ,
313+ templateURL ,
314+ tempDir string ,
315+ ) (string , error ) {
243316 parsedTemplateURL , err := tf .ToSourceURL (templateURL , tempDir )
244317 if err != nil {
245318 return "" , errors .New (err )
@@ -278,15 +351,25 @@ func downloadTemplate(ctx context.Context, l log.Logger, opts *options.Terragrun
278351 templateDir = filepath .Join (templateDir , subFolder )
279352 // Verify that subfolder exists
280353 if _ , err := os .Stat (templateDir ); os .IsNotExist (err ) {
281- return "" , errors .Errorf ("subfolder \" //%s\" not found in downloaded template from %s" , subFolder , templateURL )
354+ return "" , errors .Errorf (
355+ "subfolder \" //%s\" not found in downloaded template from %s" ,
356+ subFolder ,
357+ templateURL ,
358+ )
282359 }
283360 }
284361
285362 return templateDir , nil
286363}
287364
288365// prepareBoilerplateFiles - prepare boilerplate files from provided template, tf module, or (custom) default template
289- func prepareBoilerplateFiles (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , templateURL string , tempDir string ) (string , error ) {
366+ func prepareBoilerplateFiles (
367+ ctx context.Context ,
368+ l log.Logger ,
369+ opts * options.TerragruntOptions ,
370+ templateURL ,
371+ tempDir string ,
372+ ) (string , error ) {
290373 boilerplateDir := util .JoinPath (tempDir , util .DefaultBoilerplateDir )
291374
292375 // process template url if it was passed. This overrides the .boilerplate folder in the OpenTofu/Terraform module
@@ -335,7 +418,11 @@ func prepareBoilerplateFiles(ctx context.Context, l log.Logger, opts *options.Te
335418}
336419
337420// parseVariables - parse variables from tf files.
338- func parseVariables (l log.Logger , opts * options.TerragruntOptions , moduleDir string ) ([]* config.ParsedVariable , []* config.ParsedVariable , error ) {
421+ func parseVariables (
422+ l log.Logger ,
423+ opts * options.TerragruntOptions ,
424+ moduleDir string ,
425+ ) ([]* config.ParsedVariable , []* config.ParsedVariable , error ) {
339426 inputs , err := config .ParseVariables (l , opts , moduleDir )
340427 if err != nil {
341428 return nil , nil , errors .New (err )
@@ -359,7 +446,13 @@ func parseVariables(l log.Logger, opts *options.TerragruntOptions, moduleDir str
359446}
360447
361448// parseModuleURL - parse module url and rewrite it if required
362- func parseModuleURL (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , vars map [string ]any , moduleURL string ) (string , error ) {
449+ func parseModuleURL (
450+ ctx context.Context ,
451+ l log.Logger ,
452+ opts * options.TerragruntOptions ,
453+ vars map [string ]any ,
454+ moduleURL string ,
455+ ) (string , error ) {
363456 parsedModuleURL , err := tf .ToSourceURL (moduleURL , opts .WorkingDir )
364457 if err != nil {
365458 return "" , errors .New (err )
@@ -385,7 +478,12 @@ func parseModuleURL(ctx context.Context, l log.Logger, opts *options.TerragruntO
385478
386479// rewriteModuleURL rewrites module url to git ssh if required
387480// github.com/gruntwork-io/terragrunt.git//test/fixtures/inputs => git::https://github.com/gruntwork-io/terragrunt.git//test/fixtures/inputs
388- func rewriteModuleURL (l log.Logger , opts * options.TerragruntOptions , vars map [string ]any , moduleURL string ) (* url.URL , error ) {
481+ func rewriteModuleURL (
482+ l log.Logger ,
483+ opts * options.TerragruntOptions ,
484+ vars map [string ]any ,
485+ moduleURL string ,
486+ ) (* url.URL , error ) {
389487 var updatedModuleURL = moduleURL
390488
391489 sourceURLType := sourceURLTypeHTTPS
@@ -428,7 +526,12 @@ func rewriteModuleURL(l log.Logger, opts *options.TerragruntOptions, vars map[st
428526
429527// rewriteTemplateURL rewrites template url with reference to tag
430528// github.com/denis256/terragrunt-tests.git//scaffold/base-template => github.com/denis256/terragrunt-tests.git//scaffold/base-template?ref=v0.53.8
431- func rewriteTemplateURL (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , parsedTemplateURL * url.URL ) (* url.URL , error ) {
529+ func rewriteTemplateURL (
530+ ctx context.Context ,
531+ l log.Logger ,
532+ opts * options.TerragruntOptions ,
533+ parsedTemplateURL * url.URL ,
534+ ) (* url.URL , error ) {
432535 var (
433536 updatedTemplateURL = parsedTemplateURL
434537 templateParams = updatedTemplateURL .Query ()
@@ -459,7 +562,13 @@ func rewriteTemplateURL(ctx context.Context, l log.Logger, opts *options.Terragr
459562}
460563
461564// addRefToModuleURL adds ref to module url if is passed through variables or find it from git tags
462- func addRefToModuleURL (ctx context.Context , l log.Logger , opts * options.TerragruntOptions , parsedModuleURL * url.URL , vars map [string ]any ) (* url.URL , error ) {
565+ func addRefToModuleURL (
566+ ctx context.Context ,
567+ l log.Logger ,
568+ opts * options.TerragruntOptions ,
569+ parsedModuleURL * url.URL ,
570+ vars map [string ]any ,
571+ ) (* url.URL , error ) {
463572 var moduleURL = parsedModuleURL
464573 // append ref to source url, if is passed through variables or find it from git tags
465574 params := moduleURL .Query ()
0 commit comments