mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-28 21:18:18 +00:00
323 lines
8.9 KiB
Go
323 lines
8.9 KiB
Go
package controllers_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"io"
|
|
"net/http"
|
|
"net/http/httptest"
|
|
"testing"
|
|
"time"
|
|
|
|
. "github.com/petergtz/pegomock/v4"
|
|
"github.com/runatlantis/atlantis/server/controllers"
|
|
. "github.com/runatlantis/atlantis/server/core/locking/mocks"
|
|
"github.com/runatlantis/atlantis/server/events"
|
|
"github.com/runatlantis/atlantis/server/events/command"
|
|
. "github.com/runatlantis/atlantis/server/events/mocks"
|
|
"github.com/runatlantis/atlantis/server/events/models"
|
|
. "github.com/runatlantis/atlantis/server/events/vcs/mocks"
|
|
"github.com/runatlantis/atlantis/server/logging"
|
|
"github.com/runatlantis/atlantis/server/metrics"
|
|
. "github.com/runatlantis/atlantis/testing"
|
|
)
|
|
|
|
const atlantisTokenHeader = "X-Atlantis-Token"
|
|
const atlantisToken = "token"
|
|
|
|
func TestAPIController_Plan(t *testing.T) {
|
|
ac, projectCommandBuilder, projectCommandRunner := setup(t)
|
|
|
|
cases := []struct {
|
|
repository string
|
|
ref string
|
|
vcsType string
|
|
pr int
|
|
projects []string
|
|
paths []struct {
|
|
Directory string
|
|
Workspace string
|
|
}
|
|
}{
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
projects: []string{"default"},
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
pr: 1,
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
paths: []struct {
|
|
Directory string
|
|
Workspace string
|
|
}{
|
|
{
|
|
Directory: ".",
|
|
Workspace: "myworkspace",
|
|
},
|
|
{
|
|
Directory: "./myworkspace2",
|
|
Workspace: "myworkspace2",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
pr: 1,
|
|
projects: []string{"test"},
|
|
paths: []struct {
|
|
Directory string
|
|
Workspace string
|
|
}{
|
|
{
|
|
Directory: ".",
|
|
Workspace: "myworkspace",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
expectedCalls := 0
|
|
for _, c := range cases {
|
|
body, _ := json.Marshal(controllers.APIRequest{
|
|
Repository: c.repository,
|
|
Ref: c.ref,
|
|
Type: c.vcsType,
|
|
PR: c.pr,
|
|
Projects: c.projects,
|
|
Paths: c.paths,
|
|
})
|
|
|
|
req, _ := http.NewRequest("POST", "", bytes.NewBuffer(body))
|
|
req.Header.Set(atlantisTokenHeader, atlantisToken)
|
|
w := httptest.NewRecorder()
|
|
ac.Plan(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "")
|
|
|
|
expectedCalls += len(c.projects)
|
|
expectedCalls += len(c.paths)
|
|
}
|
|
|
|
projectCommandBuilder.VerifyWasCalled(Times(expectedCalls)).BuildPlanCommands(Any[*command.Context](), Any[*events.CommentCommand]())
|
|
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Plan(Any[command.ProjectContext]())
|
|
}
|
|
|
|
func TestAPIController_Apply(t *testing.T) {
|
|
ac, projectCommandBuilder, projectCommandRunner := setup(t)
|
|
|
|
cases := []struct {
|
|
repository string
|
|
ref string
|
|
vcsType string
|
|
pr int
|
|
projects []string
|
|
paths []struct {
|
|
Directory string
|
|
Workspace string
|
|
}
|
|
}{
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
projects: []string{"default"},
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
pr: 1,
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
paths: []struct {
|
|
Directory string
|
|
Workspace string
|
|
}{
|
|
{
|
|
Directory: ".",
|
|
Workspace: "myworkspace",
|
|
},
|
|
{
|
|
Directory: "./myworkspace2",
|
|
Workspace: "myworkspace2",
|
|
},
|
|
},
|
|
},
|
|
{
|
|
repository: "Repo",
|
|
ref: "main",
|
|
vcsType: "Gitlab",
|
|
pr: 1,
|
|
projects: []string{"test"},
|
|
paths: []struct {
|
|
Directory string
|
|
Workspace string
|
|
}{
|
|
{
|
|
Directory: ".",
|
|
Workspace: "myworkspace",
|
|
},
|
|
},
|
|
},
|
|
}
|
|
|
|
expectedCalls := 0
|
|
for _, c := range cases {
|
|
body, _ := json.Marshal(controllers.APIRequest{
|
|
Repository: c.repository,
|
|
Ref: c.ref,
|
|
Type: c.vcsType,
|
|
PR: c.pr,
|
|
Projects: c.projects,
|
|
Paths: c.paths,
|
|
})
|
|
|
|
req, _ := http.NewRequest("POST", "", bytes.NewBuffer(body))
|
|
req.Header.Set(atlantisTokenHeader, atlantisToken)
|
|
w := httptest.NewRecorder()
|
|
ac.Apply(w, req)
|
|
ResponseContains(t, w, http.StatusOK, "")
|
|
|
|
expectedCalls += len(c.projects)
|
|
expectedCalls += len(c.paths)
|
|
}
|
|
|
|
projectCommandBuilder.VerifyWasCalled(Times(expectedCalls)).BuildApplyCommands(Any[*command.Context](), Any[*events.CommentCommand]())
|
|
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Plan(Any[command.ProjectContext]())
|
|
projectCommandRunner.VerifyWasCalled(Times(expectedCalls)).Apply(Any[command.ProjectContext]())
|
|
}
|
|
|
|
func TestAPIController_ListLocks(t *testing.T) {
|
|
ac, _, _ := setup(t)
|
|
time := time.Now()
|
|
expected := controllers.ListLocksResult{[]controllers.LockDetail{
|
|
{
|
|
Name: "lock-id",
|
|
ProjectName: "terraform",
|
|
ProjectRepo: "owner/repo",
|
|
ProjectRepoPath: "/path",
|
|
PullID: 123,
|
|
PullURL: "url",
|
|
User: "jdoe",
|
|
Workspace: "default",
|
|
Time: time,
|
|
},
|
|
},
|
|
}
|
|
mockLock := models.ProjectLock{
|
|
Project: models.Project{ProjectName: "terraform", RepoFullName: "owner/repo", Path: "/path"},
|
|
Pull: models.PullRequest{Num: 123, URL: "url", Author: "lkysow"},
|
|
User: models.User{Username: "jdoe"},
|
|
Workspace: "default",
|
|
Time: time,
|
|
}
|
|
mockLocks := map[string]models.ProjectLock{
|
|
"lock-id": mockLock,
|
|
}
|
|
When(ac.Locker.List()).ThenReturn(mockLocks, nil)
|
|
|
|
req, _ := http.NewRequest("GET", "", nil)
|
|
w := httptest.NewRecorder()
|
|
ac.ListLocks(w, req)
|
|
response, _ := io.ReadAll(w.Result().Body)
|
|
var result controllers.ListLocksResult
|
|
err := json.Unmarshal(response, &result)
|
|
Ok(t, err)
|
|
Equals(t, expected, result)
|
|
}
|
|
|
|
func TestAPIController_ListLocksEmpty(t *testing.T) {
|
|
ac, _, _ := setup(t)
|
|
|
|
expected := controllers.ListLocksResult{}
|
|
mockLocks := map[string]models.ProjectLock{}
|
|
When(ac.Locker.List()).ThenReturn(mockLocks, nil)
|
|
|
|
req, _ := http.NewRequest("GET", "", nil)
|
|
w := httptest.NewRecorder()
|
|
ac.ListLocks(w, req)
|
|
response, _ := io.ReadAll(w.Result().Body)
|
|
var result controllers.ListLocksResult
|
|
err := json.Unmarshal(response, &result)
|
|
Ok(t, err)
|
|
Equals(t, expected, result)
|
|
}
|
|
|
|
func setup(t *testing.T) (controllers.APIController, *MockProjectCommandBuilder, *MockProjectCommandRunner) {
|
|
RegisterMockTestingT(t)
|
|
locker := NewMockLocker()
|
|
logger := logging.NewNoopLogger(t)
|
|
parser := NewMockEventParsing()
|
|
repoAllowlistChecker, err := events.NewRepoAllowlistChecker("*")
|
|
scope, _, _ := metrics.NewLoggingScope(logger, "null")
|
|
vcsClient := NewMockClient()
|
|
workingDir := NewMockWorkingDir()
|
|
Ok(t, err)
|
|
|
|
workingDirLocker := NewMockWorkingDirLocker()
|
|
When(workingDirLocker.TryLock(Any[string](), Any[int](), Eq(events.DefaultWorkspace), Eq(events.DefaultRepoRelDir))).
|
|
ThenReturn(func() {}, nil)
|
|
|
|
projectCommandBuilder := NewMockProjectCommandBuilder()
|
|
When(projectCommandBuilder.BuildPlanCommands(Any[*command.Context](), Any[*events.CommentCommand]())).
|
|
ThenReturn([]command.ProjectContext{{
|
|
CommandName: command.Plan,
|
|
}}, nil)
|
|
When(projectCommandBuilder.BuildApplyCommands(Any[*command.Context](), Any[*events.CommentCommand]())).
|
|
ThenReturn([]command.ProjectContext{{
|
|
CommandName: command.Apply,
|
|
}}, nil)
|
|
|
|
projectCommandRunner := NewMockProjectCommandRunner()
|
|
When(projectCommandRunner.Plan(Any[command.ProjectContext]())).ThenReturn(command.ProjectResult{
|
|
PlanSuccess: &models.PlanSuccess{},
|
|
})
|
|
When(projectCommandRunner.Apply(Any[command.ProjectContext]())).ThenReturn(command.ProjectResult{
|
|
ApplySuccess: "success",
|
|
})
|
|
|
|
preWorkflowHooksCommandRunner := NewMockPreWorkflowHooksCommandRunner()
|
|
|
|
When(preWorkflowHooksCommandRunner.RunPreHooks(Any[*command.Context](), Any[*events.CommentCommand]())).ThenReturn(nil)
|
|
|
|
postWorkflowHooksCommandRunner := NewMockPostWorkflowHooksCommandRunner()
|
|
|
|
When(postWorkflowHooksCommandRunner.RunPostHooks(Any[*command.Context](), Any[*events.CommentCommand]())).ThenReturn(nil)
|
|
|
|
commitStatusUpdater := NewMockCommitStatusUpdater()
|
|
|
|
When(commitStatusUpdater.UpdateCombined(Any[logging.SimpleLogging](), Any[models.Repo](), Any[models.PullRequest](), Any[models.CommitStatus](), Any[command.Name]())).ThenReturn(nil)
|
|
|
|
ac := controllers.APIController{
|
|
APISecret: []byte(atlantisToken),
|
|
Locker: locker,
|
|
Logger: logger,
|
|
Scope: scope,
|
|
Parser: parser,
|
|
ProjectCommandBuilder: projectCommandBuilder,
|
|
ProjectPlanCommandRunner: projectCommandRunner,
|
|
ProjectApplyCommandRunner: projectCommandRunner,
|
|
PreWorkflowHooksCommandRunner: preWorkflowHooksCommandRunner,
|
|
PostWorkflowHooksCommandRunner: postWorkflowHooksCommandRunner,
|
|
VCSClient: vcsClient,
|
|
RepoAllowlistChecker: repoAllowlistChecker,
|
|
WorkingDir: workingDir,
|
|
WorkingDirLocker: workingDirLocker,
|
|
CommitStatusUpdater: commitStatusUpdater,
|
|
}
|
|
return ac, projectCommandBuilder, projectCommandRunner
|
|
}
|