From ed2bdf6825b1e91db613d7cb257ae44cb1b24769 Mon Sep 17 00:00:00 2001 From: Daniel Banck Date: Wed, 11 Mar 2026 15:07:48 +0100 Subject: [PATCH] command: Add vars to providers mirror command --- .../command/arguments/providers_mirror.go | 9 ++- .../arguments/providers_mirror_test.go | 59 ++++++++++++++++++- internal/command/providers_mirror.go | 54 ++++++++++++----- 3 files changed, 104 insertions(+), 18 deletions(-) diff --git a/internal/command/arguments/providers_mirror.go b/internal/command/arguments/providers_mirror.go index 219ad50032..6b7c671a07 100644 --- a/internal/command/arguments/providers_mirror.go +++ b/internal/command/arguments/providers_mirror.go @@ -11,6 +11,9 @@ type ProvidersMirror struct { Platforms FlagStringSlice LockFile bool OutputDir string + + // Vars are the variable-related flags (-var, -var-file). + Vars *Vars } // ParseProvidersMirror processes CLI arguments, returning a ProvidersMirror @@ -18,9 +21,11 @@ type ProvidersMirror struct { // still returned representing the best effort interpretation of the arguments. func ParseProvidersMirror(args []string) (*ProvidersMirror, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics - providersMirror := &ProvidersMirror{} + providersMirror := &ProvidersMirror{ + Vars: &Vars{}, + } - cmdFlags := defaultFlagSet("providers mirror") + cmdFlags := extendedFlagSet("providers mirror", nil, nil, providersMirror.Vars) cmdFlags.Var(&providersMirror.Platforms, "platform", "target platform") cmdFlags.BoolVar(&providersMirror.LockFile, "lock-file", true, "use lock file") diff --git a/internal/command/arguments/providers_mirror_test.go b/internal/command/arguments/providers_mirror_test.go index d6fb5598ee..596ed73d66 100644 --- a/internal/command/arguments/providers_mirror_test.go +++ b/internal/command/arguments/providers_mirror_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" "github.com/hashicorp/terraform/internal/tfdiags" ) @@ -20,6 +21,7 @@ func TestParseProvidersMirror_valid(t *testing.T) { &ProvidersMirror{ LockFile: true, OutputDir: "./mirror", + Vars: &Vars{}, }, }, "all options": { @@ -32,17 +34,20 @@ func TestParseProvidersMirror_valid(t *testing.T) { &ProvidersMirror{ Platforms: FlagStringSlice{"linux_amd64", "darwin_arm64"}, OutputDir: "./mirror", + Vars: &Vars{}, }, }, } + cmpOpts := cmpopts.IgnoreUnexported(Vars{}) + for name, tc := range testCases { t.Run(name, func(t *testing.T) { got, diags := ParseProvidersMirror(tc.args) if len(diags) > 0 { t.Fatalf("unexpected diags: %v", diags) } - if diff := cmp.Diff(tc.want, got); diff != "" { + if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" { t.Fatalf("unexpected result\n%s", diff) } }) @@ -59,6 +64,7 @@ func TestParseProvidersMirror_invalid(t *testing.T) { nil, &ProvidersMirror{ LockFile: true, + Vars: &Vars{}, }, tfdiags.Diagnostics{ tfdiags.Sourceless( @@ -72,6 +78,7 @@ func TestParseProvidersMirror_invalid(t *testing.T) { []string{"./mirror", "./extra"}, &ProvidersMirror{ LockFile: true, + Vars: &Vars{}, }, tfdiags.Diagnostics{ tfdiags.Sourceless( @@ -85,6 +92,7 @@ func TestParseProvidersMirror_invalid(t *testing.T) { []string{"-wat"}, &ProvidersMirror{ LockFile: true, + Vars: &Vars{}, }, tfdiags.Diagnostics{ tfdiags.Sourceless( @@ -101,13 +109,60 @@ func TestParseProvidersMirror_invalid(t *testing.T) { }, } + cmpOpts := cmpopts.IgnoreUnexported(Vars{}) + for name, tc := range testCases { t.Run(name, func(t *testing.T) { got, gotDiags := ParseProvidersMirror(tc.args) - if diff := cmp.Diff(tc.want, got); diff != "" { + if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" { t.Fatalf("unexpected result\n%s", diff) } tfdiags.AssertDiagnosticsMatch(t, gotDiags, tc.wantDiags) }) } } + +func TestParseProvidersMirror_vars(t *testing.T) { + testCases := map[string]struct { + args []string + want []FlagNameValue + }{ + "var": { + args: []string{"-var", "foo=bar", "./mirror"}, + want: []FlagNameValue{ + {Name: "-var", Value: "foo=bar"}, + }, + }, + "var-file": { + args: []string{"-var-file", "cool.tfvars", "./mirror"}, + want: []FlagNameValue{ + {Name: "-var-file", Value: "cool.tfvars"}, + }, + }, + "both": { + args: []string{ + "-var", "foo=bar", + "-var-file", "cool.tfvars", + "-var", "boop=beep", + "./mirror", + }, + want: []FlagNameValue{ + {Name: "-var", Value: "foo=bar"}, + {Name: "-var-file", Value: "cool.tfvars"}, + {Name: "-var", Value: "boop=beep"}, + }, + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + got, diags := ParseProvidersMirror(tc.args) + if len(diags) > 0 { + t.Fatalf("unexpected diags: %v", diags) + } + if vars := got.Vars.All(); !cmp.Equal(vars, tc.want) { + t.Fatalf("unexpected vars: %#v", vars) + } + }) + } +} diff --git a/internal/command/providers_mirror.go b/internal/command/providers_mirror.go index cfff1b2e2c..d17f548189 100644 --- a/internal/command/providers_mirror.go +++ b/internal/command/providers_mirror.go @@ -61,6 +61,23 @@ func (c *ProvidersMirrorCommand) Run(args []string) int { ctx, done := c.InterruptibleContext(c.CommandContext()) defer done() + loader, err := c.initConfigLoader() + if err != nil { + diags = diags.Append(err) + c.showDiagnostics(diags) + return 1 + } + + var varDiags tfdiags.Diagnostics + c.VariableValues, varDiags = parsedArgs.Vars.CollectValues(func(filename string, src []byte) { + loader.Parser().ForceFileSource(filename, src) + }) + diags = diags.Append(varDiags) + if diags.HasErrors() { + c.showDiagnostics(diags) + return 1 + } + config, confDiags := c.loadConfig(".") diags = diags.Append(confDiags) reqs, moreDiags := config.ProviderRequirements() @@ -350,21 +367,30 @@ Usage: terraform [global options] providers mirror [options] Options: - -platform=os_arch Choose which target platform to build a mirror for. - By default Terraform will obtain plugin packages - suitable for the platform where you run this command. - Use this flag multiple times to include packages for - multiple target systems. + -platform=os_arch Choose which target platform to build a mirror for. + By default Terraform will obtain plugin packages + suitable for the platform where you run this command. + Use this flag multiple times to include packages for + multiple target systems. + + Target names consist of an operating system and a CPU + architecture. For example, "linux_amd64" selects the + Linux operating system running on an AMD64 or x86_64 + CPU. Each provider is available only for a limited + set of target platforms. + + -lock-file=false Ignore the provider lock file when fetching providers. + By default the mirror command will use the version info + in the lock file if the configuration directory has been + previously initialized. - Target names consist of an operating system and a CPU - architecture. For example, "linux_amd64" selects the - Linux operating system running on an AMD64 or x86_64 - CPU. Each provider is available only for a limited - set of target platforms. + -var 'foo=bar' Set a value for one of the input variables in the root + module of the configuration. Use this option more than + once to set more than one variable. - -lock-file=false Ignore the provider lock file when fetching providers. - By default the mirror command will use the version info - in the lock file if the configuration directory has been - previously initialized. + -var-file=filename Load variable values from the given file, in addition + to the default files terraform.tfvars and *.auto.tfvars. + Use this option more than once to include more than one + variables file. ` }