1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-02 20:35:25 +02:00

refactor(stacks): break swagger docs by type [EE-5381] (#8820)

This commit is contained in:
Chaim Lev-Ari 2023-04-27 11:03:55 +07:00 committed by GitHub
parent bbea0bc8a5
commit 77f8b9333a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 347 additions and 144 deletions

View file

@ -23,23 +23,8 @@ func (e *InvalidPayloadError) Error() string {
return e.msg
}
// @id EdgeStackCreate
// @summary Create an EdgeStack
// @description **Access policy**: administrator
// @tags edge_stacks
// @security ApiKeyAuth
// @security jwt
// @produce json
// @param method query string true "Creation Method" Enums(file,string,repository)
// @param body_string body swarmStackFromFileContentPayload true "Required when using method=string"
// @param body_file body swarmStackFromFileUploadPayload true "Required when using method=file"
// @param body_repository body swarmStackFromGitRepositoryPayload true "Required when using method=repository"
// @success 200 {object} portainer.EdgeStack
// @failure 500
// @failure 503 "Edge compute features are disabled"
// @router /edge_stacks [post]
func (handler *Handler) edgeStackCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
method, err := request.RetrieveQueryParameter(r, "method", false)
method, err := request.RetrieveRouteVariableValue(r, "method")
if err != nil {
return httperror.BadRequest("Invalid query parameter: method", err)
}
@ -74,7 +59,7 @@ func (handler *Handler) createSwarmStack(method string, dryrun bool, userID port
case "file":
return handler.createSwarmStackFromFileUpload(r, dryrun)
}
return nil, errors.New("Invalid value for query parameter: method. Value must be one of: string, repository or file")
return nil, &InvalidPayloadError{"Invalid value for query parameter: method. Value must be one of: string, repository or file"}
}
type swarmStackFromFileContentPayload struct {
@ -109,6 +94,19 @@ func (payload *swarmStackFromFileContentPayload) Validate(r *http.Request) error
return nil
}
// @id EdgeStackCreateString
// @summary Create an EdgeStack from a text
// @description **Access policy**: administrator
// @tags edge_stacks
// @security ApiKeyAuth
// @security jwt
// @produce json
// @param body body swarmStackFromFileContentPayload true "stack config"
// @param dryrun query string false "if true, will not create an edge stack, but just will check the settings and return a non-persisted edge stack object"
// @success 200 {object} portainer.EdgeStack
// @failure 500
// @failure 503 "Edge compute features are disabled"
// @router /edge_stacks/create/string [post]
func (handler *Handler) createSwarmStackFromFileContent(r *http.Request, dryrun bool) (*portainer.EdgeStack, error) {
var payload swarmStackFromFileContentPayload
err := request.DecodeAndValidateJSONPayload(r, &payload)
@ -229,6 +227,20 @@ func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) err
return nil
}
// @id EdgeStackCreateRepository
// @summary Create an EdgeStack from a git repository
// @description **Access policy**: administrator
// @tags edge_stacks
// @security ApiKeyAuth
// @security jwt
// @produce json
// @param method query string true "Creation Method" Enums(file,string,repository)
// @param body body swarmStackFromGitRepositoryPayload true "stack config"
// @param dryrun query string false "if true, will not create an edge stack, but just will check the settings and return a non-persisted edge stack object"
// @success 200 {object} portainer.EdgeStack
// @failure 500
// @failure 503 "Edge compute features are disabled"
// @router /edge_stacks/create/repository [post]
func (handler *Handler) createSwarmStackFromGitRepository(r *http.Request, dryrun bool, userID portainer.UserID) (*portainer.EdgeStack, error) {
var payload swarmStackFromGitRepositoryPayload
err := request.DecodeAndValidateJSONPayload(r, &payload)
@ -299,14 +311,14 @@ func (payload *swarmStackFromFileUploadPayload) Validate(r *http.Request) error
}
payload.EdgeGroups = edgeGroups
deploymentType, err := request.RetrieveNumericMultiPartFormValue(r, "DeploymentType", true)
deploymentType, err := request.RetrieveNumericMultiPartFormValue(r, "DeploymentType", false)
if err != nil {
return &InvalidPayloadError{msg: "Invalid deployment type"}
}
payload.DeploymentType = portainer.EdgeStackDeploymentType(deploymentType)
var registries []portainer.RegistryID
request.RetrieveMultiPartFormJSONValue(r, "Registries", &registries, false)
err = request.RetrieveMultiPartFormJSONValue(r, "Registries", &registries, true)
if err != nil {
return errors.New("Invalid registry type")
}
@ -318,6 +330,27 @@ func (payload *swarmStackFromFileUploadPayload) Validate(r *http.Request) error
return nil
}
// @id EdgeStackCreateFile
// @summary Create an EdgeStack from file
// @description **Access policy**: administrator
// @tags edge_stacks
// @security ApiKeyAuth
// @security jwt
// @accept multipart/form-data
// @produce json
// @param Name formData string true "Name of the stack"
// @param file formData file true "Content of the Stack file"
// @param EdgeGroups formData string true "JSON stringified array of Edge Groups ids"
// @param DeploymentType formData int true "deploy type 0 - 'compose', 1 - 'kubernetes', 2 - 'nomad'"
// @param Registries formData string false "JSON stringified array of Registry ids to use for this stack"
// @param UseManifestNamespaces formData bool false "Uses the manifest's namespaces instead of the default one, relevant only for kube environments"
// @param PrePullImage formData bool false "Pre Pull image"
// @param RetryDeploy formData bool false "Retry deploy"
// @param dryrun query string false "if true, will not create an edge stack, but just will check the settings and return a non-persisted edge stack object"
// @success 200 {object} portainer.EdgeStack
// @failure 500
// @failure 503 "Edge compute features are disabled"
// @router /edge_stacks/create/file [post]
func (handler *Handler) createSwarmStackFromFileUpload(r *http.Request, dryrun bool) (*portainer.EdgeStack, error) {
payload := &swarmStackFromFileUploadPayload{}
err := payload.Validate(r)

View file

@ -16,12 +16,13 @@ import (
// @tags edge_stacks
// @produce json
// @param id path int true "EdgeStack Id"
// @param environmentId path int true "Environment identifier"
// @success 200 {object} portainer.EdgeStack
// @failure 500
// @failure 400
// @failure 404
// @failure 403
// @router /edge_stacks/{id}/status/{endpoint_id} [delete]
// @router /edge_stacks/{id}/status/{environmentId} [delete]
func (handler *Handler) edgeStackStatusDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
if err != nil {

View file

@ -237,7 +237,7 @@ func TestCreateAndInspect(t *testing.T) {
r := bytes.NewBuffer(jsonPayload)
// Create EdgeStack
req, err := http.NewRequest(http.MethodPost, "/edge_stacks?method=string", r)
req, err := http.NewRequest(http.MethodPost, "/edge_stacks/create/string", r)
if err != nil {
t.Fatal("request error:", err)
}
@ -290,37 +290,32 @@ func TestCreateWithInvalidPayload(t *testing.T) {
cases := []struct {
Name string
Payload interface{}
QueryString string
ExpectedStatusCode int
Method string
}{
{
Name: "Invalid query string parameter",
Name: "Invalid method parameter",
Payload: swarmStackFromFileContentPayload{},
QueryString: "invalid=query-string",
Method: "invalid",
ExpectedStatusCode: 400,
},
{
Name: "Invalid creation method",
Payload: swarmStackFromFileContentPayload{},
QueryString: "method=invalid-creation-method",
ExpectedStatusCode: 500,
},
{
Name: "Empty swarmStackFromFileContentPayload with string method",
Payload: swarmStackFromFileContentPayload{},
QueryString: "method=string",
Method: "string",
ExpectedStatusCode: 400,
},
{
Name: "Empty swarmStackFromFileContentPayload with repository method",
Payload: swarmStackFromFileContentPayload{},
QueryString: "method=repository",
Method: "repository",
ExpectedStatusCode: 400,
},
{
Name: "Empty swarmStackFromFileContentPayload with file method",
Payload: swarmStackFromFileContentPayload{},
QueryString: "method=file",
Method: "file",
ExpectedStatusCode: 400,
},
{
@ -331,7 +326,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
EdgeGroups: edgeStack.EdgeGroups,
DeploymentType: edgeStack.DeploymentType,
},
QueryString: "method=string",
Method: "string",
ExpectedStatusCode: 500,
},
{
@ -342,7 +337,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
EdgeGroups: []portainer.EdgeGroupID{},
DeploymentType: edgeStack.DeploymentType,
},
QueryString: "method=string",
Method: "string",
ExpectedStatusCode: 400,
},
{
@ -353,7 +348,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
EdgeGroups: []portainer.EdgeGroupID{1},
DeploymentType: portainer.EdgeStackDeploymentKubernetes,
},
QueryString: "method=string",
Method: "string",
ExpectedStatusCode: 500,
},
{
@ -364,7 +359,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
EdgeGroups: []portainer.EdgeGroupID{1},
DeploymentType: portainer.EdgeStackDeploymentCompose,
},
QueryString: "method=string",
Method: "string",
ExpectedStatusCode: 400,
},
{
@ -380,7 +375,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
EdgeGroups: []portainer.EdgeGroupID{1},
DeploymentType: portainer.EdgeStackDeploymentCompose,
},
QueryString: "method=repository",
Method: "repository",
ExpectedStatusCode: 500,
},
}
@ -394,7 +389,7 @@ func TestCreateWithInvalidPayload(t *testing.T) {
r := bytes.NewBuffer(jsonPayload)
// Create EdgeStack
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("/edge_stacks?%s", tc.QueryString), r)
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("/edge_stacks/create/%s", tc.Method), r)
if err != nil {
t.Fatal("request error:", err)
}

View file

@ -34,7 +34,7 @@ func NewHandler(bouncer *security.RequestBouncer, dataStore dataservices.DataSto
edgeStacksService: edgeStacksService,
}
h.Handle("/edge_stacks",
h.Handle("/edge_stacks/create/{method}",
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeStackCreate)))).Methods(http.MethodPost)
h.Handle("/edge_stacks",
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeStackList)))).Methods(http.MethodGet)