Skip to content

Commit 4aed6c9

Browse files
committed
Add tests for TF Distribution and fix styles
Signed-off-by: Andrew Borg <[email protected]>
1 parent 5bbf855 commit 4aed6c9

16 files changed

+655
-59
lines changed

Diff for: cmd/server.go

+15-16
Original file line numberDiff line numberDiff line change
@@ -142,22 +142,21 @@ const (
142142
SSLCertFileFlag = "ssl-cert-file"
143143
SSLKeyFileFlag = "ssl-key-file"
144144
RestrictFileList = "restrict-file-list"
145-
// TFDistributionFlag is deprecated for DefaultTFDistributionFlag
146-
TFDistributionFlag = "tf-distribution"
147-
TFDownloadFlag = "tf-download"
148-
TFDownloadURLFlag = "tf-download-url"
149-
UseTFPluginCache = "use-tf-plugin-cache"
150-
VarFileAllowlistFlag = "var-file-allowlist"
151-
VCSStatusName = "vcs-status-name"
152-
IgnoreVCSStatusNames = "ignore-vcs-status-names"
153-
TFEHostnameFlag = "tfe-hostname"
154-
TFELocalExecutionModeFlag = "tfe-local-execution-mode"
155-
TFETokenFlag = "tfe-token"
156-
WriteGitCredsFlag = "write-git-creds" // nolint: gosec
157-
WebBasicAuthFlag = "web-basic-auth"
158-
WebUsernameFlag = "web-username"
159-
WebPasswordFlag = "web-password"
160-
WebsocketCheckOrigin = "websocket-check-origin"
145+
TFDistributionFlag = "tf-distribution" // deprecated for DefaultTFDistributionFlag
146+
TFDownloadFlag = "tf-download"
147+
TFDownloadURLFlag = "tf-download-url"
148+
UseTFPluginCache = "use-tf-plugin-cache"
149+
VarFileAllowlistFlag = "var-file-allowlist"
150+
VCSStatusName = "vcs-status-name"
151+
IgnoreVCSStatusNames = "ignore-vcs-status-names"
152+
TFEHostnameFlag = "tfe-hostname"
153+
TFELocalExecutionModeFlag = "tfe-local-execution-mode"
154+
TFETokenFlag = "tfe-token"
155+
WriteGitCredsFlag = "write-git-creds" // nolint: gosec
156+
WebBasicAuthFlag = "web-basic-auth"
157+
WebUsernameFlag = "web-username"
158+
WebPasswordFlag = "web-password"
159+
WebsocketCheckOrigin = "websocket-check-origin"
161160

162161
// NOTE: Must manually set these as defaults in the setDefaults function.
163162
DefaultADBasicUser = ""

Diff for: cmd/server_test.go

+40
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,46 @@ func TestExecute_AutoplanFileList(t *testing.T) {
978978
}
979979
}
980980

