command: Add vars to taint command

pull/38288/head
Daniel Banck 1 month ago committed by Daniel Banck
parent a836cd610d
commit cdbd4f17f2

@ -11,6 +11,9 @@ import (
// Taint represents the command-line arguments for the taint command.
type Taint struct {
// Vars are the variable-related flags (-var, -var-file).
Vars *Vars
// Address is the address of the resource instance to taint.
Address string
@ -44,9 +47,11 @@ type Taint struct {
// the best effort interpretation of the arguments.
func ParseTaint(args []string) (*Taint, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
taint := &Taint{}
taint := &Taint{
Vars: &Vars{},
}
cmdFlags := defaultFlagSet("taint")
cmdFlags := extendedFlagSet("taint", nil, nil, taint.Vars)
cmdFlags.BoolVar(&taint.AllowMissing, "allow-missing", false, "allow missing")
cmdFlags.StringVar(&taint.BackupPath, "backup", "", "path")
cmdFlags.BoolVar(&taint.StateLock, "lock", true, "lock state")

@ -7,6 +7,9 @@ import (
"testing"
"time"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/terraform/internal/tfdiags"
)
@ -18,6 +21,7 @@ func TestParseTaint_valid(t *testing.T) {
"defaults with address": {
[]string{"test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
},
@ -25,6 +29,7 @@ func TestParseTaint_valid(t *testing.T) {
"allow-missing": {
[]string{"-allow-missing", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
AllowMissing: true,
StateLock: true,
@ -33,6 +38,7 @@ func TestParseTaint_valid(t *testing.T) {
"backup": {
[]string{"-backup", "backup.tfstate", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
BackupPath: "backup.tfstate",
StateLock: true,
@ -41,12 +47,14 @@ func TestParseTaint_valid(t *testing.T) {
"lock disabled": {
[]string{"-lock=false", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
},
},
"lock-timeout": {
[]string{"-lock-timeout=10s", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
StateLockTimeout: 10 * time.Second,
@ -55,6 +63,7 @@ func TestParseTaint_valid(t *testing.T) {
"state": {
[]string{"-state=foo.tfstate", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
StatePath: "foo.tfstate",
@ -63,6 +72,7 @@ func TestParseTaint_valid(t *testing.T) {
"state-out": {
[]string{"-state-out=foo.tfstate", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
StateOutPath: "foo.tfstate",
@ -71,6 +81,7 @@ func TestParseTaint_valid(t *testing.T) {
"ignore-remote-version": {
[]string{"-ignore-remote-version", "test_instance.foo"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
IgnoreRemoteVersion: true,
@ -88,6 +99,7 @@ func TestParseTaint_valid(t *testing.T) {
"module.child.test_instance.foo",
},
&Taint{
Vars: &Vars{},
Address: "module.child.test_instance.foo",
AllowMissing: true,
BackupPath: "backup.tfstate",
@ -99,19 +111,66 @@ func TestParseTaint_valid(t *testing.T) {
},
}
cmpOpts := cmpopts.IgnoreUnexported(Vars{})
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, diags := ParseTaint(tc.args)
if len(diags) > 0 {
t.Fatalf("unexpected diags: %v", diags)
}
if *got != *tc.want {
if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" {
t.Fatalf("unexpected result\n got: %#v\nwant: %#v", got, tc.want)
}
})
}
}
func TestParseTaint_vars(t *testing.T) {
testCases := map[string]struct {
args []string
want []FlagNameValue
}{
"var": {
args: []string{"-var", "foo=bar", "test_instance.foo"},
want: []FlagNameValue{
{Name: "-var", Value: "foo=bar"},
},
},
"var-file": {
args: []string{"-var-file", "cool.tfvars", "test_instance.foo"},
want: []FlagNameValue{
{Name: "-var-file", Value: "cool.tfvars"},
},
},
"both": {
args: []string{
"-var", "foo=bar",
"-var-file", "cool.tfvars",
"-var", "boop=beep",
"test_instance.foo",
},
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 := ParseTaint(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)
}
})
}
}
func TestParseTaint_invalid(t *testing.T) {
testCases := map[string]struct {
args []string
@ -121,6 +180,7 @@ func TestParseTaint_invalid(t *testing.T) {
"unknown flag": {
[]string{"-unknown"},
&Taint{
Vars: &Vars{},
StateLock: true,
},
tfdiags.Diagnostics{
@ -139,6 +199,7 @@ func TestParseTaint_invalid(t *testing.T) {
"missing address": {
nil,
&Taint{
Vars: &Vars{},
StateLock: true,
},
tfdiags.Diagnostics{
@ -152,6 +213,7 @@ func TestParseTaint_invalid(t *testing.T) {
"too many arguments": {
[]string{"test_instance.foo", "test_instance.bar"},
&Taint{
Vars: &Vars{},
Address: "test_instance.foo",
StateLock: true,
},
@ -165,10 +227,12 @@ func TestParseTaint_invalid(t *testing.T) {
},
}
cmpOpts := cmpopts.IgnoreUnexported(Vars{})
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, gotDiags := ParseTaint(tc.args)
if *got != *tc.want {
if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" {
t.Fatalf("unexpected result\n got: %#v\nwant: %#v", got, tc.want)
}
tfdiags.AssertDiagnosticsMatch(t, gotDiags, tc.wantDiags)

@ -37,6 +37,23 @@ func (c *TaintCommand) Run(rawArgs []string) int {
c.Meta.stateOutPath = parsedArgs.StateOutPath
c.Meta.ignoreRemoteVersion = parsedArgs.IgnoreRemoteVersion
loader, err := c.initConfigLoader()
if err != nil {
var diags tfdiags.Diagnostics
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)
})
if varDiags.HasErrors() {
c.showDiagnostics(varDiags)
return 1
}
var diags tfdiags.Diagnostics
addr, addrDiags := addrs.ParseAbsResourceInstanceStr(parsedArgs.Address)
@ -224,6 +241,15 @@ Options:
-ignore-remote-version A rare option used for the remote backend only. See
the remote backend documentation for more information.
-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.
-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.
-state, state-out, and -backup are legacy options supported for the local
backend only. For more information, see the local backend's documentation.

Loading…
Cancel
Save