Test project command runner.

This commit is contained in:
Luke Kysow
2018-07-01 23:48:32 +02:00
parent 6d8766403b
commit f067818aa5
16 changed files with 780 additions and 337 deletions

View File

@@ -0,0 +1,20 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
webhooks "github.com/runatlantis/atlantis/server/events/webhooks"
)
func AnyWebhooksApplyResult() webhooks.ApplyResult {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(webhooks.ApplyResult))(nil)).Elem()))
var nullValue webhooks.ApplyResult
return nullValue
}
func EqWebhooksApplyResult(value webhooks.ApplyResult) webhooks.ApplyResult {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue webhooks.ApplyResult
return nullValue
}

View File

@@ -0,0 +1,88 @@
// Automatically generated by pegomock. DO NOT EDIT!
// Source: github.com/runatlantis/atlantis/server/events (interfaces: StepRunner)
package mocks
import (
"reflect"
pegomock "github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
)
type MockStepRunner struct {
fail func(message string, callerSkip ...int)
}
func NewMockStepRunner() *MockStepRunner {
return &MockStepRunner{fail: pegomock.GlobalFailHandler}
}
func (mock *MockStepRunner) Run(ctx models.ProjectCommandContext, extraArgs []string, path string) (string, error) {
params := []pegomock.Param{ctx, extraArgs, path}
result := pegomock.GetGenericMockFrom(mock).Invoke("Run", params, []reflect.Type{reflect.TypeOf((*string)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 string
var ret1 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(string)
}
if result[1] != nil {
ret1 = result[1].(error)
}
}
return ret0, ret1
}
func (mock *MockStepRunner) VerifyWasCalledOnce() *VerifierStepRunner {
return &VerifierStepRunner{mock, pegomock.Times(1), nil}
}
func (mock *MockStepRunner) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierStepRunner {
return &VerifierStepRunner{mock, invocationCountMatcher, nil}
}
func (mock *MockStepRunner) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierStepRunner {
return &VerifierStepRunner{mock, invocationCountMatcher, inOrderContext}
}
type VerifierStepRunner struct {
mock *MockStepRunner
invocationCountMatcher pegomock.Matcher
inOrderContext *pegomock.InOrderContext
}
func (verifier *VerifierStepRunner) Run(ctx models.ProjectCommandContext, extraArgs []string, path string) *StepRunner_Run_OngoingVerification {
params := []pegomock.Param{ctx, extraArgs, path}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Run", params)
return &StepRunner_Run_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type StepRunner_Run_OngoingVerification struct {
mock *MockStepRunner
methodInvocations []pegomock.MethodInvocation
}
func (c *StepRunner_Run_OngoingVerification) GetCapturedArguments() (models.ProjectCommandContext, []string, string) {
ctx, extraArgs, path := c.GetAllCapturedArguments()
return ctx[len(ctx)-1], extraArgs[len(extraArgs)-1], path[len(path)-1]
}
func (c *StepRunner_Run_OngoingVerification) GetAllCapturedArguments() (_param0 []models.ProjectCommandContext, _param1 [][]string, _param2 []string) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]models.ProjectCommandContext, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(models.ProjectCommandContext)
}
_param1 = make([][]string, len(params[1]))
for u, param := range params[1] {
_param1[u] = param.([]string)
}
_param2 = make([]string, len(params[2]))
for u, param := range params[2] {
_param2[u] = param.(string)
}
}
return
}

View File

@@ -0,0 +1,81 @@
// Automatically generated by pegomock. DO NOT EDIT!
// Source: github.com/runatlantis/atlantis/server/events (interfaces: WebhooksSender)
package mocks
import (
"reflect"
pegomock "github.com/petergtz/pegomock"
webhooks "github.com/runatlantis/atlantis/server/events/webhooks"
logging "github.com/runatlantis/atlantis/server/logging"
)
type MockWebhooksSender struct {
fail func(message string, callerSkip ...int)
}
func NewMockWebhooksSender() *MockWebhooksSender {
return &MockWebhooksSender{fail: pegomock.GlobalFailHandler}
}
func (mock *MockWebhooksSender) Send(log *logging.SimpleLogger, res webhooks.ApplyResult) error {
params := []pegomock.Param{log, res}
result := pegomock.GetGenericMockFrom(mock).Invoke("Send", params, []reflect.Type{reflect.TypeOf((*error)(nil)).Elem()})
var ret0 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(error)
}
}
return ret0
}
func (mock *MockWebhooksSender) VerifyWasCalledOnce() *VerifierWebhooksSender {
return &VerifierWebhooksSender{mock, pegomock.Times(1), nil}
}
func (mock *MockWebhooksSender) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierWebhooksSender {
return &VerifierWebhooksSender{mock, invocationCountMatcher, nil}
}
func (mock *MockWebhooksSender) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierWebhooksSender {
return &VerifierWebhooksSender{mock, invocationCountMatcher, inOrderContext}
}
type VerifierWebhooksSender struct {
mock *MockWebhooksSender
invocationCountMatcher pegomock.Matcher
inOrderContext *pegomock.InOrderContext
}
func (verifier *VerifierWebhooksSender) Send(log *logging.SimpleLogger, res webhooks.ApplyResult) *WebhooksSender_Send_OngoingVerification {
params := []pegomock.Param{log, res}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "Send", params)
return &WebhooksSender_Send_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type WebhooksSender_Send_OngoingVerification struct {
mock *MockWebhooksSender
methodInvocations []pegomock.MethodInvocation
}
func (c *WebhooksSender_Send_OngoingVerification) GetCapturedArguments() (*logging.SimpleLogger, webhooks.ApplyResult) {
log, res := c.GetAllCapturedArguments()
return log[len(log)-1], res[len(res)-1]
}
func (c *WebhooksSender_Send_OngoingVerification) GetAllCapturedArguments() (_param0 []*logging.SimpleLogger, _param1 []webhooks.ApplyResult) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]*logging.SimpleLogger, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(*logging.SimpleLogger)
}
_param1 = make([]webhooks.ApplyResult, len(params[1]))
for u, param := range params[1] {
_param1[u] = param.(webhooks.ApplyResult)
}
}
return
}