981+
func TestExecute_ValidateDefaultTFDistribution(t *testing.T) {
982+
cases := []struct {
983+
description string
984+
flags map[string]interface{}
985+
expectErr string
986+
}{
987+
{
988+
"terraform",
989+
map[string]interface{}{
990+
DefaultTFDistributionFlag: "terraform",
991+
},
992+
"",
993+
},
994+
{
995+
"opentofu",
996+
map[string]interface{}{
997+
DefaultTFDistributionFlag: "opentofu",
998+
},
999+
"",
1000+
},
1001+
{
1002+
"errs on invalid distribution",
1003+
map[string]interface{}{
1004+
DefaultTFDistributionFlag: "invalid_distribution",
1005+
},
1006+
"invalid tf distribution: expected one of terraform or opentofu",
1007+
},
1008+
}
1009+
for _, testCase := range cases {
1010+
t.Log("Should validate default tf distribution when " + testCase.description)
1011+
c := setupWithDefaults(testCase.flags, t)
1012+
err := c.Execute()
1013+
if testCase.expectErr != "" {
1014+
ErrEquals(t, testCase.expectErr, err)
1015+
} else {
1016+
Ok(t, err)
1017+
}
1018+
}
1019+
}
1020+
9811021
func setup(flags map[string]interface{}, t *testing.T) *cobra.Command {
9821022
vipr := viper.New()
9831023
for k, v := range flags {

Diff for: server/controllers/events/events_controller_e2e_test.go

+1
Original file line numberDiff line numberDiff line change
@@ -1474,6 +1474,7 @@ func setupE2E(t *testing.T, repoDir string, opt setupOption) (events_controllers
14741474
StateRmStepRunner: runtime.NewStateRmStepRunner(terraformClient, defaultTFDistribution, defaultTFVersion),
14751475
RunStepRunner: &runtime.RunStepRunner{
14761476
TerraformExecutor: terraformClient,
1477+
DefaultTFDistribution: defaultTFDistribution,
14771478
DefaultTFVersion: defaultTFVersion,
14781479
ProjectCmdOutputHandler: projectCmdOutputHandler,
14791480
},

Diff for: server/core/config/raw/project.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ func validImportReq(value interface{}) error {
211211
func validDistribution(value interface{}) error {
212212
distribution := value.(*string)
213213
if distribution != nil && *distribution != "terraform" && *distribution != "opentofu" {
214-
return fmt.Errorf("%q is not a valid terraform_distribution, only %q and %q are supported", *distribution, "terraform", "opentofu")
214+
return fmt.Errorf("'%s' is not a valid terraform_distribution, only '%s' and '%s' are supported", *distribution, "terraform", "opentofu")
215215
}
216216
return nil
217217
}

Diff for: server/core/runtime/apply_step_runner_test.go

+37-1
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func TestRun_AppliesCorrectProjectPlan(t *testing.T) {
113113
Assert(t, os.IsNotExist(err), "planfile should be deleted")
114114
}
115115

116-
func TestRun_UsesConfiguredTFVersion(t *testing.T) {
116+
func TestApplyStepRunner_TestRun_UsesConfiguredTFVersion(t *testing.T) {
117117
tmpDir := t.TempDir()
118118
planPath := filepath.Join(tmpDir, "workspace.tfplan")
119119
err := os.WriteFile(planPath, nil, 0600)
@@ -147,6 +147,42 @@ func TestRun_UsesConfiguredTFVersion(t *testing.T) {
147147
Assert(t, os.IsNotExist(err), "planfile should be deleted")
148148
}
149149

150+
func TestApplyStepRunner_TestRun_UsesConfiguredDistribution(t *testing.T) {
151+
tmpDir := t.TempDir()
152+
planPath := filepath.Join(tmpDir, "workspace.tfplan")
153+
err := os.WriteFile(planPath, nil, 0600)
154+
Ok(t, err)
155+
156+
logger := logging.NewNoopLogger(t)
157+
mockDownloader := mocks.NewMockDownloader()
158+
tfDistribution := tf.NewDistributionTerraformWithDownloader(mockDownloader)
159+
tfVersion, _ := version.NewVersion("0.11.0")
160+
projTFDistribution := "opentofu"
161+
ctx := command.ProjectContext{
162+
Workspace: "workspace",
163+
RepoRelDir: ".",
164+
EscapedCommentArgs: []string{"comment", "args"},
165+
TerraformDistribution: &projTFDistribution,
166+
Log: logger,
167+
}
168+
169+
RegisterMockTestingT(t)
170+
terraform := tfclientmocks.NewMockClient()
171+
o := runtime.ApplyStepRunner{
172+
TerraformExecutor: terraform,
173+
DefaultTFDistribution: tfDistribution,
174+
DefaultTFVersion: tfVersion,
175+
}
176+
When(terraform.RunCommandWithVersion(Any[command.ProjectContext](), Any[string](), Any[[]string](), Any[map[string]string](), NotEq[tf.Distribution](tfDistribution), Any[*version.Version](), Any[string]())).
177+
ThenReturn("output", nil)
178+
output, err := o.Run(ctx, []string{"extra", "args"}, tmpDir, map[string]string(nil))
179+
Ok(t, err)
180+
Equals(t, "output", output)
181+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(ctx), Eq(tmpDir), Eq([]string{"apply", "-input=false", "extra", "args", "comment", "args", fmt.Sprintf("%q", planPath)}), Eq(map[string]string(nil)), NotEq[tf.Distribution](tfDistribution), Eq(tfVersion), Eq("workspace"))
182+
_, err = os.Stat(planPath)
183+
Assert(t, os.IsNotExist(err), "planfile should be deleted")
184+
}
185+
150186
// Apply ignores the -target flag when used with a planfile so we should give
151187
// an error if it's being used with -target.
152188
func TestRun_UsingTarget(t *testing.T) {

Diff for: server/core/runtime/import_step_runner_test.go

+41
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,44 @@ func TestImportStepRunner_Run_Workspace(t *testing.T) {
8686
_, err = os.Stat(planPath)
8787
Assert(t, os.IsNotExist(err), "planfile should be deleted")
8888
}
89+
90+
func TestImportStepRunner_Run_UsesConfiguredDistribution(t *testing.T) {
91+
logger := logging.NewNoopLogger(t)
92+
workspace := "something"
93+
tmpDir := t.TempDir()
94+
planPath := filepath.Join(tmpDir, fmt.Sprintf("%s.tfplan", workspace))
95+
err := os.WriteFile(planPath, nil, 0600)
96+
Ok(t, err)
97+
98+
projTFDistribution := "opentofu"
99+
context := command.ProjectContext{
100+
Log: logger,
101+
EscapedCommentArgs: []string{"-var", "foo=bar", "addr", "id"},
102+
Workspace: workspace,
103+
TerraformDistribution: &projTFDistribution,
104+
}
105+
106+
RegisterMockTestingT(t)
107+
terraform := tfclientmocks.NewMockClient()
108+
tfVersion, _ := version.NewVersion("0.15.0")
109+
mockDownloader := mocks.NewMockDownloader()
110+
tfDistribution := tf.NewDistributionTerraformWithDownloader(mockDownloader)
111+
s := NewImportStepRunner(terraform, tfDistribution, tfVersion)
112+
113+
When(terraform.RunCommandWithVersion(Any[command.ProjectContext](), Any[string](), Any[[]string](), Any[map[string]string](), Any[tf.Distribution](), Any[*version.Version](), Any[string]())).
114+
ThenReturn("output", nil)
115+
output, err := s.Run(context, []string{}, tmpDir, map[string]string(nil))
116+
Ok(t, err)
117+
Equals(t, "output", output)
118+
119+
// switch workspace
120+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(context), Eq(tmpDir), Eq([]string{"workspace", "show"}), Eq(map[string]string(nil)), NotEq(tfDistribution), Eq(tfVersion), Eq(workspace))
121+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(context), Eq(tmpDir), Eq([]string{"workspace", "select", workspace}), Eq(map[string]string(nil)), NotEq(tfDistribution), Eq(tfVersion), Eq(workspace))
122+
123+
// exec import
124+
commands := []string{"import", "-var", "foo=bar", "addr", "id"}
125+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(context), Eq(tmpDir), Eq(commands), Eq(map[string]string(nil)), NotEq(tfDistribution), Eq(tfVersion), Eq(workspace))
126+
127+
_, err = os.Stat(planPath)
128+
Assert(t, os.IsNotExist(err), "planfile should be deleted")
129+
}

Diff for: server/core/runtime/init_step_runner_test.go

+67
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,73 @@ func TestRun_UsesGetOrInitForRightVersion(t *testing.T) {
8181
}
8282
}
8383

84+
func TestInitStepRunner_TestRun_UsesConfiguredDistribution(t *testing.T) {
85+
RegisterMockTestingT(t)
86+
mockDownloader := mocks.NewMockDownloader()
87+
tfDistribution := tf.NewDistributionTerraformWithDownloader(mockDownloader)
88+
cases := []struct {
89+
version string
90+
distribution string
91+
expCmd string
92+
}{
93+
{
94+
"0.8.9",
95+
"opentofu",
96+
"get",
97+
},
98+
{
99+
"0.8.9",
100+
"terraform",
101+
"get",
102+
},
103+
{
104+
"0.9.0",
105+
"opentofu",
106+
"init",
107+
},
108+
{
109+
"0.9.1",
110+
"terraform",
111+
"init",
112+
},
113+
}
114+
115+
for _, c := range cases {
116+
t.Run(c.version, func(t *testing.T) {
117+
terraform := tfclientmocks.NewMockClient()
118+
119+
logger := logging.NewNoopLogger(t)
120+
ctx := command.ProjectContext{
121+
Workspace: "workspace",
122+
RepoRelDir: ".",
123+
Log: logger,
124+
TerraformDistribution: &c.distribution,
125+
}
126+
127+
tfVersion, _ := version.NewVersion(c.version)
128+
iso := runtime.InitStepRunner{
129+
TerraformExecutor: terraform,
130+
DefaultTFDistribution: tfDistribution,
131+
DefaultTFVersion: tfVersion,
132+
}
133+
When(terraform.RunCommandWithVersion(Any[command.ProjectContext](), Any[string](), Any[[]string](), Any[map[string]string](), Any[tf.Distribution](), Any[*version.Version](), Any[string]())).
134+
ThenReturn("output", nil)
135+
136+
output, err := iso.Run(ctx, []string{"extra", "args"}, "/path", map[string]string(nil))
137+
Ok(t, err)
138+
// When there is no error, should not return init output to PR.
139+
Equals(t, "", output)
140+
141+
// If using init then we specify -input=false but not for get.
142+
expArgs := []string{c.expCmd, "-input=false", "-upgrade", "extra", "args"}
143+
if c.expCmd == "get" {
144+
expArgs = []string{c.expCmd, "-upgrade", "extra", "args"}
145+
}
146+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(ctx), Eq("/path"), Eq(expArgs), Eq(map[string]string(nil)), NotEq(tfDistribution), Eq(tfVersion), Eq("workspace"))
147+
})
148+
}
149+
}
150+
84151
func TestRun_ShowInitOutputOnError(t *testing.T) {
85152
// If there was an error during init then we want the output to be returned.
86153
RegisterMockTestingT(t)

Diff for: server/core/runtime/plan_step_runner_test.go

+76
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,82 @@ Plan: 0 to add, 0 to change, 1 to destroy.`, output)
554554
}
555555
}
556556

557+
func TestPlanStepRunner_TestRun_UsesConfiguredDistribution(t *testing.T) {
558+
RegisterMockTestingT(t)
559+
560+
expPlanArgs := []string{
561+
"plan",
562+
"-input=false",
563+
"-refresh",
564+
"-out",
565+
fmt.Sprintf("%q", "/path/default.tfplan"),
566+
"extra",
567+
"args",
568+
"comment",
569+
"args",
570+
}
571+
572+
cases := []struct {
573+
name string
574+
tfVersion string
575+
tfDistribution string
576+
}{
577+
{
578+
"stable version",
579+
"0.12.0",
580+
"terraform",
581+
},
582+
{
583+
"with prerelease",
584+
"0.14.0-rc1",
585+
"opentofu",
586+
},
587+
}
588+
589+
for _, c := range cases {
590+
t.Run(c.name, func(t *testing.T) {
591+
terraform := tfclientmocks.NewMockClient()
592+
commitStatusUpdater := runtimemocks.NewMockStatusUpdater()
593+
asyncTfExec := runtimemocks.NewMockAsyncTFExec()
594+
When(terraform.RunCommandWithVersion(
595+
Any[command.ProjectContext](),
596+
Any[string](),
597+
Any[[]string](),
598+
Any[map[string]string](),
599+
Any[tf.Distribution](),
600+
Any[*version.Version](),
601+
Any[string]())).ThenReturn("output", nil)
602+
603+
mockDownloader := mocks.NewMockDownloader()
604+
tfDistribution := tf.NewDistributionTerraformWithDownloader(mockDownloader)
605+
tfVersion, _ := version.NewVersion(c.tfVersion)
606+
s := runtime.NewPlanStepRunner(terraform, tfDistribution, tfVersion, commitStatusUpdater, asyncTfExec)
607+
ctx := command.ProjectContext{
608+
Workspace: "default",
609+
RepoRelDir: ".",
610+
User: models.User{Username: "username"},
611+
EscapedCommentArgs: []string{"comment", "args"},
612+
Pull: models.PullRequest{
613+
Num: 2,
614+
},
615+
BaseRepo: models.Repo{
616+
FullName: "owner/repo",
617+
Owner: "owner",
618+
Name: "repo",
619+
},
620+
TerraformDistribution: &c.tfDistribution,
621+
}
622+
623+
output, err := s.Run(ctx, []string{"extra", "args"}, "/path", map[string]string(nil))
624+
Ok(t, err)
625+
Equals(t, "output", output)
626+
627+
terraform.VerifyWasCalledOnce().RunCommandWithVersion(Eq(ctx), Eq("/path"), Eq(expPlanArgs), Eq(map[string]string(nil)), NotEq(tfDistribution), Eq(tfVersion), Eq("default"))
628+
})
629+
}
630+
631+
}
632+
557633
type remotePlanMock struct {
558634
// LinesToSend will be sent on the channel.
559635
LinesToSend string

0 commit comments

Comments
 (0)