|
|
|
|
@@ -172,17 +172,19 @@ func TestCloud_PrepareConfig(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
|
s := testServer(t)
|
|
|
|
|
b := New(testDisco(s))
|
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
|
s := testServer(t)
|
|
|
|
|
b := New(testDisco(s))
|
|
|
|
|
|
|
|
|
|
// Validate
|
|
|
|
|
_, valDiags := b.PrepareConfig(tc.config)
|
|
|
|
|
if valDiags.Err() != nil && tc.expectedErr != "" {
|
|
|
|
|
actualErr := valDiags.Err().Error()
|
|
|
|
|
if !strings.Contains(actualErr, tc.expectedErr) {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err())
|
|
|
|
|
// Validate
|
|
|
|
|
_, valDiags := b.PrepareConfig(tc.config)
|
|
|
|
|
if valDiags.Err() != nil && tc.expectedErr != "" {
|
|
|
|
|
actualErr := valDiags.Err().Error()
|
|
|
|
|
if !strings.Contains(actualErr, tc.expectedErr) {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -260,7 +262,7 @@ func TestCloud_PrepareConfigWithEnvVars(t *testing.T) {
|
|
|
|
|
"TF_CLOUD_PROJECT": "example-project",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"with project env var ovewrite config value": {
|
|
|
|
|
"with project env var overwrite config value": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("organization"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
@@ -273,6 +275,51 @@ func TestCloud_PrepareConfigWithEnvVars(t *testing.T) {
|
|
|
|
|
"TF_CLOUD_PROJECT": "example-project",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"with workspace defined by tags overwritten by TF_WORKSPACE": {
|
|
|
|
|
// see https://github.com/opentofu/opentofu/issues/814 for context
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("foo"),
|
|
|
|
|
"organization": cty.StringVal("bar"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{cty.StringVal("baz"), cty.StringVal("qux")}),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "qux",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
"with TF_WORKSPACE value outside of the tags set": {
|
|
|
|
|
// see https://github.com/opentofu/opentofu/issues/814 for context
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("foo"),
|
|
|
|
|
"organization": cty.StringVal("bar"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{cty.StringVal("baz"), cty.StringVal("qux")}),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "quxx",
|
|
|
|
|
},
|
|
|
|
|
expectedErr: `Invalid workspaces configuration: The workspace defined using the environment variable "TF_WORKSPACE" does not belong to "tags".`,
|
|
|
|
|
},
|
|
|
|
|
"with workspace block w/o attributes, TF_WORKSPACE defined": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("foo"),
|
|
|
|
|
"organization": cty.StringVal("bar"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "qux",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
|
@@ -290,323 +337,13 @@ func TestCloud_PrepareConfigWithEnvVars(t *testing.T) {
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
_, valDiags := b.PrepareConfig(tc.config)
|
|
|
|
|
if valDiags.Err() != nil && tc.expectedErr != "" {
|
|
|
|
|
actualErr := valDiags.Err().Error()
|
|
|
|
|
if !strings.Contains(actualErr, tc.expectedErr) {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func WithEnvVars(t *testing.T) {
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
|
setup func(b *Cloud)
|
|
|
|
|
config cty.Value
|
|
|
|
|
vars map[string]string
|
|
|
|
|
expectedOrganization string
|
|
|
|
|
expectedHostname string
|
|
|
|
|
expectedWorkspaceName string
|
|
|
|
|
expectedProjectName string
|
|
|
|
|
expectedErr string
|
|
|
|
|
}{
|
|
|
|
|
"with no organization specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_ORGANIZATION": "hashicorp",
|
|
|
|
|
},
|
|
|
|
|
expectedOrganization: "hashicorp",
|
|
|
|
|
},
|
|
|
|
|
"with both organization and env var specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_ORGANIZATION": "we-should-not-see-this",
|
|
|
|
|
},
|
|
|
|
|
expectedOrganization: "hashicorp",
|
|
|
|
|
},
|
|
|
|
|
"with no hostname specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "private.hashicorp.engineering",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "private.hashicorp.engineering",
|
|
|
|
|
},
|
|
|
|
|
"with hostname and env var specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("private.hashicorp.engineering"),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "mycool.tfe-host.io",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "private.hashicorp.engineering",
|
|
|
|
|
},
|
|
|
|
|
"an invalid workspace env var": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"workspaces": cty.NullVal(cty.Object(map[string]cty.Type{
|
|
|
|
|
"name": cty.String,
|
|
|
|
|
"tags": cty.Set(cty.String),
|
|
|
|
|
"project": cty.String,
|
|
|
|
|
})),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "i-dont-exist-in-org",
|
|
|
|
|
},
|
|
|
|
|
expectedErr: `Invalid workspace selection: OpenTofu failed to find workspace "i-dont-exist-in-org" in organization hashicorp`,
|
|
|
|
|
},
|
|
|
|
|
"workspaces and env var specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("mt-doom"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "shire",
|
|
|
|
|
},
|
|
|
|
|
expectedWorkspaceName: "mt-doom",
|
|
|
|
|
},
|
|
|
|
|
"env var workspace does not have specified tag": {
|
|
|
|
|
setup: func(b *Cloud) {
|
|
|
|
|
b.client.Organizations.Create(context.Background(), tfe.OrganizationCreateOptions{
|
|
|
|
|
Name: tfe.String("mordor"),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.client.Workspaces.Create(context.Background(), "mordor", tfe.WorkspaceCreateOptions{
|
|
|
|
|
Name: tfe.String("shire"),
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{
|
|
|
|
|
cty.StringVal("cloud"),
|
|
|
|
|
}),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "shire",
|
|
|
|
|
},
|
|
|
|
|
expectedErr: "OpenTofu failed to find workspace \"shire\" with the tags specified in your configuration:\n[cloud]",
|
|
|
|
|
},
|
|
|
|
|
"env var workspace has specified tag": {
|
|
|
|
|
setup: func(b *Cloud) {
|
|
|
|
|
b.client.Organizations.Create(context.Background(), tfe.OrganizationCreateOptions{
|
|
|
|
|
Name: tfe.String("mordor"),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.client.Workspaces.Create(context.Background(), "mordor", tfe.WorkspaceCreateOptions{
|
|
|
|
|
Name: tfe.String("shire"),
|
|
|
|
|
Tags: []*tfe.Tag{
|
|
|
|
|
{
|
|
|
|
|
Name: "hobbity",
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{
|
|
|
|
|
cty.StringVal("hobbity"),
|
|
|
|
|
}),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "shire",
|
|
|
|
|
},
|
|
|
|
|
expectedWorkspaceName: "", // No error is raised, but workspace is not set
|
|
|
|
|
},
|
|
|
|
|
"project specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("mt-doom"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.StringVal("my-project"),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedWorkspaceName: "mt-doom",
|
|
|
|
|
expectedProjectName: "my-project",
|
|
|
|
|
},
|
|
|
|
|
"project env var specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("mt-doom"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_PROJECT": "other-project",
|
|
|
|
|
},
|
|
|
|
|
expectedWorkspaceName: "mt-doom",
|
|
|
|
|
expectedProjectName: "other-project",
|
|
|
|
|
},
|
|
|
|
|
"project and env var specified": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("mt-doom"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.StringVal("my-project"),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_PROJECT": "other-project",
|
|
|
|
|
},
|
|
|
|
|
expectedWorkspaceName: "mt-doom",
|
|
|
|
|
expectedProjectName: "my-project",
|
|
|
|
|
},
|
|
|
|
|
"workspace exists but in different project": {
|
|
|
|
|
setup: func(b *Cloud) {
|
|
|
|
|
b.client.Organizations.Create(context.Background(), tfe.OrganizationCreateOptions{
|
|
|
|
|
Name: tfe.String("mordor"),
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
project, _ := b.client.Projects.Create(context.Background(), "mordor", tfe.ProjectCreateOptions{
|
|
|
|
|
Name: "another-project",
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
b.client.Workspaces.Create(context.Background(), "mordor", tfe.WorkspaceCreateOptions{
|
|
|
|
|
Name: tfe.String("shire"),
|
|
|
|
|
Project: project,
|
|
|
|
|
})
|
|
|
|
|
},
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.StringVal("mordor"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{
|
|
|
|
|
cty.StringVal("hobbity"),
|
|
|
|
|
}),
|
|
|
|
|
"project": cty.StringVal("my-project"),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedProjectName: "another-project", // No error is raised, workspace is still in the original project
|
|
|
|
|
},
|
|
|
|
|
"with everything set as env vars": {
|
|
|
|
|
config: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
vars: map[string]string{
|
|
|
|
|
"TF_CLOUD_ORGANIZATION": "mordor",
|
|
|
|
|
"TF_WORKSPACE": "mt-doom",
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "mycool.tfe-host.io",
|
|
|
|
|
"TF_CLOUD_PROJECT": "my-project",
|
|
|
|
|
},
|
|
|
|
|
expectedOrganization: "mordor",
|
|
|
|
|
expectedWorkspaceName: "mt-doom",
|
|
|
|
|
expectedHostname: "mycool.tfe-host.io",
|
|
|
|
|
expectedProjectName: "my-project",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
|
b, cleanup := testUnconfiguredBackend(t)
|
|
|
|
|
t.Cleanup(cleanup)
|
|
|
|
|
|
|
|
|
|
for k, v := range tc.vars {
|
|
|
|
|
os.Setenv(k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
t.Cleanup(func() {
|
|
|
|
|
for k := range tc.vars {
|
|
|
|
|
os.Unsetenv(k)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
_, valDiags := b.PrepareConfig(tc.config)
|
|
|
|
|
if valDiags.Err() != nil {
|
|
|
|
|
if (valDiags.Err() == nil) != (tc.expectedErr == "") {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.setup != nil {
|
|
|
|
|
tc.setup(b)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
diags := b.Configure(tc.config)
|
|
|
|
|
if (diags.Err() != nil || tc.expectedErr != "") &&
|
|
|
|
|
(diags.Err() == nil || !strings.Contains(diags.Err().Error(), tc.expectedErr)) {
|
|
|
|
|
t.Fatalf("%s: unexpected configure result: %v", name, diags.Err())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.expectedOrganization != "" && tc.expectedOrganization != b.organization {
|
|
|
|
|
t.Fatalf("%s: organization not valid: %s, expected: %s", name, b.organization, tc.expectedOrganization)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.expectedHostname != "" && tc.expectedHostname != b.hostname {
|
|
|
|
|
t.Fatalf("%s: hostname not valid: %s, expected: %s", name, b.hostname, tc.expectedHostname)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.expectedWorkspaceName != "" && tc.expectedWorkspaceName != b.WorkspaceMapping.Name {
|
|
|
|
|
t.Fatalf("%s: workspace name not valid: %s, expected: %s", name, b.WorkspaceMapping.Name, tc.expectedWorkspaceName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.expectedProjectName != "" && tc.expectedProjectName != b.WorkspaceMapping.Project {
|
|
|
|
|
t.Fatalf("%s: project name not valid: %s, expected: %s", name, b.WorkspaceMapping.Project, tc.expectedProjectName)
|
|
|
|
|
if valDiags.Err() != nil {
|
|
|
|
|
if !strings.Contains(valDiags.Err().Error(), tc.expectedErr) {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, valDiags.Err())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
@@ -859,170 +596,312 @@ func TestCloud_setUnavailableTerraformVersion(t *testing.T) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestCloud_setConfigurationFields(t *testing.T) {
|
|
|
|
|
originalForceBackendEnv := os.Getenv("TF_FORCE_LOCAL_BACKEND")
|
|
|
|
|
|
|
|
|
|
func TestCloud_setConfigurationFieldsHappyPath(t *testing.T) {
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
|
obj cty.Value
|
|
|
|
|
envVars map[string]string
|
|
|
|
|
expectedHostname string
|
|
|
|
|
expectedOrganziation string
|
|
|
|
|
expectedOrganization string
|
|
|
|
|
expectedWorkspaceName string
|
|
|
|
|
expectedProjectName string
|
|
|
|
|
expectedWorkspaceTags []string
|
|
|
|
|
expectedWorkspaceTags map[string]struct{}
|
|
|
|
|
expectedForceLocal bool
|
|
|
|
|
setEnv func()
|
|
|
|
|
resetEnv func()
|
|
|
|
|
expectedErr string
|
|
|
|
|
}{
|
|
|
|
|
"with hostname set": {
|
|
|
|
|
"with hostname, organization and tags set": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"hostname": cty.StringVal("hashicorp.com"),
|
|
|
|
|
"organization": cty.StringVal("opentofu"),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("bar")}),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedHostname: "hashicorp.com",
|
|
|
|
|
expectedOrganziation: "hashicorp",
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedOrganization: "opentofu",
|
|
|
|
|
expectedWorkspaceTags: map[string]struct{}{"foo": {}, "bar": {}},
|
|
|
|
|
},
|
|
|
|
|
"with workspace name set": {
|
|
|
|
|
"with hostname and workspace name set": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"hostname": cty.StringVal("hashicorp.com"),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedHostname: "hashicorp.com",
|
|
|
|
|
expectedOrganziation: "hashicorp",
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedWorkspaceName: "prod",
|
|
|
|
|
},
|
|
|
|
|
"with workspace tags set": {
|
|
|
|
|
"with hostname and project name set": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"hostname": cty.StringVal("hashicorp.com"),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal(
|
|
|
|
|
[]cty.Value{
|
|
|
|
|
cty.StringVal("billing"),
|
|
|
|
|
},
|
|
|
|
|
),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedHostname: "hashicorp.com",
|
|
|
|
|
expectedOrganziation: "hashicorp",
|
|
|
|
|
expectedWorkspaceTags: []string{"billing"},
|
|
|
|
|
},
|
|
|
|
|
"with project name set": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"hostname": cty.StringVal("hashicorp.com"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("prod"),
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.StringVal("my-project"),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedHostname: "hashicorp.com",
|
|
|
|
|
expectedOrganziation: "hashicorp",
|
|
|
|
|
expectedWorkspaceName: "prod",
|
|
|
|
|
expectedProjectName: "my-project",
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedProjectName: "my-project",
|
|
|
|
|
},
|
|
|
|
|
"with force local set": {
|
|
|
|
|
"with hostname and force local set (env var)": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.StringVal("hashicorp"),
|
|
|
|
|
"hostname": cty.StringVal("hashicorp.com"),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
expectedHostname: "hashicorp.com",
|
|
|
|
|
expectedOrganziation: "hashicorp",
|
|
|
|
|
setEnv: func() {
|
|
|
|
|
os.Setenv("TF_FORCE_LOCAL_BACKEND", "1")
|
|
|
|
|
},
|
|
|
|
|
resetEnv: func() {
|
|
|
|
|
os.Setenv("TF_FORCE_LOCAL_BACKEND", originalForceBackendEnv)
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_FORCE_LOCAL_BACKEND": "1",
|
|
|
|
|
},
|
|
|
|
|
expectedForceLocal: true,
|
|
|
|
|
},
|
|
|
|
|
"with hostname and workspace tags set, and tags overwritten by TF_WORKSPACE": {
|
|
|
|
|
// see: https://github.com/opentofu/opentofu/issues/814
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("bar")}),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "foo",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedWorkspaceName: "foo",
|
|
|
|
|
expectedWorkspaceTags: nil,
|
|
|
|
|
},
|
|
|
|
|
"with hostname and workspace name set, and TF_WORKSPACE specified": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.StringVal("old"),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "new",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedWorkspaceName: "old",
|
|
|
|
|
expectedWorkspaceTags: nil,
|
|
|
|
|
},
|
|
|
|
|
"with hostname and project set, and project overwritten by TF_CLOUD_PROJECT": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.StringVal("old"),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_PROJECT": "new",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedProjectName: "old",
|
|
|
|
|
},
|
|
|
|
|
"with hostname set, and project specified by TF_CLOUD_PROJECT": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_PROJECT": "new",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedProjectName: "new",
|
|
|
|
|
},
|
|
|
|
|
"with hostname set, and organization specified by TF_CLOUD_ORGANIZATION": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_ORGANIZATION": "my-org",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedOrganization: "my-org",
|
|
|
|
|
},
|
|
|
|
|
"with hostname set, and TF_CLOUD_HOSTNAME defined": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "new",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
},
|
|
|
|
|
"with hostname specified by TF_CLOUD_HOSTNAME": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"token": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.NullVal(cty.Set(cty.String)),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "new",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "new",
|
|
|
|
|
},
|
|
|
|
|
"with nothing set, all configured using env vars": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_CLOUD_HOSTNAME": "opentofu.org",
|
|
|
|
|
"TF_CLOUD_ORGANIZATION": "opentofu",
|
|
|
|
|
"TF_WORKSPACE": "foo",
|
|
|
|
|
"TF_CLOUD_PROJECT": "bar",
|
|
|
|
|
},
|
|
|
|
|
expectedHostname: "opentofu.org",
|
|
|
|
|
expectedOrganization: "opentofu",
|
|
|
|
|
expectedWorkspaceName: "foo",
|
|
|
|
|
expectedProjectName: "bar",
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
|
b := &Cloud{}
|
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
|
for k, v := range tc.envVars {
|
|
|
|
|
t.Setenv(k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// if `setEnv` is set, then we expect `resetEnv` to also be set
|
|
|
|
|
if tc.setEnv != nil {
|
|
|
|
|
tc.setEnv()
|
|
|
|
|
defer tc.resetEnv()
|
|
|
|
|
}
|
|
|
|
|
b := &Cloud{}
|
|
|
|
|
errDiags := b.setConfigurationFields(tc.obj)
|
|
|
|
|
|
|
|
|
|
errDiags := b.setConfigurationFields(tc.obj)
|
|
|
|
|
if errDiags.HasErrors() || tc.expectedErr != "" {
|
|
|
|
|
actualErr := errDiags.Err().Error()
|
|
|
|
|
if !strings.Contains(actualErr, tc.expectedErr) {
|
|
|
|
|
if errDiags.HasErrors() {
|
|
|
|
|
t.Fatalf("%s: unexpected validation result: %v", name, errDiags.Err())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if tc.expectedHostname != "" && b.hostname != tc.expectedHostname {
|
|
|
|
|
t.Fatalf("%s: expected hostname %s to match configured hostname %s", name, b.hostname, tc.expectedHostname)
|
|
|
|
|
}
|
|
|
|
|
if tc.expectedOrganziation != "" && b.organization != tc.expectedOrganziation {
|
|
|
|
|
t.Fatalf("%s: expected organization (%s) to match configured organization (%s)", name, b.organization, tc.expectedOrganziation)
|
|
|
|
|
}
|
|
|
|
|
if tc.expectedWorkspaceName != "" && b.WorkspaceMapping.Name != tc.expectedWorkspaceName {
|
|
|
|
|
t.Fatalf("%s: expected workspace name mapping (%s) to match configured workspace name (%s)", name, b.WorkspaceMapping.Name, tc.expectedWorkspaceName)
|
|
|
|
|
}
|
|
|
|
|
if len(tc.expectedWorkspaceTags) > 0 {
|
|
|
|
|
presentSet := make(map[string]struct{})
|
|
|
|
|
for _, tag := range b.WorkspaceMapping.Tags {
|
|
|
|
|
presentSet[tag] = struct{}{}
|
|
|
|
|
if b.hostname != tc.expectedHostname {
|
|
|
|
|
t.Fatalf("%s: expected hostname %s to match configured hostname %s", name, b.hostname, tc.expectedHostname)
|
|
|
|
|
}
|
|
|
|
|
if b.organization != tc.expectedOrganization {
|
|
|
|
|
t.Fatalf("%s: expected organization (%s) to match configured organization (%s)", name, b.organization, tc.expectedOrganization)
|
|
|
|
|
}
|
|
|
|
|
if b.WorkspaceMapping.Name != tc.expectedWorkspaceName {
|
|
|
|
|
t.Fatalf("%s: expected workspace name mapping (%s) to match configured workspace name (%s)", name, b.WorkspaceMapping.Name, tc.expectedWorkspaceName)
|
|
|
|
|
}
|
|
|
|
|
if b.forceLocal != tc.expectedForceLocal {
|
|
|
|
|
t.Fatalf("%s: expected force local backend to be set to %v", name, tc.expectedForceLocal)
|
|
|
|
|
}
|
|
|
|
|
if b.WorkspaceMapping.Project != tc.expectedProjectName {
|
|
|
|
|
t.Fatalf("%s: expected project name mapping (%s) to match configured project name (%s)", name, b.WorkspaceMapping.Project, tc.expectedProjectName)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
expectedSet := make(map[string]struct{})
|
|
|
|
|
for _, tag := range tc.expectedWorkspaceTags {
|
|
|
|
|
expectedSet[tag] = struct{}{}
|
|
|
|
|
// read map of configured tags
|
|
|
|
|
gotTags := map[string]struct{}{}
|
|
|
|
|
for _, v := range b.WorkspaceMapping.Tags {
|
|
|
|
|
gotTags[v] = struct{}{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var missing []string
|
|
|
|
|
var unexpected []string
|
|
|
|
|
if len(gotTags) != len(tc.expectedWorkspaceTags) {
|
|
|
|
|
t.Fatalf("%s: unordered workspace tags (%v) don't match configuration (%v)", name, gotTags, tc.expectedWorkspaceTags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, expected := range tc.expectedWorkspaceTags {
|
|
|
|
|
if _, ok := presentSet[expected]; !ok {
|
|
|
|
|
missing = append(missing, expected)
|
|
|
|
|
for k := range tc.expectedWorkspaceTags {
|
|
|
|
|
if _, ok := gotTags[k]; !ok {
|
|
|
|
|
t.Fatalf("%s: unordered workspace tags (%v) don't match configuration (%v)", name, gotTags, tc.expectedWorkspaceTags)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, actual := range b.WorkspaceMapping.Tags {
|
|
|
|
|
if _, ok := expectedSet[actual]; !ok {
|
|
|
|
|
unexpected = append(unexpected, actual)
|
|
|
|
|
}
|
|
|
|
|
func TestCloud_setConfigurationFieldsUnhappyPath(t *testing.T) {
|
|
|
|
|
cases := map[string]struct {
|
|
|
|
|
obj cty.Value
|
|
|
|
|
envVars map[string]string
|
|
|
|
|
wantSummary string
|
|
|
|
|
wantDetail string
|
|
|
|
|
}{
|
|
|
|
|
"cloud block is not configured": {
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.NullVal(cty.String),
|
|
|
|
|
"workspaces": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
wantSummary: "Hostname is required for the cloud backend",
|
|
|
|
|
wantDetail: `OpenTofu does not provide a default "hostname" attribute, so it must be set to the hostname of the cloud backend.`,
|
|
|
|
|
},
|
|
|
|
|
"with hostname and workspace tags set, and tags overwritten by TF_WORKSPACE": {
|
|
|
|
|
// see: https://github.com/opentofu/opentofu/issues/814
|
|
|
|
|
obj: cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"organization": cty.NullVal(cty.String),
|
|
|
|
|
"hostname": cty.StringVal("opentofu.org"),
|
|
|
|
|
"workspaces": cty.ObjectVal(map[string]cty.Value{
|
|
|
|
|
"name": cty.NullVal(cty.String),
|
|
|
|
|
"tags": cty.SetVal([]cty.Value{cty.StringVal("foo"), cty.StringVal("bar")}),
|
|
|
|
|
"project": cty.NullVal(cty.String),
|
|
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
envVars: map[string]string{
|
|
|
|
|
"TF_WORKSPACE": "qux",
|
|
|
|
|
},
|
|
|
|
|
wantSummary: invalidWorkspaceConfigMisconfigurationEnvVar.Description().Summary,
|
|
|
|
|
wantDetail: invalidWorkspaceConfigMisconfigurationEnvVar.Description().Detail,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for name, tc := range cases {
|
|
|
|
|
t.Run(name, func(t *testing.T) {
|
|
|
|
|
for k, v := range tc.envVars {
|
|
|
|
|
t.Setenv(k, v)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(missing) > 0 {
|
|
|
|
|
t.Fatalf("%s: expected workspace tag mapping (%s) to contain the following tags: %s", name, b.WorkspaceMapping.Tags, missing)
|
|
|
|
|
b := &Cloud{}
|
|
|
|
|
errDiags := b.setConfigurationFields(tc.obj)
|
|
|
|
|
if (tc.wantDetail != "" || tc.wantSummary != "") != errDiags.HasErrors() {
|
|
|
|
|
t.Fatalf("%s error expected", name)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(unexpected) > 0 {
|
|
|
|
|
t.Fatalf("%s: expected workspace tag mapping (%s) to NOT contain the following tags: %s", name, b.WorkspaceMapping.Tags, unexpected)
|
|
|
|
|
gotSummary := errDiags[0].Description().Summary
|
|
|
|
|
if gotSummary != tc.wantSummary {
|
|
|
|
|
t.Fatalf("%s diagnostic summary mismatch, want: %s, got: %s", name, tc.wantSummary, gotSummary)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
if tc.expectedForceLocal != false && b.forceLocal != tc.expectedForceLocal {
|
|
|
|
|
t.Fatalf("%s: expected force local backend to be set ", name)
|
|
|
|
|
}
|
|
|
|
|
if tc.expectedProjectName != "" && b.WorkspaceMapping.Project != tc.expectedProjectName {
|
|
|
|
|
t.Fatalf("%s: expected project name mapping (%s) to match configured project name (%s)", name, b.WorkspaceMapping.Project, tc.expectedProjectName)
|
|
|
|
|
}
|
|
|
|
|
gotDetail := errDiags[0].Description().Detail
|
|
|
|
|
if gotDetail != tc.wantDetail {
|
|
|
|
|
t.Fatalf("%s diagnostic details mismatch, want: %s, got: %s", name, tc.wantDetail, gotDetail)
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|