mirror of
https://github.com/hashicorp/terraform.git
synced 2026-05-14 02:10:10 -04:00
Some checks are pending
build / Determine intended Terraform version (push) Waiting to run
build / Determine Go toolchain version (push) Waiting to run
build / Generate release metadata (push) Blocked by required conditions
build / Build for freebsd_386 (push) Blocked by required conditions
build / Build for linux_386 (push) Blocked by required conditions
build / Build for openbsd_386 (push) Blocked by required conditions
build / Build for windows_386 (push) Blocked by required conditions
build / Build for darwin_amd64 (push) Blocked by required conditions
build / Build for freebsd_amd64 (push) Blocked by required conditions
build / Build for linux_amd64 (push) Blocked by required conditions
build / Build for openbsd_amd64 (push) Blocked by required conditions
build / Build for solaris_amd64 (push) Blocked by required conditions
build / Build for windows_amd64 (push) Blocked by required conditions
build / Build for freebsd_arm (push) Blocked by required conditions
build / Build for linux_arm (push) Blocked by required conditions
build / Build for darwin_arm64 (push) Blocked by required conditions
build / Build for linux_arm64 (push) Blocked by required conditions
build / Build for windows_arm64 (push) Blocked by required conditions
build / Build Docker image for linux_386 (push) Blocked by required conditions
build / Build Docker image for linux_amd64 (push) Blocked by required conditions
build / Build Docker image for linux_arm (push) Blocked by required conditions
build / Build Docker image for linux_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_386 (push) Blocked by required conditions
build / Build e2etest for windows_386 (push) Blocked by required conditions
build / Build e2etest for darwin_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_amd64 (push) Blocked by required conditions
build / Build e2etest for windows_amd64 (push) Blocked by required conditions
build / Build e2etest for linux_arm (push) Blocked by required conditions
build / Build e2etest for darwin_arm64 (push) Blocked by required conditions
build / Build e2etest for linux_arm64 (push) Blocked by required conditions
build / Run e2e test for linux_386 (push) Blocked by required conditions
build / Run e2e test for windows_386 (push) Blocked by required conditions
build / Run e2e test for darwin_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_amd64 (push) Blocked by required conditions
build / Run e2e test for windows_amd64 (push) Blocked by required conditions
build / Run e2e test for linux_arm (push) Blocked by required conditions
build / Run e2e test for linux_arm64 (push) Blocked by required conditions
build / Run terraform-exec test for linux amd64 (push) Blocked by required conditions
Quick Checks / Unit Tests (push) Waiting to run
Quick Checks / Race Tests (push) Waiting to run
Quick Checks / End-to-end Tests (push) Waiting to run
Quick Checks / Code Consistency Checks (push) Waiting to run
* refactor: Stop Terraform creating the default workspace during init when using PSS This is part of reconciling how in the past backends always reported that the default backend existed, even when it didn't. We want state stores to report reality only, so we need to let Terraform handle the discrepancy. Prior to this commit we handled it by making reality match the old lie that the default workspace always exists. After this commit we're just embracing Terraform working with truthful information.
265 lines
7.5 KiB
Go
265 lines
7.5 KiB
Go
// Copyright IBM Corp. 2014, 2026
|
|
// SPDX-License-Identifier: BUSL-1.1
|
|
|
|
package arguments
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/google/go-cmp/cmp"
|
|
"github.com/google/go-cmp/cmp/cmpopts"
|
|
)
|
|
|
|
func TestParseInit_basicValid(t *testing.T) {
|
|
var flagNameValue []FlagNameValue
|
|
testCases := map[string]struct {
|
|
args []string
|
|
want *Init
|
|
}{
|
|
"with default options": {
|
|
nil,
|
|
&Init{
|
|
FromModule: "",
|
|
Lockfile: "",
|
|
TestsDirectory: "tests",
|
|
ViewType: ViewHuman,
|
|
Backend: true,
|
|
Cloud: true,
|
|
Get: true,
|
|
ForceInitCopy: false,
|
|
StateLock: true,
|
|
StateLockTimeout: 0,
|
|
Reconfigure: false,
|
|
MigrateState: false,
|
|
Upgrade: false,
|
|
Json: false,
|
|
IgnoreRemoteVersion: false,
|
|
BackendConfig: FlagNameValueSlice{
|
|
FlagName: "-backend-config",
|
|
Items: &flagNameValue,
|
|
},
|
|
Vars: &Vars{},
|
|
InputEnabled: true,
|
|
CompactWarnings: false,
|
|
TargetFlags: nil,
|
|
},
|
|
},
|
|
"setting multiple options": {
|
|
[]string{
|
|
"-backend=false", "-force-copy=true",
|
|
"-from-module=./main-dir", "-json", "-get=false",
|
|
"-lock=false", "-lock-timeout=10s", "-reconfigure=true",
|
|
"-upgrade=true", "-lockfile=readonly", "-compact-warnings=true",
|
|
"-ignore-remote-version=true", "-test-directory=./test-dir",
|
|
},
|
|
&Init{
|
|
FromModule: "./main-dir",
|
|
Lockfile: "readonly",
|
|
TestsDirectory: "./test-dir",
|
|
ViewType: ViewJSON,
|
|
Backend: false,
|
|
Cloud: false,
|
|
Get: false,
|
|
ForceInitCopy: true,
|
|
StateLock: false,
|
|
StateLockTimeout: time.Duration(10) * time.Second,
|
|
Reconfigure: true,
|
|
MigrateState: false,
|
|
Upgrade: true,
|
|
Json: true,
|
|
IgnoreRemoteVersion: true,
|
|
BackendConfig: FlagNameValueSlice{
|
|
FlagName: "-backend-config",
|
|
Items: &flagNameValue,
|
|
},
|
|
Vars: &Vars{},
|
|
InputEnabled: true,
|
|
Args: []string{},
|
|
CompactWarnings: true,
|
|
TargetFlags: nil,
|
|
},
|
|
},
|
|
"with cloud option": {
|
|
[]string{"-cloud=false", "-input=false", "-target=foo_bar.baz", "-backend-config", "backend.config"},
|
|
&Init{
|
|
FromModule: "",
|
|
Lockfile: "",
|
|
TestsDirectory: "tests",
|
|
ViewType: ViewHuman,
|
|
Backend: false,
|
|
Cloud: false,
|
|
Get: true,
|
|
ForceInitCopy: false,
|
|
StateLock: true,
|
|
StateLockTimeout: 0,
|
|
Reconfigure: false,
|
|
MigrateState: false,
|
|
Upgrade: false,
|
|
Json: false,
|
|
IgnoreRemoteVersion: false,
|
|
BackendConfig: FlagNameValueSlice{
|
|
FlagName: "-backend-config",
|
|
Items: &[]FlagNameValue{{Name: "-backend-config", Value: "backend.config"}},
|
|
},
|
|
Vars: &Vars{},
|
|
InputEnabled: false,
|
|
Args: []string{},
|
|
CompactWarnings: false,
|
|
TargetFlags: []string{"foo_bar.baz"},
|
|
},
|
|
},
|
|
}
|
|
|
|
cmpOpts := cmpopts.IgnoreUnexported(Vars{})
|
|
|
|
for name, tc := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
experimentsEnabled := false
|
|
got, diags := ParseInit(tc.args, experimentsEnabled)
|
|
if len(diags) > 0 {
|
|
t.Fatalf("unexpected diags: %v", diags)
|
|
}
|
|
|
|
if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" {
|
|
t.Errorf("unexpected result\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseInit_invalid(t *testing.T) {
|
|
testCases := map[string]struct {
|
|
args []string
|
|
wantErr string
|
|
wantViewType ViewType
|
|
}{
|
|
"with unsupported options": {
|
|
args: []string{"-raw"},
|
|
wantErr: "flag provided but not defined",
|
|
wantViewType: ViewHuman,
|
|
},
|
|
"with both -backend and -cloud options set": {
|
|
args: []string{"-backend=false", "-cloud=false"},
|
|
wantErr: "The -backend and -cloud options are aliases of one another and mutually-exclusive in their use",
|
|
wantViewType: ViewHuman,
|
|
},
|
|
"with both -migrate-state and -json options set": {
|
|
args: []string{"-migrate-state", "-json"},
|
|
wantErr: "Terraform cannot ask for interactive approval when -json is set. To use the -migrate-state option, disable the -json option.",
|
|
wantViewType: ViewJSON,
|
|
},
|
|
"with both -migrate-state and -reconfigure options set": {
|
|
args: []string{"-migrate-state", "-reconfigure"},
|
|
wantErr: "The -migrate-state and -reconfigure options are mutually-exclusive.",
|
|
wantViewType: ViewHuman,
|
|
},
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
experimentsEnabled := false
|
|
got, diags := ParseInit(tc.args, experimentsEnabled)
|
|
if len(diags) == 0 {
|
|
t.Fatal("expected diags but got none")
|
|
}
|
|
if got, want := diags.Err().Error(), tc.wantErr; !strings.Contains(got, want) {
|
|
t.Fatalf("wrong diags\n got: %s\nwant: %s", got, want)
|
|
}
|
|
if got.ViewType != tc.wantViewType {
|
|
t.Fatalf("wrong view type, got %#v, want %#v", got.ViewType, ViewHuman)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseInit_experimentalFlags(t *testing.T) {
|
|
testCases := map[string]struct {
|
|
args []string
|
|
envs map[string]string
|
|
wantErr string
|
|
experimentsEnabled bool
|
|
}{
|
|
"error: -enable-pluggable-state-storage-experiment and experiments are disabled": {
|
|
args: []string{"-enable-pluggable-state-storage-experiment"},
|
|
experimentsEnabled: false,
|
|
wantErr: "Cannot use -enable-pluggable-state-storage-experiment flag without experiments enabled",
|
|
},
|
|
"error: TF_ENABLE_PLUGGABLE_STATE_STORAGE is set and experiments are disabled": {
|
|
envs: map[string]string{
|
|
"TF_ENABLE_PLUGGABLE_STATE_STORAGE": "1",
|
|
},
|
|
experimentsEnabled: false,
|
|
wantErr: "Cannot use -enable-pluggable-state-storage-experiment flag without experiments enabled",
|
|
},
|
|
}
|
|
|
|
for name, tc := range testCases {
|
|
t.Run(name, func(t *testing.T) {
|
|
for k, v := range tc.envs {
|
|
t.Setenv(k, v)
|
|
}
|
|
|
|
_, diags := ParseInit(tc.args, tc.experimentsEnabled)
|
|
if len(diags) == 0 {
|
|
t.Fatal("expected diags but got none")
|
|
}
|
|
if got, want := diags.Err().Error(), tc.wantErr; !strings.Contains(got, want) {
|
|
t.Fatalf("wrong diags\n got: %s\nwant: %s", got, want)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestParseInit_vars(t *testing.T) {
|
|
testCases := map[string]struct {
|
|
args []string
|
|
want []FlagNameValue
|
|
}{
|
|
"no var flags by default": {
|
|
args: nil,
|
|
want: nil,
|
|
},
|
|
"one var": {
|
|
args: []string{"-var", "foo=bar"},
|
|
want: []FlagNameValue{
|
|
{Name: "-var", Value: "foo=bar"},
|
|
},
|
|
},
|
|
"one var-file": {
|
|
args: []string{"-var-file", "cool.tfvars"},
|
|
want: []FlagNameValue{
|
|
{Name: "-var-file", Value: "cool.tfvars"},
|
|
},
|
|
},
|
|
"ordering preserved": {
|
|
args: []string{
|
|
"-var", "foo=bar",
|
|
"-var-file", "cool.tfvars",
|
|
"-var", "boop=beep",
|
|
},
|
|
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) {
|
|
experimentsEnabled := false
|
|
got, diags := ParseInit(tc.args, experimentsEnabled)
|
|
if len(diags) > 0 {
|
|
t.Fatalf("unexpected diags: %v", diags)
|
|
}
|
|
if vars := got.Vars.All(); !cmp.Equal(vars, tc.want) {
|
|
t.Fatalf("unexpected result\n%s", cmp.Diff(vars, tc.want))
|
|
}
|
|
if got, want := got.Vars.Empty(), len(tc.want) == 0; got != want {
|
|
t.Fatalf("expected Empty() to return %t, but was %t", want, got)
|
|
}
|
|
})
|
|
}
|
|
}
|