View File

@@ -238,7 +238,6 @@ type ProjectCommandContext struct {
// CommentArgs are the extra arguments appended to comment,
// ex. atlantis plan -- -target=resource
CommentArgs []string
Workspace string
RequireApprovalOverride bool
CommentArgs []string
Workspace string
}

View File

@@ -29,7 +29,6 @@ type DefaultProjectCommandBuilder struct {
VCSClient vcs.ClientProxy
WorkingDir WorkingDir
WorkingDirLocker WorkingDirLocker
RequireApproval bool
AllowRepoConfig bool
AllowRepoConfigFlag string
}
@@ -180,17 +179,16 @@ func (p *DefaultProjectCommandBuilder) buildProjectCommandCtx(ctx *CommandContex
}
return models.ProjectCommandContext{
BaseRepo: ctx.BaseRepo,
HeadRepo: ctx.HeadRepo,
Pull: ctx.Pull,
User: ctx.User,
Log: ctx.Log,
CommentArgs: cmd.Flags,
Workspace: workspace,
RepoRelDir: dir,
ProjectConfig: projCfg,
GlobalConfig: globalCfg,
RequireApprovalOverride: p.RequireApproval,
BaseRepo: ctx.BaseRepo,
HeadRepo: ctx.HeadRepo,
Pull: ctx.Pull,
User: ctx.User,
Log: ctx.Log,
CommentArgs: cmd.Flags,
Workspace: workspace,
RepoRelDir: dir,
ProjectConfig: projCfg,
GlobalConfig: globalCfg,
}, nil
}

View File

