Skip to content

Commit

Permalink
Fix and update tests
Browse files Browse the repository at this point in the history
  • Loading branch information
adam-verigin committed Dec 21, 2022
1 parent c334cc4 commit e10ed6d
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 4 deletions.
3 changes: 2 additions & 1 deletion server/controllers/events/events_controller_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -914,7 +914,7 @@ func setupE2E(t *testing.T, repoDir, repoConfigFile string) (events_controllers.
GitlabUser: "gitlab-user",
ExecutableName: "atlantis",
}
terraformClient, err := terraform.NewClient(logger, binDir, cacheDir, "", "", "", "default-tf-version", "https://releases.hashicorp.com", &NoopTFDownloader{}, false, projectCmdOutputHandler)
terraformClient, err := terraform.NewClient(logger, binDir, cacheDir, "", "", "", "default-tf-version", "https://releases.hashicorp.com", &NoopTFDownloader{}, false, false, projectCmdOutputHandler)
Ok(t, err)
boltdb, err := db.New(dataDir)
Ok(t, err)
Expand Down Expand Up @@ -1010,6 +1010,7 @@ func setupE2E(t *testing.T, repoDir, repoConfigFile string) (events_controllers.
false,
statsScope,
logger,
terraformClient,
)

showStepRunner, err := runtime.NewShowStepRunner(terraformClient, defaultTFVersion)
Expand Down
28 changes: 26 additions & 2 deletions server/core/terraform/terraform_client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func TestNewClient_NoTF(t *testing.T) {
defer tempSetEnv(t, "PATH", tmp)()

_, err := terraform.NewClient(logger, binDir, cacheDir, "", "", "", cmd.DefaultTFVersionFlag, cmd.DefaultTFDownloadURL, nil, false, true, projectCmdOutputHandler)
ErrEquals(t, "terraform not found in $PATH. Set --default-tf-version or download terraform from https://www.terraform.io/downloads.html", err)
ErrEquals(t, "terraform not found in $PATH. Set --default-tf-version or download terraform from https://developer.hashicorp.com/terraform/downloads", err)
}

// Test that if the default-tf flag is set and that binary is in our PATH
Expand Down Expand Up @@ -282,7 +282,7 @@ func TestRunCommandWithVersion_DLsTF(t *testing.T) {
Equals(t, "\nTerraform v99.99.99\n\n", output)
}

