mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-29 09:58:24 +00:00
* Adding policy_check support into yaml config * Added policy check model and runtime structs * Adding BuildPolicyCheckCommand to ProjectCommandBuilder * Return incorrectly deleted code * Remove BuildAutoPolicyPlanCommand from ProjectCommandBuilder * Split runAutoCommand into two functions runAutoPlanCommand - does what originally RunAutoplancommand was doing except now it returns CommandResult and []models.ProjectCommandContext runAutoPolicyCheckCommand - accepts CommandContext, CommandResult, and []models.ProjectCommandContext as arguments and runs PolicyCheckStep runner * Refactor RunCommentCommand * Remove BuildPolicyCheckCommand and rename StepCmdExec back to TerraformExec * Add policy step runner logic and conftest interfaces. * Add show step runner to policy check stage. * Adding models.PolicyCheckCommand to buildCtx This also means buildPlanAllCommands call buildCtx twice once with models.PlanCommand and once with models.PolicyCheckCommand * Adding new project_command_builder that supports policy_check * Refactoring PolicyCheck specific logic into a PolicyCheckProjectCommandBuilder * Moving events.CommandContext to models.CommandContext this will allow me to remove buildCtx method and move ProjectCommandContext creation into models package * Policy Owners might be different types, for that reason we are refactoring Owners into its own struct with specific keys defining different owner types Co-authored-by: Nish Krishnan <nishk@lyft.com> Co-authored-by: Nish Krishnan <nishkrishnan@users.noreply.github.com>
847 lines
22 KiB
Go
847 lines
22 KiB
Go
package events
|
|
|
|
import (
|
|
"io/ioutil"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
version "github.com/hashicorp/go-version"
|
|
. "github.com/petergtz/pegomock"
|
|
"github.com/runatlantis/atlantis/server/events/matchers"
|
|
"github.com/runatlantis/atlantis/server/events/models"
|
|
vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks"
|
|
"github.com/runatlantis/atlantis/server/events/yaml"
|
|
"github.com/runatlantis/atlantis/server/events/yaml/valid"
|
|
. "github.com/runatlantis/atlantis/testing"
|
|
)
|
|
|
|
// Test different permutations of global and repo config.
|
|
func TestBuildProjectCmdCtx(t *testing.T) {
|
|
emptyPolicySets := valid.PolicySets{
|
|
Version: nil,
|
|
PolicySets: []valid.PolicySet{},
|
|
}
|
|
baseRepo := models.Repo{
|
|
FullName: "owner/repo",
|
|
VCSHost: models.VCSHost{
|
|
Hostname: "github.com",
|
|
},
|
|
}
|
|
pull := models.PullRequest{
|
|
BaseRepo: baseRepo,
|
|
}
|
|
cases := map[string]struct {
|
|
globalCfg string
|
|
repoCfg string
|
|
expErr string
|
|
expCtx models.ProjectCommandContext
|
|
expPlanSteps []string
|
|
expApplySteps []string
|
|
}{
|
|
// Test that if we've set global defaults and no project config
|
|
// that the global defaults are used.
|
|
"global defaults": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: "",
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: false,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"init", "plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
|
|
// Test that if we've set global defaults, that they are used but the
|
|
// allowed project config values also come through.
|
|
"global defaults with repo cfg": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"init", "plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
|
|
// Set a global apply req that should be used.
|
|
"global apply_requirements": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved, mergeable]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{"approved", "mergeable"},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"init", "plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
|
|
// If we have global config that matches a specific repo, it should be used.
|
|
"specific repo": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
- id: github.com/owner/repo
|
|
workflow: specific
|
|
apply_requirements: [approved]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply
|
|
specific:
|
|
plan:
|
|
steps:
|
|
- plan
|
|
apply:
|
|
steps: []`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{"approved"},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"plan"},
|
|
expApplySteps: []string{},
|
|
},
|
|
|
|
// We should get an error if the repo sets an apply req when its
|
|
// not allowed.
|
|
"repo defines apply_requirements": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved, mergeable]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
apply_requirements: []
|
|
`,
|
|
expErr: "repo config not allowed to set 'apply_requirements' key: server-side config needs 'allowed_overrides: [apply_requirements]'",
|
|
},
|
|
|
|
// We should get an error if a repo sets a workflow when it's not allowed.
|
|
"repo sets its own workflow": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved, mergeable]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
workflow: default
|
|
`,
|
|
expErr: "repo config not allowed to set 'workflow' key: server-side config needs 'allowed_overrides: [workflow]'",
|
|
},
|
|
|
|
// We should get an error if a repo defines a workflow when it's not
|
|
// allowed.
|
|
"repo defines new workflow": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved, mergeable]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps:
|
|
- init
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
workflows:
|
|
new: ~
|
|
`,
|
|
expErr: "repo config not allowed to define custom workflows: server-side config needs 'allow_custom_workflows: true'",
|
|
},
|
|
|
|
// If the repos are allowed to set everything then their config should
|
|
// come through.
|
|
"full repo permissions": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved]
|
|
allowed_overrides: [apply_requirements, workflow]
|
|
allow_custom_workflows: true
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps: []
|
|
apply:
|
|
steps: []
|
|
`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
apply_requirements: []
|
|
workflow: custom
|
|
workflows:
|
|
custom:
|
|
plan:
|
|
steps:
|
|
- plan
|
|
apply:
|
|
steps:
|
|
- apply
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
|
|
// Repos can choose server-side workflows.
|
|
"repos choose server-side workflow": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
allowed_overrides: [workflow]
|
|
workflows:
|
|
default:
|
|
plan:
|
|
steps: []
|
|
apply:
|
|
steps: []
|
|
custom:
|
|
plan:
|
|
steps: [plan]
|
|
apply:
|
|
steps: [apply]
|
|
`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
workflow: custom
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
|
|
// Repo-side workflows with the same name override server-side if
|
|
// allowed.
|
|
"repo-side workflow override": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: custom
|
|
allowed_overrides: [workflow]
|
|
allow_custom_workflows: true
|
|
workflows:
|
|
custom:
|
|
plan:
|
|
steps: [plan]
|
|
apply:
|
|
steps: [apply]
|
|
`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
workflow: custom
|
|
workflows:
|
|
custom:
|
|
plan:
|
|
steps: []
|
|
apply:
|
|
steps: []
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{},
|
|
expApplySteps: []string{},
|
|
},
|
|
// Test that if we leave keys undefined, that they don't override.
|
|
"cascading matches": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
apply_requirements: [approved]
|
|
- id: github.com/owner/repo
|
|
workflow: custom
|
|
workflows:
|
|
custom:
|
|
plan:
|
|
steps: [plan]
|
|
`,
|
|
repoCfg: `
|
|
version: 3
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: false,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{"approved"},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPlanSteps: []string{"plan"},
|
|
expApplySteps: []string{"apply"},
|
|
},
|
|
}
|
|
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
tmp, cleanup := DirStructure(t, map[string]interface{}{
|
|
"project1": map[string]interface{}{
|
|
"main.tf": nil,
|
|
},
|
|
"modules": map[string]interface{}{
|
|
"module": map[string]interface{}{
|
|
"main.tf": nil,
|
|
},
|
|
},
|
|
})
|
|
defer cleanup()
|
|
|
|
workingDir := NewMockWorkingDir()
|
|
When(workingDir.Clone(matchers.AnyPtrToLoggingSimpleLogger(), matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), AnyString())).ThenReturn(tmp, false, nil)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
When(vcsClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"modules/module/main.tf"}, nil)
|
|
|
|
// Write and parse the global config file.
|
|
globalCfgPath := filepath.Join(tmp, "global.yaml")
|
|
Ok(t, ioutil.WriteFile(globalCfgPath, []byte(c.globalCfg), 0600))
|
|
parser := &yaml.ParserValidator{}
|
|
globalCfg, err := parser.ParseGlobalCfg(globalCfgPath, valid.NewGlobalCfg(false, false, false))
|
|
Ok(t, err)
|
|
|
|
if c.repoCfg != "" {
|
|
Ok(t, ioutil.WriteFile(filepath.Join(tmp, "atlantis.yaml"), []byte(c.repoCfg), 0600))
|
|
}
|
|
|
|
builder := NewProjectCommandBuilder(
|
|
false,
|
|
parser,
|
|
&DefaultProjectFinder{},
|
|
vcsClient,
|
|
workingDir,
|
|
NewDefaultWorkingDirLocker(),
|
|
globalCfg,
|
|
&DefaultPendingPlanFinder{},
|
|
&CommentParser{},
|
|
false,
|
|
)
|
|
|
|
// We run a test for each type of command.
|
|
for _, cmd := range []models.CommandName{models.PlanCommand, models.ApplyCommand} {
|
|
t.Run(cmd.String(), func(t *testing.T) {
|
|
ctxs, err := builder.buildProjectCommandCtx(&CommandContext{
|
|
Pull: models.PullRequest{
|
|
BaseRepo: baseRepo,
|
|
},
|
|
PullMergeable: true,
|
|
}, cmd, "", []string{"flag"}, tmp, "project1", "myworkspace", true)
|
|
|
|
if c.expErr != "" {
|
|
ErrEquals(t, c.expErr, err)
|
|
return
|
|
}
|
|
ctx := ctxs[0]
|
|
|
|
Ok(t, err)
|
|
|
|
// Construct expected steps.
|
|
var stepNames []string
|
|
switch cmd {
|
|
case models.PlanCommand:
|
|
stepNames = c.expPlanSteps
|
|
case models.ApplyCommand:
|
|
stepNames = c.expApplySteps
|
|
}
|
|
var expSteps []valid.Step
|
|
for _, stepName := range stepNames {
|
|
expSteps = append(expSteps, valid.Step{
|
|
StepName: stepName,
|
|
})
|
|
}
|
|
|
|
c.expCtx.CommandName = cmd
|
|
// Init fields we couldn't in our cases map.
|
|
c.expCtx.Steps = expSteps
|
|
ctx.PolicySets = emptyPolicySets
|
|
|
|
Equals(t, c.expCtx, ctx)
|
|
// Equals() doesn't compare TF version properly so have to
|
|
// use .String().
|
|
if c.expCtx.TerraformVersion != nil {
|
|
Equals(t, c.expCtx.TerraformVersion.String(), ctx.TerraformVersion.String())
|
|
}
|
|
})
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestBuildProjectCmdCtx_WithPolicCheckEnabled(t *testing.T) {
|
|
emptyPolicySets := valid.PolicySets{
|
|
Version: nil,
|
|
PolicySets: []valid.PolicySet{},
|
|
}
|
|
baseRepo := models.Repo{
|
|
FullName: "owner/repo",
|
|
VCSHost: models.VCSHost{
|
|
Hostname: "github.com",
|
|
},
|
|
}
|
|
pull := models.PullRequest{
|
|
BaseRepo: baseRepo,
|
|
}
|
|
cases := map[string]struct {
|
|
globalCfg string
|
|
repoCfg string
|
|
expErr string
|
|
expCtx models.ProjectCommandContext
|
|
expPolicyCheckSteps []string
|
|
}{
|
|
// Test that if we've set global defaults and no project config
|
|
// that the global defaults are used.
|
|
"global defaults": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
`,
|
|
repoCfg: "",
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: false,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPolicyCheckSteps: []string{"show", "policy_check"},
|
|
},
|
|
|
|
// If the repos are allowed to set everything then their config should
|
|
// come through.
|
|
"full repo permissions": {
|
|
globalCfg: `
|
|
repos:
|
|
- id: /.*/
|
|
workflow: default
|
|
apply_requirements: [approved]
|
|
allowed_overrides: [apply_requirements, workflow]
|
|
allow_custom_workflows: true
|
|
workflows:
|
|
default:
|
|
policy_check:
|
|
steps: []
|
|
`,
|
|
repoCfg: `
|
|
version: 3
|
|
automerge: true
|
|
projects:
|
|
- dir: project1
|
|
workspace: myworkspace
|
|
autoplan:
|
|
enabled: true
|
|
when_modified: [../modules/**/*.tf]
|
|
terraform_version: v10.0
|
|
apply_requirements: []
|
|
workflow: custom
|
|
workflows:
|
|
custom:
|
|
policy_check:
|
|
steps:
|
|
- policy_check
|
|
`,
|
|
expCtx: models.ProjectCommandContext{
|
|
ApplyCmd: "atlantis apply -d project1 -w myworkspace",
|
|
BaseRepo: baseRepo,
|
|
EscapedCommentArgs: []string{`\f\l\a\g`},
|
|
AutomergeEnabled: true,
|
|
AutoplanEnabled: true,
|
|
HeadRepo: models.Repo{},
|
|
Log: nil,
|
|
PullMergeable: true,
|
|
Pull: pull,
|
|
ProjectName: "",
|
|
ApplyRequirements: []string{},
|
|
RepoConfigVersion: 3,
|
|
RePlanCmd: "atlantis plan -d project1 -w myworkspace -- flag",
|
|
RepoRelDir: "project1",
|
|
TerraformVersion: mustVersion("10.0"),
|
|
User: models.User{},
|
|
Verbose: true,
|
|
Workspace: "myworkspace",
|
|
PolicySets: emptyPolicySets,
|
|
},
|
|
expPolicyCheckSteps: []string{"policy_check"},
|
|
},
|
|
}
|
|
|
|
for name, c := range cases {
|
|
t.Run(name, func(t *testing.T) {
|
|
tmp, cleanup := DirStructure(t, map[string]interface{}{
|
|
"project1": map[string]interface{}{
|
|
"main.tf": nil,
|
|
},
|
|
"modules": map[string]interface{}{
|
|
"module": map[string]interface{}{
|
|
"main.tf": nil,
|
|
},
|
|
},
|
|
})
|
|
defer cleanup()
|
|
|
|
workingDir := NewMockWorkingDir()
|
|
When(workingDir.Clone(matchers.AnyPtrToLoggingSimpleLogger(), matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest(), AnyString())).ThenReturn(tmp, false, nil)
|
|
vcsClient := vcsmocks.NewMockClient()
|
|
When(vcsClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"modules/module/main.tf"}, nil)
|
|
|
|
// Write and parse the global config file.
|
|
globalCfgPath := filepath.Join(tmp, "global.yaml")
|
|
Ok(t, ioutil.WriteFile(globalCfgPath, []byte(c.globalCfg), 0600))
|
|
parser := &yaml.ParserValidator{}
|
|
globalCfg, err := parser.ParseGlobalCfg(globalCfgPath, valid.NewGlobalCfg(false, false, false))
|
|
Ok(t, err)
|
|
|
|
if c.repoCfg != "" {
|
|
Ok(t, ioutil.WriteFile(filepath.Join(tmp, "atlantis.yaml"), []byte(c.repoCfg), 0600))
|
|
}
|
|
|
|
builder := NewProjectCommandBuilder(
|
|
true,
|
|
parser,
|
|
&DefaultProjectFinder{},
|
|
vcsClient,
|
|
workingDir,
|
|
NewDefaultWorkingDirLocker(),
|
|
globalCfg,
|
|
&DefaultPendingPlanFinder{},
|
|
&CommentParser{},
|
|
false,
|
|
)
|
|
|
|
cmd := models.PolicyCheckCommand
|
|
t.Run(cmd.String(), func(t *testing.T) {
|
|
ctxs, err := builder.buildProjectCommandCtx(&CommandContext{
|
|
Pull: models.PullRequest{
|
|
BaseRepo: baseRepo,
|
|
},
|
|
PullMergeable: true,
|
|
}, models.PlanCommand, "", []string{"flag"}, tmp, "project1", "myworkspace", true)
|
|
|
|
if c.expErr != "" {
|
|
ErrEquals(t, c.expErr, err)
|
|
return
|
|
}
|
|
|
|
ctx := ctxs[1]
|
|
|
|
Ok(t, err)
|
|
|
|
// Construct expected steps.
|
|
var stepNames []string
|
|
var expSteps []valid.Step
|
|
|
|
stepNames = c.expPolicyCheckSteps
|
|
for _, stepName := range stepNames {
|
|
expSteps = append(expSteps, valid.Step{
|
|
StepName: stepName,
|
|
})
|
|
}
|
|
|
|
c.expCtx.CommandName = cmd
|
|
// Init fields we couldn't in our cases map.
|
|
c.expCtx.Steps = expSteps
|
|
ctx.PolicySets = emptyPolicySets
|
|
|
|
Equals(t, c.expCtx, ctx)
|
|
// Equals() doesn't compare TF version properly so have to
|
|
// use .String().
|
|
if c.expCtx.TerraformVersion != nil {
|
|
Equals(t, c.expCtx.TerraformVersion.String(), ctx.TerraformVersion.String())
|
|
}
|
|
})
|
|
})
|
|
}
|
|
}
|
|
|
|
func mustVersion(v string) *version.Version {
|
|
vers, err := version.NewVersion(v)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return vers
|
|
}
|