@@ -190,7 +190,7 @@ projects:
When(vcsClient.GetModifiedFiles(baseRepo, pull)).ThenReturn([]string{"main.tf"}, nil)
builder := &events.DefaultProjectCommandBuilder{
WorkingDirLocker: events.NewDefaultAtlantisWorkingDirLocker(),
WorkingDirLocker: events.NewDefaultWorkingDirLocker(),
WorkingDir: workingDir,
ParserValidator: &yaml.ParserValidator{},
VCSClient: vcsClient,
@@ -216,7 +216,6 @@ projects:
Equals(t, models.User{}, actCtx.User)
Equals(t, logger, actCtx.Log)
Equals(t, 0, len(actCtx.CommentArgs))
Equals(t, false, actCtx.RequireApprovalOverride)
Equals(t, expCtx.projectConfig, actCtx.ProjectConfig)
Equals(t, expCtx.dir, actCtx.RepoRelDir)
@@ -412,7 +411,7 @@ projects:
When(vcsClient.GetModifiedFiles(baseRepo, pull)).ThenReturn([]string{"main.tf"}, nil)
builder := &events.DefaultProjectCommandBuilder{
WorkingDirLocker: events.NewDefaultAtlantisWorkingDirLocker(),
WorkingDirLocker: events.NewDefaultWorkingDirLocker(),
WorkingDir: workingDir,
ParserValidator: &yaml.ParserValidator{},
VCSClient: vcsClient,
@@ -446,7 +445,6 @@ projects:
Equals(t, pull, actCtx.Pull)
Equals(t, models.User{}, actCtx.User)
Equals(t, logger, actCtx.Log)
Equals(t, false, actCtx.RequireApprovalOverride)
Equals(t, c.ExpProjectConfig, actCtx.ProjectConfig)
Equals(t, c.ExpDir, actCtx.RepoRelDir)

View File

@@ -34,8 +34,16 @@ type LockURLGenerator interface {
GenerateLockURL(lockID string) string
}
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_step_runner.go StepRunner
type StepRunner interface {
Run(ctx models.ProjectCommandContext, extraArgs []string, path string) (string, error)
}
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_webhooks_sender.go WebhooksSender
type WebhooksSender interface {
Send(log *logging.SimpleLogger, result webhooks.ApplyResult) error
Send(log *logging.SimpleLogger, res webhooks.ApplyResult) error
}
// PlanSuccess is the result of a successful plan.
@@ -52,16 +60,17 @@ type ProjectCommandRunner interface {
}
type DefaultProjectCommandRunner struct {
Locker ProjectLocker
LockURLGenerator LockURLGenerator
InitStepRunner runtime.InitStepRunner
PlanStepRunner runtime.PlanStepRunner
ApplyStepRunner runtime.ApplyStepRunner
RunStepRunner runtime.RunStepRunner
PullApprovedChecker runtime.PullApprovedChecker
WorkingDir WorkingDir
Webhooks WebhooksSender
WorkingDirLocker WorkingDirLocker
Locker ProjectLocker
LockURLGenerator LockURLGenerator
InitStepRunner StepRunner
PlanStepRunner StepRunner
ApplyStepRunner StepRunner
RunStepRunner StepRunner
PullApprovedChecker runtime.PullApprovedChecker
WorkingDir WorkingDir
Webhooks WebhooksSender
WorkingDirLocker WorkingDirLocker
RequireApprovalOverride bool
}
func (p *DefaultProjectCommandRunner) Plan(ctx models.ProjectCommandContext) ProjectCommandResult {
@@ -160,7 +169,7 @@ func (p *DefaultProjectCommandRunner) Apply(ctx models.ProjectCommandContext) Pr
if ctx.ProjectConfig != nil {
applyRequirements = ctx.ProjectConfig.ApplyRequirements
}
if ctx.RequireApprovalOverride {
if p.RequireApprovalOverride {
applyRequirements = []string{raw.ApprovedApplyRequirement}
}
for _, req := range applyRequirements {

View File

@@ -13,277 +13,402 @@
//
package events_test
//
//import (
// "errors"
// "testing"
//
// "github.com/mohae/deepcopy"
// . "github.com/petergtz/pegomock"
// "github.com/runatlantis/atlantis/server/events"
// "github.com/runatlantis/atlantis/server/events/locking"
// lmocks "github.com/runatlantis/atlantis/server/events/locking/mocks"
// "github.com/runatlantis/atlantis/server/events/mocks"
// "github.com/runatlantis/atlantis/server/events/models"
// rmocks "github.com/runatlantis/atlantis/server/events/run/mocks"
// tmocks "github.com/runatlantis/atlantis/server/events/terraform/mocks"
// vcsmocks "github.com/runatlantis/atlantis/server/events/vcs/mocks"
// "github.com/runatlantis/atlantis/server/events/vcs/mocks/matchers"
// "github.com/runatlantis/atlantis/server/logging"
// . "github.com/runatlantis/atlantis/testing"
//)
//
//var planCtx = events.CommandContext{
// Command: &events.Command{
// Name: events.Plan,
// Workspace: "workspace",
// RepoRelDir: "",
// },
// Log: logging.NewNoopLogger(),
// BaseRepo: models.Repo{},
// HeadRepo: models.Repo{},
// Pull: models.PullRequest{},
// User: models.User{
// Username: "anubhavmishra",
// },
//}
//
//func TestExecute_ModifiedFilesErr(t *testing.T) {
// t.Log("If GetModifiedFiles returns an error we return an error")
// p, _, _ := setupPlanExecutorTest(t)
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn(nil, errors.New("err"))
// r := p.Execute(&planCtx)
//
// Assert(t, r.Error != nil, "exp .Error to be set")
// Equals(t, "getting modified files: err", r.Error.Error())
//}
//
//func TestExecute_NoModifiedProjects(t *testing.T) {
// t.Log("If there are no modified projects we return a failure")
// p, _, _ := setupPlanExecutorTest(t)
// // We don't need to actually mock VCSClient.GetModifiedFiles because by
// // default it will return an empty slice which is what we want for this test.
// r := p.Execute(&planCtx)
//
// Equals(t, "No Terraform files were modified.", r.Failure)
//}
//
//func TestExecute_CloneErr(t *testing.T) {
// t.Log("If WorkingDir.Clone returns an error we return an error")
// p, _, _ := setupPlanExecutorTest(t)
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil)
// When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).ThenReturn("", errors.New("err"))
// r := p.Execute(&planCtx)
//
// Assert(t, r.Error != nil, "exp .Error to be set")
// Equals(t, "err", r.Error.Error())
//}
//
//func TestExecute_DirectoryAndWorkspaceSet(t *testing.T) {
// t.Log("Test that we run plan in the right directory and workspace if they're set")
// p, runner, _ := setupPlanExecutorTest(t)
// ctx := deepcopy.Copy(planCtx).(events.CommandContext)
// ctx.Log = logging.NewNoopLogger()
// ctx.Command.RepoRelDir = "dir1/dir2"
// ctx.Command.Workspace = "workspace-flag"
//
// When(p.Workspace.Clone(ctx.Log, ctx.BaseRepo, ctx.HeadRepo, ctx.Pull, "workspace-flag")).
// ThenReturn("/tmp/clone-repo", nil)
// When(p.ProjectPreExecute.Execute(&ctx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "dir1/dir2"})).
// ThenReturn(events.PreExecuteResult{
// LockResponse: locking.TryLockResponse{
// LockKey: "key",
// },
// })
// r := p.Execute(&ctx)
//
// runner.VerifyWasCalledOnce().RunCommandWithVersion(
// ctx.Log,
// "/tmp/clone-repo/dir1/dir2",
// []string{"plan", "-refresh", "-no-color", "-out", "/tmp/clone-repo/dir1/dir2/workspace-flag.tfplan", "-var", "atlantis_user=anubhavmishra"},
// nil,
// "workspace-flag",
// )
// Assert(t, len(r.ProjectResults) == 1, "exp one project result")
// result := r.ProjectResults[0]
// Assert(t, result.PlanSuccess != nil, "exp plan success to not be nil")
// Equals(t, "", result.PlanSuccess.TerraformOutput)
// Equals(t, "lockurl-key", result.PlanSuccess.LockURL)
//}
//
//func TestExecute_AddedArgs(t *testing.T) {
// t.Log("Test that we include extra-args added to the comment in the plan command")
// p, runner, _ := setupPlanExecutorTest(t)
// ctx := deepcopy.Copy(planCtx).(events.CommandContext)
// ctx.Log = logging.NewNoopLogger()
// ctx.Command.CommentArgs = []string{"\"-target=resource\"", "\"-var\"", "\"a=b\"", "\";\"", "\"echo\"", "\"hi\""}
//
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil)
// When(p.Workspace.Clone(ctx.Log, ctx.BaseRepo, ctx.HeadRepo, ctx.Pull, "workspace")).
// ThenReturn("/tmp/clone-repo", nil)
// When(p.ProjectPreExecute.Execute(&ctx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "."})).
// ThenReturn(events.PreExecuteResult{
// LockResponse: locking.TryLockResponse{
// LockKey: "key",
// },
// })
// r := p.Execute(&ctx)
//
// runner.VerifyWasCalledOnce().RunCommandWithVersion(
// ctx.Log,
// "/tmp/clone-repo",
// []string{
// "plan",
// "-refresh",
// "-no-color",
// "-out",
// "/tmp/clone-repo/workspace.tfplan",
// "-var",
// "atlantis_user=anubhavmishra",
// // NOTE: extra args should be quoted to prevent an attacker from
// // appending malicious commands.
// "\"-target=resource\"",
// "\"-var\"",
// "\"a=b\"",
// "\";\"",
// "\"echo\"",
// "\"hi\"",
// },
// nil,
// "workspace",
// )
// Assert(t, len(r.ProjectResults) == 1, "exp one project result")
// result := r.ProjectResults[0]
// Assert(t, result.PlanSuccess != nil, "exp plan success to not be nil")
// Equals(t, "", result.PlanSuccess.TerraformOutput)
// Equals(t, "lockurl-key", result.PlanSuccess.LockURL)
//}
//
//func TestExecute_Success(t *testing.T) {
// t.Log("If there are no errors, the plan should be returned")
// p, runner, _ := setupPlanExecutorTest(t)
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil)
// When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).
// ThenReturn("/tmp/clone-repo", nil)
// When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "."})).
// ThenReturn(events.PreExecuteResult{
// LockResponse: locking.TryLockResponse{
// LockKey: "key",
// },
// })
//
// r := p.Execute(&planCtx)
//
// runner.VerifyWasCalledOnce().RunCommandWithVersion(
// planCtx.Log,
// "/tmp/clone-repo",
// []string{"plan", "-refresh", "-no-color", "-out", "/tmp/clone-repo/workspace.tfplan", "-var", "atlantis_user=anubhavmishra"},
// nil,
// "workspace",
// )
// Assert(t, len(r.ProjectResults) == 1, "exp one project result")
// result := r.ProjectResults[0]
// Assert(t, result.PlanSuccess != nil, "exp plan success to not be nil")
// Equals(t, "", result.PlanSuccess.TerraformOutput)
// Equals(t, "lockurl-key", result.PlanSuccess.LockURL)
//}
//
//func TestExecute_PreExecuteResult(t *testing.T) {
// t.Log("If DefaultProjectPreExecutor.Execute returns a ProjectResult we should return it")
// p, _, _ := setupPlanExecutorTest(t)
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil)
// When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).
// ThenReturn("/tmp/clone-repo", nil)
// projectResult := events.ProjectResult{
// Failure: "failure",
// }
// When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "."})).
// ThenReturn(events.PreExecuteResult{ProjectResult: projectResult})
// r := p.Execute(&planCtx)
//
// Assert(t, len(r.ProjectResults) == 1, "exp one project result")
// result := r.ProjectResults[0]
// Equals(t, "failure", result.Failure)
//}
//
//func TestExecute_MultiProjectFailure(t *testing.T) {
// t.Log("If is an error planning in one project it should be returned. It shouldn't affect another project though.")
// p, runner, locker := setupPlanExecutorTest(t)
// // Two projects have been modified so we should run plan in two paths.
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"path1/file.tf", "path2/file.tf"}, nil)
// When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).
// ThenReturn("/tmp/clone-repo", nil)
//
// // Both projects will succeed in the PreExecute stage.
// When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "path1"})).
// ThenReturn(events.PreExecuteResult{LockResponse: locking.TryLockResponse{LockKey: "key1"}})
// When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "path2"})).
// ThenReturn(events.PreExecuteResult{LockResponse: locking.TryLockResponse{LockKey: "key2"}})
//
// // The first project will fail when running plan
// When(runner.RunCommandWithVersion(
// planCtx.Log,
// "/tmp/clone-repo/path1",
// []string{"plan", "-refresh", "-no-color", "-out", "/tmp/clone-repo/path1/workspace.tfplan", "-var", "atlantis_user=anubhavmishra"},
// nil,
// "workspace",
// )).ThenReturn("", errors.New("path1 err"))
// // The second will succeed. We don't need to stub it because by default it
// // will return a nil error.
// r := p.Execute(&planCtx)
//
// // We expect Unlock to be called for the failed project.
// locker.VerifyWasCalledOnce().Unlock("key1")
//
// // So at the end we expect the first project to return an error and the second to be successful.
// Assert(t, len(r.ProjectResults) == 2, "exp two project results")
// result1 := r.ProjectResults[0]
// Assert(t, result1.Error != nil, "exp err to not be nil")
// Equals(t, "path1 err\n", result1.Error.Error())
//
// result2 := r.ProjectResults[1]
// Assert(t, result2.PlanSuccess != nil, "exp plan success to not be nil")
// Equals(t, "", result2.PlanSuccess.TerraformOutput)
// Equals(t, "lockurl-key2", result2.PlanSuccess.LockURL)
//}
//
//func TestExecute_PostPlanCommands(t *testing.T) {
// t.Log("Should execute post-plan commands and return if there is an error")
// p, _, _ := setupPlanExecutorTest(t)
// When(p.VCSClient.GetModifiedFiles(matchers.AnyModelsRepo(), matchers.AnyModelsPullRequest())).ThenReturn([]string{"file.tf"}, nil)
// When(p.Workspace.Clone(planCtx.Log, planCtx.BaseRepo, planCtx.HeadRepo, planCtx.Pull, "workspace")).
// ThenReturn("/tmp/clone-repo", nil)
// When(p.ProjectPreExecute.Execute(&planCtx, "/tmp/clone-repo", models.Project{RepoFullName: "", RepoRelDir: "."})).
// ThenReturn(events.PreExecuteResult{
// ProjectConfig: events.ProjectConfig{PostPlan: []string{"post-plan"}},
// })
// When(p.Run.Execute(planCtx.Log, []string{"post-plan"}, "/tmp/clone-repo", "workspace", nil, "post_plan")).
// ThenReturn("", errors.New("err"))
//
// r := p.Execute(&planCtx)
//
// Assert(t, len(r.ProjectResults) == 1, "exp one project result")
// result := r.ProjectResults[0]
// Assert(t, result.Error != nil, "exp plan error to not be nil")
// Equals(t, "running post plan commands: err", result.Error.Error())
//}
//
//func setupPlanExecutorTest(t *testing.T) (*events.PlanExecutor, *tmocks.MockClient, *lmocks.MockLocker) {
// RegisterMockTestingT(t)
// vcsProxy := vcsmocks.NewMockClientProxy()
// w := mocks.NewMockWorkingDir()
// ppe := mocks.NewMockProjectPreExecutor()
// runner := tmocks.NewMockClient()
// locker := lmocks.NewMockLocker()
// run := rmocks.NewMockRunner()
// p := events.PlanExecutor{
// VCSClient: vcsProxy,
// ProjectFinder: &events.DefaultProjectFinder{},
// Workspace: w,
// ProjectPreExecute: ppe,
// Terraform: runner,
// Locker: locker,
// Run: run,
// }
// return &p, runner, locker
//}
import (
"os"
"strings"
"testing"
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/events"
"github.com/runatlantis/atlantis/server/events/mocks"
"github.com/runatlantis/atlantis/server/events/mocks/matchers"
"github.com/runatlantis/atlantis/server/events/models"
mocks2 "github.com/runatlantis/atlantis/server/events/runtime/mocks"
"github.com/runatlantis/atlantis/server/events/yaml/valid"
"github.com/runatlantis/atlantis/server/logging"
. "github.com/runatlantis/atlantis/testing"
)
func TestDefaultProjectCommandRunner_Plan(t *testing.T) {
cases := []struct {
description string
projCfg *valid.Project
globalCfg *valid.Config
expSteps []string
expOut string
}{
{
description: "use defaults",
projCfg: nil,
globalCfg: nil,
expSteps: []string{"init", "plan"},
expOut: "init\nplan",
},
{
description: "no workflow, use defaults",
projCfg: &valid.Project{
Dir: ".",
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
},
expSteps: []string{"init", "plan"},
expOut: "init\nplan",
},
{
description: "workflow without plan stage set",
projCfg: &valid.Project{
Dir: ".",
Workflow: String("myworkflow"),
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
Workflows: map[string]valid.Workflow{
"myworkflow": {
Apply: &valid.Stage{
Steps: nil,
},
},
},
},
expSteps: []string{"init", "plan"},
expOut: "init\nplan",
},
{
description: "workflow with custom plan stage",
projCfg: &valid.Project{
Dir: ".",
Workflow: String("myworkflow"),
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
Workflows: map[string]valid.Workflow{
"myworkflow": {
Plan: &valid.Stage{
Steps: []valid.Step{
{
StepName: "run",
},
{
StepName: "apply",
},
{
StepName: "plan",
},
{
StepName: "init",
},
},
},
},
},
},
expSteps: []string{"run", "apply", "plan", "init"},
expOut: "run\napply\nplan\ninit",
},
}
for _, c := range cases {
t.Run(strings.Join(c.expSteps, ","), func(t *testing.T) {
RegisterMockTestingT(t)
mockInit := mocks.NewMockStepRunner()
mockPlan := mocks.NewMockStepRunner()
mockApply := mocks.NewMockStepRunner()
mockRun := mocks.NewMockStepRunner()
mockWorkingDir := mocks.NewMockWorkingDir()
mockLocker := mocks.NewMockProjectLocker()
runner := events.DefaultProjectCommandRunner{
Locker: mockLocker,
LockURLGenerator: mockURLGenerator{},
InitStepRunner: mockInit,
PlanStepRunner: mockPlan,
ApplyStepRunner: mockApply,
RunStepRunner: mockRun,
PullApprovedChecker: nil,
WorkingDir: mockWorkingDir,
Webhooks: nil,
WorkingDirLocker: events.NewDefaultWorkingDirLocker(),
}
repoDir := "/tmp/mydir"
When(mockWorkingDir.Clone(
matchers.AnyPtrToLoggingSimpleLogger(),
matchers.AnyModelsRepo(),
matchers.AnyModelsRepo(),
matchers.AnyModelsPullRequest(),
AnyString(),
)).ThenReturn(repoDir, nil)
When(mockLocker.TryLock(
matchers.AnyPtrToLoggingSimpleLogger(),
matchers.AnyModelsPullRequest(),
matchers.AnyModelsUser(),
AnyString(),
matchers.AnyModelsProject(),
)).ThenReturn(&events.TryLockResponse{
LockAcquired: true,
LockKey: "lock-key",
}, nil)
ctx := models.ProjectCommandContext{
Log: logging.NewNoopLogger(),
ProjectConfig: c.projCfg,
Workspace: "default",
GlobalConfig: c.globalCfg,
RepoRelDir: ".",
}
When(mockInit.Run(ctx, nil, repoDir)).ThenReturn("init", nil)
When(mockPlan.Run(ctx, nil, repoDir)).ThenReturn("plan", nil)
When(mockApply.Run(ctx, nil, repoDir)).ThenReturn("apply", nil)
When(mockRun.Run(ctx, nil, repoDir)).ThenReturn("run", nil)
res := runner.Plan(ctx)
Assert(t, res.PlanSuccess != nil, "exp plan success")
Equals(t, "https://lock-key", res.PlanSuccess.LockURL)
Equals(t, c.expOut, res.PlanSuccess.TerraformOutput)
for _, step := range c.expSteps {
switch step {
case "init":
mockInit.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "plan":
mockPlan.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "apply":
mockApply.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "run":
mockRun.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
}
}
})
}
}
func TestDefaultProjectCommandRunner_ApplyNotCloned(t *testing.T) {
mockWorkingDir := mocks.NewMockWorkingDir()
runner := &events.DefaultProjectCommandRunner{
WorkingDir: mockWorkingDir,
}
ctx := models.ProjectCommandContext{}
When(mockWorkingDir.GetWorkingDir(ctx.BaseRepo, ctx.Pull, ctx.Workspace)).ThenReturn("", os.ErrNotExist)
res := runner.Apply(ctx)
ErrEquals(t, "project has not been cloneddid you run plan?", res.Error)
}
func TestDefaultProjectCommandRunner_ApplyNotApproved(t *testing.T) {
RegisterMockTestingT(t)
mockWorkingDir := mocks.NewMockWorkingDir()
mockApproved := mocks2.NewMockPullApprovedChecker()
runner := &events.DefaultProjectCommandRunner{
WorkingDir: mockWorkingDir,
PullApprovedChecker: mockApproved,
WorkingDirLocker: events.NewDefaultWorkingDirLocker(),
RequireApprovalOverride: true,
}
ctx := models.ProjectCommandContext{}
When(mockWorkingDir.GetWorkingDir(ctx.BaseRepo, ctx.Pull, ctx.Workspace)).ThenReturn("/tmp/mydir", nil)
When(mockApproved.PullIsApproved(ctx.BaseRepo, ctx.Pull)).ThenReturn(false, nil)
res := runner.Apply(ctx)
Equals(t, "Pull request must be approved before running apply.", res.Failure)
}
func TestDefaultProjectCommandRunner_Apply(t *testing.T) {
cases := []struct {
description string
projCfg *valid.Project
globalCfg *valid.Config
expSteps []string
expOut string
}{
{
description: "use defaults",
projCfg: nil,
globalCfg: nil,
expSteps: []string{"apply"},
expOut: "apply",
},
{
description: "no workflow, use defaults",
projCfg: &valid.Project{
Dir: ".",
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
},
expSteps: []string{"apply"},
expOut: "apply",
},
{
description: "no workflow, approval required, use defaults",
projCfg: &valid.Project{
Dir: ".",
ApplyRequirements: []string{"approved"},
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
ApplyRequirements: []string{"approved"},
},
},
},
expSteps: []string{"approved", "apply"},
expOut: "apply",
},
{
description: "workflow without apply stage set",
projCfg: &valid.Project{
Dir: ".",
Workflow: String("myworkflow"),
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
Workflows: map[string]valid.Workflow{
"myworkflow": {
Plan: &valid.Stage{
Steps: nil,
},
},
},
},
expSteps: []string{"apply"},
expOut: "apply",
},
{
description: "workflow with custom apply stage",
projCfg: &valid.Project{
Dir: ".",
Workflow: String("myworkflow"),
},
globalCfg: &valid.Config{
Version: 2,
Projects: []valid.Project{
{
Dir: ".",
},
},
Workflows: map[string]valid.Workflow{
"myworkflow": {
Apply: &valid.Stage{
Steps: []valid.Step{
{
StepName: "run",
},
{
StepName: "apply",
},
{
StepName: "plan",
},
{
StepName: "init",
},
},
},
},
},
},
expSteps: []string{"run", "apply", "plan", "init"},
expOut: "run\napply\nplan\ninit",
},
}
for _, c := range cases {
t.Run(strings.Join(c.expSteps, ","), func(t *testing.T) {
RegisterMockTestingT(t)
mockInit := mocks.NewMockStepRunner()
mockPlan := mocks.NewMockStepRunner()
mockApply := mocks.NewMockStepRunner()
mockRun := mocks.NewMockStepRunner()
mockApproved := mocks2.NewMockPullApprovedChecker()
mockWorkingDir := mocks.NewMockWorkingDir()
mockLocker := mocks.NewMockProjectLocker()
mockSender := mocks.NewMockWebhooksSender()
runner := events.DefaultProjectCommandRunner{
Locker: mockLocker,
LockURLGenerator: mockURLGenerator{},
InitStepRunner: mockInit,
PlanStepRunner: mockPlan,
ApplyStepRunner: mockApply,
RunStepRunner: mockRun,
PullApprovedChecker: mockApproved,
WorkingDir: mockWorkingDir,
Webhooks: mockSender,
WorkingDirLocker: events.NewDefaultWorkingDirLocker(),
}
repoDir := "/tmp/mydir"
When(mockWorkingDir.GetWorkingDir(
matchers.AnyModelsRepo(),
matchers.AnyModelsPullRequest(),
AnyString(),
)).ThenReturn(repoDir, nil)
ctx := models.ProjectCommandContext{
Log: logging.NewNoopLogger(),
ProjectConfig: c.projCfg,
Workspace: "default",
GlobalConfig: c.globalCfg,
RepoRelDir: ".",
}
When(mockInit.Run(ctx, nil, repoDir)).ThenReturn("init", nil)
When(mockPlan.Run(ctx, nil, repoDir)).ThenReturn("plan", nil)
When(mockApply.Run(ctx, nil, repoDir)).ThenReturn("apply", nil)
When(mockRun.Run(ctx, nil, repoDir)).ThenReturn("run", nil)
When(mockApproved.PullIsApproved(ctx.BaseRepo, ctx.Pull)).ThenReturn(true, nil)
res := runner.Apply(ctx)
Equals(t, c.expOut, res.ApplySuccess)
for _, step := range c.expSteps {
switch step {
case "approved":
mockApproved.VerifyWasCalledOnce().PullIsApproved(ctx.BaseRepo, ctx.Pull)
case "init":
mockInit.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "plan":
mockPlan.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "apply":
mockApply.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
case "run":
mockRun.VerifyWasCalledOnce().Run(ctx, nil, repoDir)
}
}
})
}
}
type mockURLGenerator struct{}
func (m mockURLGenerator) GenerateLockURL(lockID string) string {
return "https://" + lockID
}