// Test the EnsureVersion downloads terraform.
// Test that EnsureVersion downloads terraform.
func TestEnsureVersion_downloaded(t *testing.T) {
logger := logging.NewNoopLogger(t)
RegisterMockTestingT(t)
Expand Down Expand Up @@ -312,6 +312,30 @@ func TestEnsureVersion_downloaded(t *testing.T) {
mockDownloader.VerifyWasCalledEventually(Once(), 2*time.Second).GetFile(filepath.Join(tmp, "bin", "terraform99.99.99"), expURL)
}

// Test that EnsureVersion throws an error when downloads are disabled
func TestEnsureVersion_downloaded_downloadingDisabled(t *testing.T) {
logger := logging.NewNoopLogger(t)
RegisterMockTestingT(t)
_, binDir, cacheDir := mkSubDirs(t)
projectCmdOutputHandler := jobmocks.NewMockProjectCommandOutputHandler()

mockDownloader := mocks.NewMockDownloader()

disableDownloads := true
c, err := terraform.NewTestClient(logger, binDir, cacheDir, "", "", "0.11.10", cmd.DefaultTFVersionFlag, cmd.DefaultTFDownloadURL, mockDownloader, disableDownloads, true, projectCmdOutputHandler)
Ok(t, err)

Equals(t, "0.11.10", c.DefaultVersion().String())

v, err := version.NewVersion("99.99.99")
Ok(t, err)

err = c.EnsureVersion(logger, v)
ErrContains(t, "could not find terraform version", err)
ErrContains(t, "downloads are disabled", err)
mockDownloader.VerifyWasCalled(Never())
}

// tempSetEnv sets env var key to value. It returns a function that when called
// will reset the env var to its original value.
func tempSetEnv(t *testing.T, key string, value string) func() {
Expand Down
232 changes: 232 additions & 0 deletions server/events/project_command_builder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,7 @@ projects:
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

for _, c := range cases {
t.Run(c.Description, func(t *testing.T) {
Expand Down Expand Up @@ -420,6 +421,7 @@ projects:
}

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -596,6 +598,7 @@ projects:
}

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -769,6 +772,7 @@ projects:
}

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -864,6 +868,7 @@ func TestDefaultProjectCommandBuilder_BuildMultiApply(t *testing.T) {
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -952,6 +957,7 @@ projects:
logger := logging.NewNoopLogger(t)
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")
terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -1035,6 +1041,7 @@ func TestDefaultProjectCommandBuilder_EscapeArgs(t *testing.T) {
}

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -1241,7 +1248,229 @@ projects:
ApprovedReq: false,
UnDivergedReq: false,
}

var versions []string
for i := 0; i < 32; i++ {
versions = append(versions, fmt.Sprintf("0.12.%d", i))
}
terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn(versions, nil)

builder := events.NewProjectCommandBuilder(
false,
&config.ParserValidator{},
&events.DefaultProjectFinder{},
vcsClient,
workingDir,
events.NewDefaultWorkingDirLocker(),
valid.NewGlobalCfgFromArgs(globalCfgArgs),
&events.DefaultPendingPlanFinder{},
&events.CommentParser{ExecutableName: "atlantis"},
false,
false,
"",
"**/*.tf,**/*.tfvars,**/*.tfvars.json,**/terragrunt.hcl,**/.terraform.lock.hcl",
false,
scope,
logger,
terraformClient,
)

actCtxs, err := builder.BuildPlanCommands(
&command.Context{
Log: logger,
Scope: scope,
},
&events.CommentCommand{
RepoRelDir: "",
Flags: nil,
Name: command.Plan,
Verbose: false,
})

Ok(t, err)
Equals(t, len(testCase.Exp), len(actCtxs))
for _, actCtx := range actCtxs {
if testCase.Exp[actCtx.RepoRelDir] != nil {
Assert(t, actCtx.TerraformVersion != nil, "TerraformVersion is nil.")
Equals(t, testCase.Exp[actCtx.RepoRelDir], actCtx.TerraformVersion.Segments())
} else {
Assert(t, actCtx.TerraformVersion == nil, "TerraformVersion is supposed to be nil.")
}
}
})
}
}

// If TF downloads are disabled, test that terraform version is used when specified in terraform configuration only if an exact version
func TestDefaultProjectCommandBuilder_TerraformVersion_DownloadsDisabled(t *testing.T) {
// For the following tests:
// If terraform configuration is used, result should be `0.12.8`.
// If project configuration is used, result should be `0.12.6`.
// If an inexact version is used, the result should be `nil`
// If default is to be used, result should be `nil`.

baseVersionConfig := `
terraform {
required_version = "%s0.12.8"
}
`

atlantisYamlContent := `
version: 3
projects:
- dir: project1 # project1 uses the defaults
terraform_version: v0.12.6
`

exactSymbols := []string{"", "="}
// Depending on when the tests are run, the > and >= matching versions will have to be increased.
// It's probably not worth testing the terraform-switcher version here so we only test <, <=, and ~>.
// One way to test this in the future is to mock tfswitcher.GetTFList() to return the highest
// version of 1.3.5.
// nonExactSymbols := []string{">", ">=", "<", "<=", "~>"}
nonExactSymbols := []string{"<", "<=", "~>"}
nonExactVersions := map[string]map[string][]int{
// ">": {
// "project1": nil,
// },
// ">=": {
// "project1": nil,
// },
"<": {
"project1": nil,
},
"<=": {
"project1": nil,
},
"~>": {
"project1": nil,
},
}

type testCase struct {
DirStructure map[string]interface{}
AtlantisYAML string
ModifiedFiles []string
Exp map[string][]int
}

testCases := make(map[string]testCase)

for _, exactSymbol := range exactSymbols {
testCases[fmt.Sprintf("exact version in terraform config using \"%s\"", exactSymbol)] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": fmt.Sprintf(baseVersionConfig, exactSymbol),
},
},
ModifiedFiles: []string{"project1/main.tf"},
Exp: map[string][]int{
"project1": {0, 12, 8},
},
}
}

for _, nonExactSymbol := range nonExactSymbols {
testCases[fmt.Sprintf("non-exact version in terraform config using \"%s\"", nonExactSymbol)] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": fmt.Sprintf(baseVersionConfig, nonExactSymbol),
},
},
ModifiedFiles: []string{"project1/main.tf"},
Exp: nonExactVersions[nonExactSymbol],
}
}

// atlantis.yaml should take precedence over terraform config
testCases["with project config and terraform config"] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": fmt.Sprintf(baseVersionConfig, exactSymbols[0]),
},
valid.DefaultAtlantisFile: atlantisYamlContent,
},
ModifiedFiles: []string{"project1/main.tf", "project2/main.tf"},
Exp: map[string][]int{
"project1": {0, 12, 6},
},
}

testCases["with project config only"] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": nil,
},
valid.DefaultAtlantisFile: atlantisYamlContent,
},
ModifiedFiles: []string{"project1/main.tf"},
Exp: map[string][]int{
"project1": {0, 12, 6},
},
}

testCases["neither project config or terraform config"] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": nil,
},
},
ModifiedFiles: []string{"project1/main.tf", "project2/main.tf"},
Exp: map[string][]int{
"project1": nil,
},
}

testCases["project with different terraform config"] = testCase{
DirStructure: map[string]interface{}{
"project1": map[string]interface{}{
"main.tf": fmt.Sprintf(baseVersionConfig, exactSymbols[0]),
},
"project2": map[string]interface{}{
"main.tf": strings.Replace(fmt.Sprintf(baseVersionConfig, exactSymbols[0]), "0.12.8", "0.12.9", -1),
},
},
ModifiedFiles: []string{"project1/main.tf", "project2/main.tf"},
Exp: map[string][]int{
"project1": {0, 12, 8},
"project2": {0, 12, 9},
},
}

logger := logging.NewNoopLogger(t)
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")

for name, testCase := range testCases {
t.Run(name, func(t *testing.T) {
RegisterMockTestingT(t)

tmpDir := DirStructure(t, testCase.DirStructure)

vcsClient := vcsmocks.NewMockClient()
When(vcsClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn(testCase.ModifiedFiles, nil)

workingDir := mocks.NewMockWorkingDir()
When(workingDir.Clone(
matchers.AnyPtrToLoggingSimpleLogger(),
matchers.AnyModelsRepo(),
matchers.AnyModelsPullRequest(),
AnyString())).ThenReturn(tmpDir, false, nil)

When(workingDir.GetWorkingDir(
matchers.AnyModelsRepo(),
matchers.AnyModelsPullRequest(),
AnyString())).ThenReturn(tmpDir, nil)

globalCfgArgs := valid.GlobalCfgArgs{
AllowRepoCfg: true,
MergeableReq: false,
ApprovedReq: false,
UnDivergedReq: false,
}

terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -1334,6 +1563,7 @@ parallel_plan: true`,
}
scope, _, _ := metrics.NewLoggingScope(logger, "atlantis")
terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down Expand Up @@ -1396,6 +1626,7 @@ func TestDefaultProjectCommandBuilder_WithPolicyCheckEnabled_BuildAutoplanComman

globalCfg := valid.NewGlobalCfgFromArgs(globalCfgArgs)
terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
true,
Expand Down Expand Up @@ -1481,6 +1712,7 @@ func TestDefaultProjectCommandBuilder_BuildVersionCommand(t *testing.T) {
UnDivergedReq: false,
}
terraformClient := terraform_mocks.NewMockClient()
When(terraformClient.ListAvailableVersions(matchers.AnyLoggingSimpleLogging())).ThenReturn([]string{}, nil)

builder := events.NewProjectCommandBuilder(
false,
Expand Down
2 changes: 1 addition & 1 deletion server/events/project_command_context_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ func getTfVersion(ctx *command.Context, terraformClient terraform.Client, absPro
if len(tfVersions) == 0 {
// Fall back to an exact required version string
// We allow `= x.y.z`, `=x.y.z` or `x.y.z` where `x`, `y` and `z` are integers.
re := regexp.MustCompile(`^=?\s*([^\s]+)\s*$`)
re := regexp.MustCompile(`^=?\s*([0-9.]+)\s*$`)
matched := re.FindStringSubmatch(requiredVersionSetting)
if len(matched) == 0 {
ctx.Log.Debug("Did not specify exact version in terraform configuration, found %q", requiredVersionSetting)
Expand Down

0 comments on commit e10ed6d

Please sign in to comment.