mirror of
https://git.vectorsigma.ru/public/atlantis.git
synced 2026-07-28 21:48:25 +00:00
feat: New API endpoint to list locks (#5328)
Signed-off-by: Patrick Vinograd <patrick.vinograd@devoted.com>
This commit is contained in:
@@ -161,6 +161,38 @@ curl --request POST 'https://<ATLANTIS_HOST_NAME>/api/apply' \
|
||||
|
||||
The endpoints listed in this section are non-destructive and therefore don't require authentication nor special secret token.
|
||||
|
||||
### GET /api/locks
|
||||
|
||||
#### Description
|
||||
|
||||
List the currently held project locks.
|
||||
|
||||
#### Sample Request
|
||||
|
||||
```shell
|
||||
curl --request GET 'https://<ATLANTIS_HOST_NAME>/api/locks'
|
||||
```
|
||||
|
||||
#### Sample Response
|
||||
|
||||
```json
|
||||
{
|
||||
"Locks": [
|
||||
{
|
||||
"Name": "lock-id",
|
||||
"ProjectName": "terraform",
|
||||
"ProjectRepo": "owner/repo",
|
||||
"ProjectRepoPath": "/path",
|
||||
"PullID": "123",
|
||||
"PullURL": "url",
|
||||
"User": "jdoe",
|
||||
"Workspace": "default",
|
||||
"Time": "2025-02-13T16:47:42.040856-08:00"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### GET /status
|
||||
|
||||
#### Description
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"net/http"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/go-playground/validator/v10"
|
||||
"github.com/runatlantis/atlantis/server/core/locking"
|
||||
@@ -159,6 +160,55 @@ func (a *APIController) Apply(w http.ResponseWriter, r *http.Request) {
|
||||
a.respond(w, logging.Warn, code, "%s", string(response))
|
||||
}
|
||||
|
||||
type LockDetail struct {
|
||||
Name string
|
||||
ProjectName string
|
||||
ProjectRepo string
|
||||
ProjectRepoPath string
|
||||
PullID int `json:",string"`
|
||||
PullURL string
|
||||
User string
|
||||
Workspace string
|
||||
Time time.Time
|
||||
}
|
||||
|
||||
type ListLocksResult struct {
|
||||
Locks []LockDetail
|
||||
}
|
||||
|
||||
func (a *APIController) ListLocks(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
|
||||
locks, err := a.Locker.List()
|
||||
if err != nil {
|
||||
a.apiReportError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
result := ListLocksResult{}
|
||||
for name, lock := range locks {
|
||||
lockDetail := LockDetail{
|
||||
name,
|
||||
lock.Project.ProjectName,
|
||||
lock.Project.RepoFullName,
|
||||
lock.Project.Path,
|
||||
lock.Pull.Num,
|
||||
lock.Pull.URL,
|
||||
lock.User.Username,
|
||||
lock.Workspace,
|
||||
lock.Time,
|
||||
}
|
||||
result.Locks = append(result.Locks, lockDetail)
|
||||
}
|
||||
|
||||
response, err := json.Marshal(result)
|
||||
if err != nil {
|
||||
a.apiReportError(w, http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
a.respond(w, logging.Warn, http.StatusOK, "%s", string(response))
|
||||
}
|
||||
|
||||
func (a *APIController) apiSetup(ctx *command.Context) error {
|
||||
pull := ctx.Pull
|
||||
baseRepo := ctx.Pull.BaseRepo
|
||||
|
||||
@@ -3,9 +3,11 @@ 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"
|
||||
@@ -198,6 +200,62 @@ func TestAPIController_Apply(t *testing.T) {
|
||||
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()
|
||||
|
||||
@@ -1038,6 +1038,7 @@ func (s *Server) Start() error {
|
||||
s.Router.HandleFunc("/events", s.VCSEventsController.Post).Methods("POST")
|
||||
s.Router.HandleFunc("/api/plan", s.APIController.Plan).Methods("POST")
|
||||
s.Router.HandleFunc("/api/apply", s.APIController.Apply).Methods("POST")
|
||||
s.Router.HandleFunc("/api/locks", s.APIController.ListLocks).Methods("GET")
|
||||
s.Router.HandleFunc("/github-app/exchange-code", s.GithubAppController.ExchangeCode).Methods("GET")
|
||||
s.Router.HandleFunc("/github-app/setup", s.GithubAppController.New).Methods("GET")
|
||||
s.Router.HandleFunc("/locks", s.LocksController.DeleteLock).Methods("DELETE").Queries("id", "{id:.*}")
|
||||
|
||||
Reference in New Issue
Block a user