View File

@@ -0,0 +1,20 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
)
func AnyModelsPullRequest() models.PullRequest {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.PullRequest))(nil)).Elem()))
var nullValue models.PullRequest
return nullValue
}
func EqModelsPullRequest(value models.PullRequest) models.PullRequest {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue models.PullRequest
return nullValue
}

View File

@@ -0,0 +1,20 @@
package matchers
import (
"reflect"
"github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
)
func AnyModelsRepo() models.Repo {
pegomock.RegisterMatcher(pegomock.NewAnyMatcher(reflect.TypeOf((*(models.Repo))(nil)).Elem()))
var nullValue models.Repo
return nullValue
}
func EqModelsRepo(value models.Repo) models.Repo {
pegomock.RegisterMatcher(&pegomock.EqMatcher{Value: value})
var nullValue models.Repo
return nullValue
}

View File

@@ -0,0 +1,84 @@
// Automatically generated by pegomock. DO NOT EDIT!
// Source: github.com/runatlantis/atlantis/server/events/runtime (interfaces: PullApprovedChecker)
package mocks
import (
"reflect"
pegomock "github.com/petergtz/pegomock"
models "github.com/runatlantis/atlantis/server/events/models"
)
type MockPullApprovedChecker struct {
fail func(message string, callerSkip ...int)
}
func NewMockPullApprovedChecker() *MockPullApprovedChecker {
return &MockPullApprovedChecker{fail: pegomock.GlobalFailHandler}
}
func (mock *MockPullApprovedChecker) PullIsApproved(baseRepo models.Repo, pull models.PullRequest) (bool, error) {
params := []pegomock.Param{baseRepo, pull}
result := pegomock.GetGenericMockFrom(mock).Invoke("PullIsApproved", params, []reflect.Type{reflect.TypeOf((*bool)(nil)).Elem(), reflect.TypeOf((*error)(nil)).Elem()})
var ret0 bool
var ret1 error
if len(result) != 0 {
if result[0] != nil {
ret0 = result[0].(bool)
}
if result[1] != nil {
ret1 = result[1].(error)
}
}
return ret0, ret1
}
func (mock *MockPullApprovedChecker) VerifyWasCalledOnce() *VerifierPullApprovedChecker {
return &VerifierPullApprovedChecker{mock, pegomock.Times(1), nil}
}
func (mock *MockPullApprovedChecker) VerifyWasCalled(invocationCountMatcher pegomock.Matcher) *VerifierPullApprovedChecker {
return &VerifierPullApprovedChecker{mock, invocationCountMatcher, nil}
}
func (mock *MockPullApprovedChecker) VerifyWasCalledInOrder(invocationCountMatcher pegomock.Matcher, inOrderContext *pegomock.InOrderContext) *VerifierPullApprovedChecker {
return &VerifierPullApprovedChecker{mock, invocationCountMatcher, inOrderContext}
}
type VerifierPullApprovedChecker struct {
mock *MockPullApprovedChecker
invocationCountMatcher pegomock.Matcher
inOrderContext *pegomock.InOrderContext
}
func (verifier *VerifierPullApprovedChecker) PullIsApproved(baseRepo models.Repo, pull models.PullRequest) *PullApprovedChecker_PullIsApproved_OngoingVerification {
params := []pegomock.Param{baseRepo, pull}
methodInvocations := pegomock.GetGenericMockFrom(verifier.mock).Verify(verifier.inOrderContext, verifier.invocationCountMatcher, "PullIsApproved", params)
return &PullApprovedChecker_PullIsApproved_OngoingVerification{mock: verifier.mock, methodInvocations: methodInvocations}
}
type PullApprovedChecker_PullIsApproved_OngoingVerification struct {
mock *MockPullApprovedChecker
methodInvocations []pegomock.MethodInvocation
}
func (c *PullApprovedChecker_PullIsApproved_OngoingVerification) GetCapturedArguments() (models.Repo, models.PullRequest) {
baseRepo, pull := c.GetAllCapturedArguments()
return baseRepo[len(baseRepo)-1], pull[len(pull)-1]
}
func (c *PullApprovedChecker_PullIsApproved_OngoingVerification) GetAllCapturedArguments() (_param0 []models.Repo, _param1 []models.PullRequest) {
params := pegomock.GetGenericMockFrom(c.mock).GetInvocationParams(c.methodInvocations)
if len(params) > 0 {
_param0 = make([]models.Repo, len(params[0]))
for u, param := range params[0] {
_param0[u] = param.(models.Repo)
}
_param1 = make([]models.PullRequest, len(params[1]))
for u, param := range params[1] {
_param1[u] = param.(models.PullRequest)
}
}
return
}

