mirror of
https://github.com/portainer/portainer.git
synced 2025-08-02 20:35:25 +02:00
refactor(edge/stacks): separate create by method [EE-4947] (#8898)
This commit is contained in:
parent
1ff19f8604
commit
426c132f97
15 changed files with 1225 additions and 1123 deletions
|
@ -1,12 +1,6 @@
|
|||
package edgestacks
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"reflect"
|
||||
"strconv"
|
||||
"testing"
|
||||
"time"
|
||||
|
@ -159,745 +153,3 @@ func createEdgeStack(t *testing.T, store dataservices.DataStore, endpointID port
|
|||
|
||||
return edgeStack
|
||||
}
|
||||
|
||||
// Inspect
|
||||
func TestInspectInvalidEdgeID(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
EdgeStackID string
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{"Invalid EdgeStackID", "x", 400},
|
||||
{"Non-existing EdgeStackID", "5", 404},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
req, err := http.NewRequest(http.MethodGet, "/edge_stacks/"+tc.EdgeStackID, nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Create
|
||||
func TestCreateAndInspect(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
// Create Endpoint, EdgeGroup and EndpointRelation
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeGroup := portainer.EdgeGroup{
|
||||
ID: 1,
|
||||
Name: "EdgeGroup 1",
|
||||
Dynamic: false,
|
||||
TagIDs: nil,
|
||||
Endpoints: []portainer.EndpointID{endpoint.ID},
|
||||
PartialMatch: false,
|
||||
}
|
||||
|
||||
err := handler.DataStore.EdgeGroup().Create(&edgeGroup)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
endpointRelation := portainer.EndpointRelation{
|
||||
EndpointID: endpoint.ID,
|
||||
EdgeStacks: map[portainer.EdgeStackID]bool{},
|
||||
}
|
||||
|
||||
err = handler.DataStore.EndpointRelation().Create(&endpointRelation)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
payload := swarmStackFromFileContentPayload{
|
||||
Name: "Test Stack",
|
||||
StackFileContent: "stack content",
|
||||
EdgeGroups: []portainer.EdgeGroupID{1},
|
||||
DeploymentType: portainer.EdgeStackDeploymentCompose,
|
||||
}
|
||||
|
||||
jsonPayload, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
t.Fatal("JSON marshal error:", err)
|
||||
}
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
|
||||
// Create EdgeStack
|
||||
req, err := http.NewRequest(http.MethodPost, "/edge_stacks/create/string", r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
data := portainer.EdgeStack{}
|
||||
err = json.NewDecoder(rec.Body).Decode(&data)
|
||||
if err != nil {
|
||||
t.Fatal("error decoding response:", err)
|
||||
}
|
||||
|
||||
// Inspect
|
||||
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/edge_stacks/%d", data.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
data = portainer.EdgeStack{}
|
||||
err = json.NewDecoder(rec.Body).Decode(&data)
|
||||
if err != nil {
|
||||
t.Fatal("error decoding response:", err)
|
||||
}
|
||||
|
||||
if payload.Name != data.Name {
|
||||
t.Fatalf("expected EdgeStack Name %s, found %s", payload.Name, data.Name)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCreateWithInvalidPayload(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
Payload interface{}
|
||||
ExpectedStatusCode int
|
||||
Method string
|
||||
}{
|
||||
{
|
||||
Name: "Invalid method parameter",
|
||||
Payload: swarmStackFromFileContentPayload{},
|
||||
Method: "invalid",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
|
||||
{
|
||||
Name: "Empty swarmStackFromFileContentPayload with string method",
|
||||
Payload: swarmStackFromFileContentPayload{},
|
||||
Method: "string",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
{
|
||||
Name: "Empty swarmStackFromFileContentPayload with repository method",
|
||||
Payload: swarmStackFromFileContentPayload{},
|
||||
Method: "repository",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
{
|
||||
Name: "Empty swarmStackFromFileContentPayload with file method",
|
||||
Payload: swarmStackFromFileContentPayload{},
|
||||
Method: "file",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
{
|
||||
Name: "Duplicated EdgeStack Name",
|
||||
Payload: swarmStackFromFileContentPayload{
|
||||
Name: edgeStack.Name,
|
||||
StackFileContent: "content",
|
||||
EdgeGroups: edgeStack.EdgeGroups,
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
Method: "string",
|
||||
ExpectedStatusCode: 500,
|
||||
},
|
||||
{
|
||||
Name: "Empty EdgeStack Groups",
|
||||
Payload: swarmStackFromFileContentPayload{
|
||||
Name: edgeStack.Name,
|
||||
StackFileContent: "content",
|
||||
EdgeGroups: []portainer.EdgeGroupID{},
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
Method: "string",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
{
|
||||
Name: "EdgeStackDeploymentKubernetes with Docker endpoint",
|
||||
Payload: swarmStackFromFileContentPayload{
|
||||
Name: "Stack name",
|
||||
StackFileContent: "content",
|
||||
EdgeGroups: []portainer.EdgeGroupID{1},
|
||||
DeploymentType: portainer.EdgeStackDeploymentKubernetes,
|
||||
},
|
||||
Method: "string",
|
||||
ExpectedStatusCode: 500,
|
||||
},
|
||||
{
|
||||
Name: "Empty Stack File Content",
|
||||
Payload: swarmStackFromFileContentPayload{
|
||||
Name: "Stack name",
|
||||
StackFileContent: "",
|
||||
EdgeGroups: []portainer.EdgeGroupID{1},
|
||||
DeploymentType: portainer.EdgeStackDeploymentCompose,
|
||||
},
|
||||
Method: "string",
|
||||
ExpectedStatusCode: 400,
|
||||
},
|
||||
{
|
||||
Name: "Clone Git respository error",
|
||||
Payload: swarmStackFromGitRepositoryPayload{
|
||||
Name: "Stack name",
|
||||
RepositoryURL: "github.com/portainer/portainer",
|
||||
RepositoryReferenceName: "ref name",
|
||||
RepositoryAuthentication: false,
|
||||
RepositoryUsername: "",
|
||||
RepositoryPassword: "",
|
||||
FilePathInRepository: "/file/path",
|
||||
EdgeGroups: []portainer.EdgeGroupID{1},
|
||||
DeploymentType: portainer.EdgeStackDeploymentCompose,
|
||||
},
|
||||
Method: "repository",
|
||||
ExpectedStatusCode: 500,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
jsonPayload, err := json.Marshal(tc.Payload)
|
||||
if err != nil {
|
||||
t.Fatal("JSON marshal error:", err)
|
||||
}
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
|
||||
// Create EdgeStack
|
||||
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("/edge_stacks/create/%s", tc.Method), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Delete
|
||||
func TestDeleteAndInspect(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
// Create
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
// Inspect
|
||||
req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
data := portainer.EdgeStack{}
|
||||
err = json.NewDecoder(rec.Body).Decode(&data)
|
||||
if err != nil {
|
||||
t.Fatal("error decoding response:", err)
|
||||
}
|
||||
|
||||
if data.ID != edgeStack.ID {
|
||||
t.Fatalf("expected EdgeStackID %d, found %d", int(edgeStack.ID), data.ID)
|
||||
}
|
||||
|
||||
// Delete
|
||||
req, err = http.NewRequest(http.MethodDelete, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusNoContent {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusNoContent, rec.Code)
|
||||
}
|
||||
|
||||
// Inspect
|
||||
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusNotFound {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusNotFound, rec.Code)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDeleteInvalidEdgeStack(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
cases := []struct {
|
||||
Name string
|
||||
URL string
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{Name: "Non-existing EdgeStackID", URL: "/edge_stacks/-1", ExpectedStatusCode: http.StatusNotFound},
|
||||
{Name: "Invalid EdgeStackID", URL: "/edge_stacks/aaaaaaa", ExpectedStatusCode: http.StatusBadRequest},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
req, err := http.NewRequest(http.MethodDelete, tc.URL, nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Update
|
||||
func TestUpdateAndInspect(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
// Update edge stack: create new Endpoint, EndpointRelation and EdgeGroup
|
||||
endpointID := portainer.EndpointID(6)
|
||||
newEndpoint := createEndpointWithId(t, handler.DataStore, endpointID)
|
||||
|
||||
err := handler.DataStore.Endpoint().Create(&newEndpoint)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
endpointRelation := portainer.EndpointRelation{
|
||||
EndpointID: endpointID,
|
||||
EdgeStacks: map[portainer.EdgeStackID]bool{
|
||||
edgeStack.ID: true,
|
||||
},
|
||||
}
|
||||
|
||||
err = handler.DataStore.EndpointRelation().Create(&endpointRelation)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newEdgeGroup := portainer.EdgeGroup{
|
||||
ID: 2,
|
||||
Name: "EdgeGroup 2",
|
||||
Dynamic: false,
|
||||
TagIDs: nil,
|
||||
Endpoints: []portainer.EndpointID{newEndpoint.ID},
|
||||
PartialMatch: false,
|
||||
}
|
||||
|
||||
err = handler.DataStore.EdgeGroup().Create(&newEdgeGroup)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
newVersion := 238
|
||||
payload := updateEdgeStackPayload{
|
||||
StackFileContent: "update-test",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: append(edgeStack.EdgeGroups, newEdgeGroup.ID),
|
||||
DeploymentType: portainer.EdgeStackDeploymentCompose,
|
||||
}
|
||||
|
||||
jsonPayload, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
// Get updated edge stack
|
||||
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
data := portainer.EdgeStack{}
|
||||
err = json.NewDecoder(rec.Body).Decode(&data)
|
||||
if err != nil {
|
||||
t.Fatal("error decoding response:", err)
|
||||
}
|
||||
|
||||
if data.Version != *payload.Version {
|
||||
t.Fatalf("expected EdgeStackID %d, found %d", edgeStack.Version, data.Version)
|
||||
}
|
||||
|
||||
if data.DeploymentType != payload.DeploymentType {
|
||||
t.Fatalf("expected DeploymentType %d, found %d", edgeStack.DeploymentType, data.DeploymentType)
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(data.EdgeGroups, payload.EdgeGroups) {
|
||||
t.Fatalf("expected EdgeGroups to be equal")
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateWithInvalidEdgeGroups(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
//newEndpoint := createEndpoint(t, handler.DataStore)
|
||||
newEdgeGroup := portainer.EdgeGroup{
|
||||
ID: 2,
|
||||
Name: "EdgeGroup 2",
|
||||
Dynamic: false,
|
||||
TagIDs: nil,
|
||||
Endpoints: []portainer.EndpointID{8889},
|
||||
PartialMatch: false,
|
||||
}
|
||||
|
||||
handler.DataStore.EdgeGroup().Create(&newEdgeGroup)
|
||||
|
||||
newVersion := 238
|
||||
cases := []struct {
|
||||
Name string
|
||||
Payload updateEdgeStackPayload
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{
|
||||
"Update with non-existing EdgeGroupID",
|
||||
updateEdgeStackPayload{
|
||||
StackFileContent: "error-test",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: []portainer.EdgeGroupID{9999},
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
http.StatusInternalServerError,
|
||||
},
|
||||
{
|
||||
"Update with invalid EdgeGroup (non-existing Endpoint)",
|
||||
updateEdgeStackPayload{
|
||||
StackFileContent: "error-test",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: []portainer.EdgeGroupID{2},
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
http.StatusInternalServerError,
|
||||
},
|
||||
{
|
||||
"Update DeploymentType from Docker to Kubernetes",
|
||||
updateEdgeStackPayload{
|
||||
StackFileContent: "error-test",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: []portainer.EdgeGroupID{1},
|
||||
DeploymentType: portainer.EdgeStackDeploymentKubernetes,
|
||||
},
|
||||
http.StatusBadRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
jsonPayload, err := json.Marshal(tc.Payload)
|
||||
if err != nil {
|
||||
t.Fatal("JSON marshal error:", err)
|
||||
}
|
||||
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestUpdateWithInvalidPayload(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
newVersion := 238
|
||||
cases := []struct {
|
||||
Name string
|
||||
Payload updateEdgeStackPayload
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{
|
||||
"Update with empty StackFileContent",
|
||||
updateEdgeStackPayload{
|
||||
StackFileContent: "",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: edgeStack.EdgeGroups,
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
"Update with empty EdgeGroups",
|
||||
updateEdgeStackPayload{
|
||||
StackFileContent: "error-test",
|
||||
Version: &newVersion,
|
||||
EdgeGroups: []portainer.EdgeGroupID{},
|
||||
DeploymentType: edgeStack.DeploymentType,
|
||||
},
|
||||
http.StatusBadRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
jsonPayload, err := json.Marshal(tc.Payload)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Update Status
|
||||
func TestUpdateStatusAndInspect(t *testing.T) {
|
||||
handler, rawAPIKey, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
// Update edge stack status
|
||||
newStatus := portainer.EdgeStackStatusError
|
||||
payload := updateStatusPayload{
|
||||
Error: "test-error",
|
||||
Status: &newStatus,
|
||||
EndpointID: endpoint.ID,
|
||||
}
|
||||
|
||||
jsonPayload, err := json.Marshal(payload)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("/edge_stacks/%d/status", edgeStack.ID), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Set(portainer.PortainerAgentEdgeIDHeader, endpoint.EdgeID)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
// Get updated edge stack
|
||||
req, err = http.NewRequest(http.MethodGet, fmt.Sprintf("/edge_stacks/%d", edgeStack.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Add("x-api-key", rawAPIKey)
|
||||
rec = httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
|
||||
data := portainer.EdgeStack{}
|
||||
err = json.NewDecoder(rec.Body).Decode(&data)
|
||||
if err != nil {
|
||||
t.Fatal("error decoding response:", err)
|
||||
}
|
||||
|
||||
if !data.Status[endpoint.ID].Details.Error {
|
||||
t.Fatalf("expected EdgeStackStatusType %d, found %t", payload.Status, data.Status[endpoint.ID].Details.Error)
|
||||
}
|
||||
|
||||
if data.Status[endpoint.ID].Error != payload.Error {
|
||||
t.Fatalf("expected EdgeStackStatusError %s, found %s", payload.Error, data.Status[endpoint.ID].Error)
|
||||
}
|
||||
|
||||
if data.Status[endpoint.ID].EndpointID != payload.EndpointID {
|
||||
t.Fatalf("expected EndpointID %d, found %d", payload.EndpointID, data.Status[endpoint.ID].EndpointID)
|
||||
}
|
||||
}
|
||||
func TestUpdateStatusWithInvalidPayload(t *testing.T) {
|
||||
handler, _, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
// Update edge stack status
|
||||
statusError := portainer.EdgeStackStatusError
|
||||
statusOk := portainer.EdgeStackStatusOk
|
||||
cases := []struct {
|
||||
Name string
|
||||
Payload updateStatusPayload
|
||||
ExpectedErrorMessage string
|
||||
ExpectedStatusCode int
|
||||
}{
|
||||
{
|
||||
"Update with nil Status",
|
||||
updateStatusPayload{
|
||||
Error: "test-error",
|
||||
Status: nil,
|
||||
EndpointID: endpoint.ID,
|
||||
},
|
||||
"Invalid status",
|
||||
400,
|
||||
},
|
||||
{
|
||||
"Update with error status and empty error message",
|
||||
updateStatusPayload{
|
||||
Error: "",
|
||||
Status: &statusError,
|
||||
EndpointID: endpoint.ID,
|
||||
},
|
||||
"Error message is mandatory when status is error",
|
||||
400,
|
||||
},
|
||||
{
|
||||
"Update with missing EndpointID",
|
||||
updateStatusPayload{
|
||||
Error: "",
|
||||
Status: &statusOk,
|
||||
EndpointID: 0,
|
||||
},
|
||||
"Invalid EnvironmentID",
|
||||
400,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.Name, func(t *testing.T) {
|
||||
jsonPayload, err := json.Marshal(tc.Payload)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
r := bytes.NewBuffer(jsonPayload)
|
||||
req, err := http.NewRequest(http.MethodPut, fmt.Sprintf("/edge_stacks/%d/status", edgeStack.ID), r)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Set(portainer.PortainerAgentEdgeIDHeader, endpoint.EdgeID)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != tc.ExpectedStatusCode {
|
||||
t.Fatalf("expected a %d response, found: %d", tc.ExpectedStatusCode, rec.Code)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Delete Status
|
||||
func TestDeleteStatus(t *testing.T) {
|
||||
handler, _, teardown := setupHandler(t)
|
||||
defer teardown()
|
||||
|
||||
endpoint := createEndpoint(t, handler.DataStore)
|
||||
edgeStack := createEdgeStack(t, handler.DataStore, endpoint.ID)
|
||||
|
||||
req, err := http.NewRequest(http.MethodDelete, fmt.Sprintf("/edge_stacks/%d/status/%d", edgeStack.ID, endpoint.ID), nil)
|
||||
if err != nil {
|
||||
t.Fatal("request error:", err)
|
||||
}
|
||||
|
||||
req.Header.Set(portainer.PortainerAgentEdgeIDHeader, endpoint.EdgeID)
|
||||
rec := httptest.NewRecorder()
|
||||
handler.ServeHTTP(rec, req)
|
||||
|
||||
if rec.Code != http.StatusOK {
|
||||
t.Fatalf("expected a %d response, found: %d", http.StatusOK, rec.Code)
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue