@@ -2,7 +2,6 @@ package cli
22
33import (
44 "fmt"
5- "os"
65 "regexp"
76
87 "github.com/gruntwork-io/terragrunt/config"
@@ -12,6 +11,8 @@ import (
1211 "github.com/gruntwork-io/terragrunt/shell"
1312 "github.com/gruntwork-io/terragrunt/util"
1413 "github.com/urfave/cli"
14+ "github.com/gruntwork-io/terragrunt/options"
15+ "strings"
1516)
1617
1718// Since Terragrunt is just a thin wrapper for Terraform, and we don't want to repeat every single Terraform command
@@ -47,6 +48,9 @@ var MODULE_REGEX = regexp.MustCompile(`module ".+"`)
4748
4849const TERRAFORM_EXTENSION_GLOB = "*.tf"
4950
51+ const OPT_TERRAGRUNT_CONFIG = "terragrunt-config"
52+ const OPT_NON_INTERACTIVE = "terragrunt-non-interactive"
53+
5054// Create the Terragrunt CLI App
5155func CreateTerragruntCli (version string ) * cli.App {
5256 cli .AppHelpTemplate = CUSTOM_USAGE_TEXT
@@ -65,17 +69,16 @@ func CreateTerragruntCli(version string) *cli.App {
6569 Moreover, for the apply and destroy commands, Terragrunt will first try to acquire a lock using DynamoDB. For
6670 documentation, see https://github.com/gruntwork-io/terragrunt/.`
6771
68- var defaultConfigFilePath = config .ConfigFilePath
69- if os .Getenv ("TERRAGRUNT_CONFIG" ) != "" {
70- defaultConfigFilePath = os .Getenv ("TERRAGRUNT_CONFIG" )
71- }
72-
7372 app .Flags = []cli.Flag {
7473 cli.StringFlag {
75- Name : "terragrunt-config" ,
76- Value : defaultConfigFilePath ,
74+ Name : OPT_TERRAGRUNT_CONFIG ,
75+ EnvVar : "TERRAGRUNT_CONFIG" ,
7776 Usage : ".terragrunt file to use" ,
7877 },
78+ cli.BoolFlag {
79+ Name : OPT_NON_INTERACTIVE ,
80+ Usage : "Don't show interactive user prompts. This will default the answer for all prompts to 'yes'." ,
81+ },
7982 }
8083
8184 return app
@@ -92,7 +95,9 @@ func runApp(cliContext *cli.Context) (finalErr error) {
9295 return nil
9396 }
9497
95- conf , err := config .ReadTerragruntConfig (cliContext .String ("terragrunt-config" ))
98+ terragruntOptions := parseTerragruntOptions (cliContext )
99+
100+ conf , err := config .ReadTerragruntConfig (terragruntOptions )
96101 if err != nil {
97102 return err
98103 }
@@ -102,7 +107,7 @@ func runApp(cliContext *cli.Context) (finalErr error) {
102107 }
103108
104109 if conf .RemoteState != nil {
105- if err := configureRemoteState (cliContext , conf .RemoteState ); err != nil {
110+ if err := configureRemoteState (cliContext , conf .RemoteState , terragruntOptions ); err != nil {
106111 return err
107112 }
108113 }
@@ -112,7 +117,22 @@ func runApp(cliContext *cli.Context) (finalErr error) {
112117 return runTerraformCommand (cliContext )
113118 }
114119
115- return runTerraformCommandWithLock (cliContext , conf .Lock )
120+ return runTerraformCommandWithLock (cliContext , conf .Lock , terragruntOptions )
121+ }
122+
123+ // Parse command line options that are passed in for Terragrunt
124+ func parseTerragruntOptions (cliContext * cli.Context ) options.TerragruntOptions {
125+ terragruntConfigPath := cliContext .String (OPT_TERRAGRUNT_CONFIG )
126+ if terragruntConfigPath == "" {
127+ terragruntConfigPath = config .DefaultTerragruntConfigPath
128+ }
129+
130+ nonInteractive := cliContext .Bool (OPT_NON_INTERACTIVE )
131+
132+ return options.TerragruntOptions {
133+ TerragruntConfigPath : terragruntConfigPath ,
134+ NonInteractive : nonInteractive ,
135+ }
116136}
117137
118138// A quick sanity check that calls `terraform get` to download modules, if they aren't already downloaded.
@@ -145,12 +165,12 @@ func shouldDownloadModules() (bool, error) {
145165
146166// If the user entered a Terraform command that uses state (e.g. plan, apply), make sure remote state is configured
147167// before running the command.
148- func configureRemoteState (cliContext * cli.Context , remoteState * remote.RemoteState ) error {
168+ func configureRemoteState (cliContext * cli.Context , remoteState * remote.RemoteState , terragruntOptions options. TerragruntOptions ) error {
149169 // We only configure remote state for the commands that use the tfstate files. We do not configure it for
150170 // commands such as "get" or "version".
151171 switch cliContext .Args ().First () {
152172 case "apply" , "destroy" , "import" , "graph" , "output" , "plan" , "push" , "refresh" , "show" , "taint" , "untaint" , "validate" :
153- return remoteState .ConfigureRemoteState ()
173+ return remoteState .ConfigureRemoteState (terragruntOptions )
154174 case "remote" :
155175 if cliContext .Args ().Get (1 ) == "config" {
156176 // Encourage the user to configure remote state by defining it in .terragrunt and letting
@@ -167,7 +187,7 @@ func configureRemoteState(cliContext *cli.Context, remoteState *remote.RemoteSta
167187}
168188
169189// Run the given Terraform command with the given lock (if the command requires locking)
170- func runTerraformCommandWithLock (cliContext * cli.Context , lock locks.Lock ) error {
190+ func runTerraformCommandWithLock (cliContext * cli.Context , lock locks.Lock , terragruntOptions options. TerragruntOptions ) error {
171191 switch cliContext .Args ().First () {
172192 case "apply" , "destroy" , "import" , "refresh" :
173193 return locks .WithLock (lock , func () error { return runTerraformCommand (cliContext ) })
@@ -178,20 +198,34 @@ func runTerraformCommandWithLock(cliContext *cli.Context, lock locks.Lock) error
178198 return runTerraformCommand (cliContext )
179199 }
180200 case "release-lock" :
181- return runReleaseLockCommand (cliContext , lock )
201+ return runReleaseLockCommand (cliContext , lock , terragruntOptions )
182202 default :
183203 return runTerraformCommand (cliContext )
184204 }
185205}
186206
187207// Run the given Terraform command
188208func runTerraformCommand (cliContext * cli.Context ) error {
189- return shell .RunShellCommand ("terraform" , cliContext .Args ()... )
209+ return shell .RunShellCommand ("terraform" , filterOutTerragruntArgs (cliContext )... )
210+ }
211+
212+ // Return the args in teh given CLI Context object, filtering any args that are only meant for Terragrunt itself
213+ func filterOutTerragruntArgs (cliContext * cli.Context ) []string {
214+ args := []string {}
215+
216+ for _ , arg := range cliContext .Args () {
217+ if ! strings .HasPrefix (arg , "--terragrunt" ) {
218+ args = append (args , arg )
219+ }
220+ }
221+
222+ return args
190223}
191224
192225// Release a lock, prompting the user for confirmation first
193- func runReleaseLockCommand (cliContext * cli.Context , lock locks.Lock ) error {
194- proceed , err := shell .PromptUserForYesNo (fmt .Sprintf ("Are you sure you want to release %s?" , lock ))
226+ func runReleaseLockCommand (cliContext * cli.Context , lock locks.Lock , terragruntOptions options.TerragruntOptions ) error {
227+ prompt := fmt .Sprintf ("Are you sure you want to release %s?" , lock )
228+ proceed , err := shell .PromptUserForYesNo (prompt , terragruntOptions )
195229 if err != nil {
196230 return err
197231 }
0 commit comments