View File

@@ -4,6 +4,8 @@ import (
"github.com/runatlantis/atlantis/server/events/models"
)
//go:generate pegomock generate -m --use-experimental-model-gen --package mocks -o mocks/mock_pull_approved_checker.go PullApprovedChecker
type PullApprovedChecker interface {
PullIsApproved(baseRepo models.Repo, pull models.PullRequest) (bool, error)
}

View File

@@ -36,20 +36,20 @@ type WorkingDirLocker interface {
Unlock(repoFullName, workspace string, pullNum int)
}
// DefaultAtlantisWorkingDirLocker implements WorkingDirLocker.
type DefaultAtlantisWorkingDirLocker struct {
// DefaultWorkingDirLocker implements WorkingDirLocker.
type DefaultWorkingDirLocker struct {
mutex sync.Mutex
locks map[string]interface{}
}
// NewDefaultAtlantisWorkingDirLocker is a constructor.
func NewDefaultAtlantisWorkingDirLocker() *DefaultAtlantisWorkingDirLocker {
return &DefaultAtlantisWorkingDirLocker{
// NewDefaultWorkingDirLocker is a constructor.
func NewDefaultWorkingDirLocker() *DefaultWorkingDirLocker {
return &DefaultWorkingDirLocker{
locks: make(map[string]interface{}),
}
}
func (d *DefaultAtlantisWorkingDirLocker) TryLock(repoFullName string, workspace string, pullNum int) (func(), error) {
func (d *DefaultWorkingDirLocker) TryLock(repoFullName string, workspace string, pullNum int) (func(), error) {
d.mutex.Lock()
defer d.mutex.Unlock()
@@ -67,12 +67,12 @@ func (d *DefaultAtlantisWorkingDirLocker) TryLock(repoFullName string, workspace
}
// Unlock unlocks the repo, pull and workspace.
func (d *DefaultAtlantisWorkingDirLocker) Unlock(repoFullName, workspace string, pullNum int) {
func (d *DefaultWorkingDirLocker) Unlock(repoFullName, workspace string, pullNum int) {
d.mutex.Lock()
defer d.mutex.Unlock()
delete(d.locks, d.key(repoFullName, workspace, pullNum))
}
func (d *DefaultAtlantisWorkingDirLocker) key(repo string, workspace string, pull int) string {
func (d *DefaultWorkingDirLocker) key(repo string, workspace string, pull int) string {
return fmt.Sprintf("%s/%s/%d", repo, workspace, pull)
}

View File

@@ -24,7 +24,7 @@ var repo = "repo/owner"
var workspace = "default"
func TestTryLock(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
// The first lock should succeed.
unlockFn, err := locker.TryLock(repo, workspace, 1)
@@ -43,7 +43,7 @@ func TestTryLock(t *testing.T) {
}
func TestTryLockDifferentWorkspaces(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("a lock for the same repo and pull but different workspace should succeed")
_, err := locker.TryLock(repo, workspace, 1)
@@ -59,7 +59,7 @@ func TestTryLockDifferentWorkspaces(t *testing.T) {
}
func TestTryLockDifferentRepo(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("a lock for a different repo but the same workspace and pull should succeed")
_, err := locker.TryLock(repo, workspace, 1)
@@ -76,7 +76,7 @@ func TestTryLockDifferentRepo(t *testing.T) {
}
func TestTryLockDifferentPulls(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("a lock for a different pull but the same repo and workspace should succeed")
_, err := locker.TryLock(repo, workspace, 1)
@@ -93,7 +93,7 @@ func TestTryLockDifferentPulls(t *testing.T) {
}
func TestUnlock(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("unlocking should work")
unlockFn, err := locker.TryLock(repo, workspace, 1)
@@ -104,7 +104,7 @@ func TestUnlock(t *testing.T) {
}
func TestUnlockDifferentWorkspaces(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("unlocking should work for different workspaces")
unlockFn1, err1 := locker.TryLock(repo, workspace, 1)
Ok(t, err1)
@@ -120,7 +120,7 @@ func TestUnlockDifferentWorkspaces(t *testing.T) {
}
func TestUnlockDifferentRepos(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("unlocking should work for different repos")
unlockFn1, err1 := locker.TryLock(repo, workspace, 1)
Ok(t, err1)
@@ -137,7 +137,7 @@ func TestUnlockDifferentRepos(t *testing.T) {
}
func TestUnlockDifferentPulls(t *testing.T) {
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
t.Log("unlocking should work for different pulls")
unlockFn1, err1 := locker.TryLock(repo, workspace, 1)
Ok(t, err1)

View File

@@ -236,23 +236,23 @@ func setupE2E(t *testing.T) (server.EventsController, *vcsmocks.MockClientProxy,
}
defaultTFVersion := terraformClient.Version()
locker := events.NewDefaultAtlantisWorkingDirLocker()
locker := events.NewDefaultWorkingDirLocker()
commandRunner := &events.DefaultCommandRunner{
ProjectCommandRunner: &events.DefaultProjectCommandRunner{
Locker: projectLocker,
LockURLGenerator: &mockLockURLGenerator{},
InitStepRunner: runtime.InitStepRunner{
InitStepRunner: &runtime.InitStepRunner{
TerraformExecutor: terraformClient,
DefaultTFVersion: defaultTFVersion,
},
PlanStepRunner: runtime.PlanStepRunner{
PlanStepRunner: &runtime.PlanStepRunner{
TerraformExecutor: terraformClient,
DefaultTFVersion: defaultTFVersion,
},
ApplyStepRunner: runtime.ApplyStepRunner{
ApplyStepRunner: &runtime.ApplyStepRunner{
TerraformExecutor: terraformClient,
},
RunStepRunner: runtime.RunStepRunner{
RunStepRunner: &runtime.RunStepRunner{
DefaultTFVersion: defaultTFVersion,
},
PullApprovedChecker: e2eVCSClient,
@@ -277,7 +277,6 @@ func setupE2E(t *testing.T) (server.EventsController, *vcsmocks.MockClientProxy,
WorkingDirLocker: locker,
AllowRepoConfigFlag: "allow-repo-config",
AllowRepoConfig: true,
RequireApproval: false,
},
}

View File

@@ -190,7 +190,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
return nil, err
}
lockingClient := locking.NewClient(boltdb)
workingDirLocker := events.NewDefaultAtlantisWorkingDirLocker()
workingDirLocker := events.NewDefaultWorkingDirLocker()
workingDir := &events.FileWorkspace{
DataDir: userConfig.DataDir,
}
@@ -239,31 +239,31 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
VCSClient: vcsClient,
WorkingDir: workingDir,
WorkingDirLocker: workingDirLocker,
RequireApproval: userConfig.RequireApproval,
AllowRepoConfig: userConfig.AllowRepoConfig,
AllowRepoConfigFlag: config.AllowRepoConfigFlag,
},
ProjectCommandRunner: &events.DefaultProjectCommandRunner{
Locker: projectLocker,
LockURLGenerator: router,
InitStepRunner: runtime.InitStepRunner{
InitStepRunner: &runtime.InitStepRunner{
TerraformExecutor: terraformClient,
DefaultTFVersion: defaultTfVersion,
},
PlanStepRunner: runtime.PlanStepRunner{
PlanStepRunner: &runtime.PlanStepRunner{
TerraformExecutor: terraformClient,
DefaultTFVersion: defaultTfVersion,
},
ApplyStepRunner: runtime.ApplyStepRunner{
ApplyStepRunner: &runtime.ApplyStepRunner{
TerraformExecutor: terraformClient,
},
RunStepRunner: runtime.RunStepRunner{
RunStepRunner: &runtime.RunStepRunner{
DefaultTFVersion: defaultTfVersion,
},
PullApprovedChecker: vcsClient,
WorkingDir: workingDir,
Webhooks: webhooksManager,
WorkingDirLocker: workingDirLocker,
PullApprovedChecker: vcsClient,
WorkingDir: workingDir,
Webhooks: webhooksManager,
WorkingDirLocker: workingDirLocker,
RequireApprovalOverride: userConfig.RequireApproval,
},
}
repoWhitelist := &events.RepoWhitelistChecker{