mirror of
https://github.com/portainer/portainer.git
synced 2025-07-24 15:59:41 +02:00
docs(api): document apis with swagger (#4678)
* feat(api): introduce swagger * feat(api): anottate api * chore(api): tag endpoints * chore(api): remove tags * chore(api): add docs for oauth auth * chore(api): document create endpoint api * chore(api): document endpoint inspect and list * chore(api): document endpoint update and snapshots * docs(endpointgroups): document groups api * docs(auth): document auth api * chore(build): introduce a yarn script to build api docs * docs(api): document auth * docs(customtemplates): document customtemplates api * docs(tags): document api * docs(api): document the use of token * docs(dockerhub): document dockerhub api * docs(edgegroups): document edgegroups api * docs(edgejobs): document api * docs(edgestacks): doc api * docs(http/upload): add security * docs(api): document edge templates * docs(edge): document edge jobs * docs(endpointgroups): change description * docs(endpoints): document missing apis * docs(motd): doc api * docs(registries): doc api * docs(resourcecontrol): api doc * docs(role): add swagger docs * docs(settings): add swagger docs * docs(api/status): add swagger docs * docs(api/teammembership): add swagger docs * docs(api/teams): add swagger docs * docs(api/templates): add swagger docs * docs(api/users): add swagger docs * docs(api/webhooks): add swagger docs * docs(api/webscokets): add swagger docs * docs(api/stacks): swagger * docs(api): fix missing apis * docs(swagger): regen * chore(build): remove docs from build * docs(api): update tags * docs(api): document tags * docs(api): add description * docs(api): rename jwt token * docs(api): add info about types * docs(api): document types * docs(api): update request types annotation * docs(api): doc registry and resource control * chore(docs): add snippet * docs(api): add description to role * docs(api): add types for settings * docs(status): add types * style(swagger): remove documented code * docs(http/upload): update docs with types * docs(http/tags): add types * docs(api/custom_templates): add types * docs(api/teammembership): add types * docs(http/teams): add types * docs(http/stacks): add types * docs(edge): add types to edgestack * docs(http/teammembership): remove double returns * docs(api/user): add types * docs(http): fixes to make file built * chore(snippets): add scope to swagger snippet * chore(deps): install swag * chore(swagger): remove handler * docs(api): add description * docs(api): ignore docs folder * docs(api): add contributing guidelines * docs(api): cleanup handler * chore(deps): require swaggo * fix(auth): fix typo * fix(docs): make http ids pascal case * feat(edge): add ids to http handlers * fix(docs): add ids * fix(docs): show correct api version * chore(deps): remove swaggo dependency * chore(docs): add install script for swag
This commit is contained in:
parent
90f5a6cd0d
commit
50b57614cf
125 changed files with 8264 additions and 4833 deletions
|
@ -10,18 +10,21 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
)
|
||||
|
||||
type authenticatePayload struct {
|
||||
Username string
|
||||
Password string
|
||||
// Username
|
||||
Username string `example:"admin" validate:"required"`
|
||||
// Password
|
||||
Password string `example:"mypassword" validate:"required"`
|
||||
}
|
||||
|
||||
type authenticateResponse struct {
|
||||
JWT string `json:"jwt"`
|
||||
// JWT token used to authenticate against the API
|
||||
JWT string `json:"jwt" example:"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6MSwidXNlcm5hbWUiOiJhZG1pbiIsInJvbGUiOjEsImV4cCI6MTQ5OTM3NjE1NH0.NJ6vE8FY1WG6jsRQzfMqeatJ4vh2TWAeeYfDhP71YEE"`
|
||||
}
|
||||
|
||||
func (payload *authenticatePayload) Validate(r *http.Request) error {
|
||||
|
@ -34,6 +37,18 @@ func (payload *authenticatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id AuthenticateUser
|
||||
// @summary Authenticate
|
||||
// @description Use this endpoint to authenticate against Portainer using a username and password.
|
||||
// @tags auth
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body authenticatePayload true "Credentials used for authentication"
|
||||
// @success 200 {object} authenticateResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 422 "Invalid Credentials"
|
||||
// @failure 500 "Server error"
|
||||
// @router /auth [post]
|
||||
func (handler *Handler) authenticate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload authenticatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
"github.com/asaskevich/govalidator"
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
)
|
||||
|
||||
type oauthPayload struct {
|
||||
// OAuth code returned from OAuth Provided
|
||||
Code string
|
||||
}
|
||||
|
||||
|
@ -24,6 +25,17 @@ func (payload *oauthPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id AuthenticateOauth
|
||||
// @summary Authenticate with OAuth
|
||||
// @tags auth
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body oauthPayload true "OAuth Credentials used for authentication"
|
||||
// @success 200 {object} authenticateResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 422 "Invalid Credentials"
|
||||
// @failure 500 "Server error"
|
||||
// @router /auth/oauth/validate [post]
|
||||
func (handler *Handler) authenticateOAuth(code string, settings *portainer.OAuthSettings) (string, error) {
|
||||
if code == "" {
|
||||
return "", errors.New("Invalid OAuth authorization code")
|
||||
|
|
|
@ -8,7 +8,13 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// POST request on /logout
|
||||
// @id Logout
|
||||
// @summary Logout
|
||||
// @security jwt
|
||||
// @tags auth
|
||||
// @success 204 "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /auth/logout [post]
|
||||
func (handler *Handler) logout(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
if err != nil {
|
||||
|
|
|
@ -15,6 +15,27 @@ import (
|
|||
"github.com/portainer/portainer/api/internal/authorization"
|
||||
)
|
||||
|
||||
// @id CustomTemplateCreate
|
||||
// @summary Create a custom template
|
||||
// @description Create a custom template.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @accept json, multipart/form-data
|
||||
// @produce json
|
||||
// @param method query string true "method for creating template" Enums(string, file, repository)
|
||||
// @param body_string body customTemplateFromFileContentPayload false "Required when using method=string"
|
||||
// @param body_repository body customTemplateFromGitRepositoryPayload false "Required when using method=repository"
|
||||
// @param Title formData string false "Title of the template. required when method is file"
|
||||
// @param Description formData string false "Description of the template. required when method is file"
|
||||
// @param Note formData string false "A note that will be displayed in the UI. Supports HTML content"
|
||||
// @param Platform formData int false "Platform associated to the template (1 - 'linux', 2 - 'windows'). required when method is file" Enums(1,2)
|
||||
// @param Type formData int false "Type of created stack (1 - swarm, 2 - compose), required when method is file" Enums(1,2)
|
||||
// @param file formData file false "required when method is file"
|
||||
// @success 200 {object} portainer.CustomTemplate
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates [post]
|
||||
func (handler *Handler) customTemplateCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
|
@ -74,13 +95,21 @@ func (handler *Handler) createCustomTemplate(method string, r *http.Request) (*p
|
|||
}
|
||||
|
||||
type customTemplateFromFileContentPayload struct {
|
||||
Logo string
|
||||
Title string
|
||||
FileContent string
|
||||
Description string
|
||||
Note string
|
||||
Platform portainer.CustomTemplatePlatform
|
||||
Type portainer.StackType
|
||||
// URL of the template's logo
|
||||
Logo string `example:"https://cloudinovasi.id/assets/img/logos/nginx.png"`
|
||||
// Title of the template
|
||||
Title string `example:"Nginx" validate:"required"`
|
||||
// Description of the template
|
||||
Description string `example:"High performance web server" validate:"required"`
|
||||
// A note that will be displayed in the UI. Supports HTML content
|
||||
Note string `example:"This is my <b>custom</b> template"`
|
||||
// Platform associated to the template.
|
||||
// Valid values are: 1 - 'linux', 2 - 'windows'
|
||||
Platform portainer.CustomTemplatePlatform `example:"1" enums:"1,2" validate:"required"`
|
||||
// Type of created stack (1 - swarm, 2 - compose)
|
||||
Type portainer.StackType `example:"1" enums:"1,2" validate:"required"`
|
||||
// Content of stack file
|
||||
FileContent string `validate:"required"`
|
||||
}
|
||||
|
||||
func (payload *customTemplateFromFileContentPayload) Validate(r *http.Request) error {
|
||||
|
@ -132,18 +161,32 @@ func (handler *Handler) createCustomTemplateFromFileContent(r *http.Request) (*p
|
|||
}
|
||||
|
||||
type customTemplateFromGitRepositoryPayload struct {
|
||||
Logo string
|
||||
Title string
|
||||
Description string
|
||||
Note string
|
||||
Platform portainer.CustomTemplatePlatform
|
||||
Type portainer.StackType
|
||||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
// URL of the template's logo
|
||||
Logo string `example:"https://cloudinovasi.id/assets/img/logos/nginx.png"`
|
||||
// Title of the template
|
||||
Title string `example:"Nginx" validate:"required"`
|
||||
// Description of the template
|
||||
Description string `example:"High performance web server" validate:"required"`
|
||||
// A note that will be displayed in the UI. Supports HTML content
|
||||
Note string `example:"This is my <b>custom</b> template"`
|
||||
// Platform associated to the template.
|
||||
// Valid values are: 1 - 'linux', 2 - 'windows'
|
||||
Platform portainer.CustomTemplatePlatform `example:"1" enums:"1,2" validate:"required"`
|
||||
// Type of created stack (1 - swarm, 2 - compose)
|
||||
Type portainer.StackType `example:"1" enums:"1,2" validate:"required"`
|
||||
|
||||
// URL of a Git repository hosting the Stack file
|
||||
RepositoryURL string `example:"https://github.com/openfaas/faas" validate:"required"`
|
||||
// Reference name of a Git repository hosting the Stack file
|
||||
RepositoryReferenceName string `example:"refs/heads/master"`
|
||||
// Use basic authentication to clone the Git repository
|
||||
RepositoryAuthentication bool `example:"true"`
|
||||
// Username used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryUsername string `example:"myGitUsername"`
|
||||
// Password used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryPassword string `example:"myGitPassword"`
|
||||
// Path to the Stack file inside the Git repository
|
||||
ComposeFilePathInRepository string `example:"docker-compose.yml" default:"docker-compose.yml"`
|
||||
}
|
||||
|
||||
func (payload *customTemplateFromGitRepositoryPayload) Validate(r *http.Request) error {
|
||||
|
|
|
@ -13,6 +13,19 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// @id CustomTemplateDelete
|
||||
// @summary Remove a template
|
||||
// @description Remove a template.
|
||||
// @description **Access policy**: authorized
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @param id path int true "Template identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Access denied to resource"
|
||||
// @failure 404 "Template not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates/{id} [delete]
|
||||
func (handler *Handler) customTemplateDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
customTemplateID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,19 @@ type fileResponse struct {
|
|||
FileContent string
|
||||
}
|
||||
|
||||
// GET request on /api/custom_templates/:id/file
|
||||
// @id CustomTemplateFile
|
||||
// @summary Get Template stack file content.
|
||||
// @description Retrieve the content of the Stack file for the specified custom template
|
||||
// @description **Access policy**: authorized
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Template identifier"
|
||||
// @success 200 {object} fileResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Custom template not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates/{id}/file [get]
|
||||
func (handler *Handler) customTemplateFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
customTemplateID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,12 +7,26 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// @id CustomTemplateInspect
|
||||
// @summary Inspect a custom template
|
||||
// @description Retrieve details about a template.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Template identifier"
|
||||
// @success 200 {object} portainer.CustomTemplate "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Template not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates/{id} [get]
|
||||
func (handler *Handler) customTemplateInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
customTemplateID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -10,6 +10,16 @@ import (
|
|||
"github.com/portainer/portainer/api/internal/authorization"
|
||||
)
|
||||
|
||||
// @id CustomTemplateList
|
||||
// @summary List available custom templates
|
||||
// @description List available custom templates.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.CustomTemplate "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates [get]
|
||||
func (handler *Handler) customTemplateList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
customTemplates, err := handler.DataStore.CustomTemplate().CustomTemplates()
|
||||
if err != nil {
|
||||
|
|
|
@ -17,13 +17,21 @@ import (
|
|||
)
|
||||
|
||||
type customTemplateUpdatePayload struct {
|
||||
Logo string
|
||||
Title string
|
||||
Description string
|
||||
Note string
|
||||
Platform portainer.CustomTemplatePlatform
|
||||
Type portainer.StackType
|
||||
FileContent string
|
||||
// URL of the template's logo
|
||||
Logo string `example:"https://cloudinovasi.id/assets/img/logos/nginx.png"`
|
||||
// Title of the template
|
||||
Title string `example:"Nginx" validate:"required"`
|
||||
// Description of the template
|
||||
Description string `example:"High performance web server" validate:"required"`
|
||||
// A note that will be displayed in the UI. Supports HTML content
|
||||
Note string `example:"This is my <b>custom</b> template"`
|
||||
// Platform associated to the template.
|
||||
// Valid values are: 1 - 'linux', 2 - 'windows'
|
||||
Platform portainer.CustomTemplatePlatform `example:"1" enums:"1,2" validate:"required"`
|
||||
// Type of created stack (1 - swarm, 2 - compose)
|
||||
Type portainer.StackType `example:"1" enums:"1,2" validate:"required"`
|
||||
// Content of stack file
|
||||
FileContent string `validate:"required"`
|
||||
}
|
||||
|
||||
func (payload *customTemplateUpdatePayload) Validate(r *http.Request) error {
|
||||
|
@ -45,6 +53,22 @@ func (payload *customTemplateUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id CustomTemplateUpdate
|
||||
// @summary Update a template
|
||||
// @description Update a template.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags custom_templates
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Template identifier"
|
||||
// @param body body customTemplateUpdatePayload true "Template details"
|
||||
// @success 200 {object} portainer.CustomTemplate "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied to access template"
|
||||
// @failure 404 "Template not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /custom_templates/{id} [put]
|
||||
func (handler *Handler) customTemplateUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
customTemplateID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,16 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// GET request on /api/dockerhub
|
||||
// @id DockerHubInspect
|
||||
// @summary Retrieve DockerHub information
|
||||
// @description Use this endpoint to retrieve the information used to connect to the DockerHub
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags dockerhub
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {object} portainer.DockerHub
|
||||
// @failure 500 "Server error"
|
||||
// @router /dockerhub [get]
|
||||
func (handler *Handler) dockerhubInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
dockerhub, err := handler.DataStore.DockerHub().DockerHub()
|
||||
if err != nil {
|
||||
|
|
|
@ -8,13 +8,16 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type dockerhubUpdatePayload struct {
|
||||
Authentication bool
|
||||
Username string
|
||||
Password string
|
||||
// Enable authentication against DockerHub
|
||||
Authentication bool `validate:"required" example:"false"`
|
||||
// Username used to authenticate against the DockerHub
|
||||
Username string `validate:"required" example:"hub_user"`
|
||||
// Password used to authenticate against the DockerHub
|
||||
Password string `validate:"required" example:"hub_password"`
|
||||
}
|
||||
|
||||
func (payload *dockerhubUpdatePayload) Validate(r *http.Request) error {
|
||||
|
@ -24,7 +27,19 @@ func (payload *dockerhubUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/dockerhub
|
||||
// @id DockerHubUpdate
|
||||
// @summary Update DockerHub information
|
||||
// @description Use this endpoint to update the information used to connect to the DockerHub
|
||||
// @description **Access policy**: administrator
|
||||
// @tags dockerhub
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body dockerhubUpdatePayload true "DockerHub information"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /dockerhub [put]
|
||||
func (handler *Handler) dockerhubUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload dockerhubUpdatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type edgeGroupCreatePayload struct {
|
||||
|
@ -32,6 +32,18 @@ func (payload *edgeGroupCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id EdgeGroupCreate
|
||||
// @summary Create an EdgeGroup
|
||||
// @description
|
||||
// @tags edge_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body edgeGroupCreatePayload true "EdgeGroup data"
|
||||
// @success 200 {object} portainer.EdgeGroup
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @failure 500
|
||||
// @router /edge_groups [post]
|
||||
func (handler *Handler) edgeGroupCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload edgeGroupCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -11,6 +11,18 @@ import (
|
|||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// @id EdgeGroupDelete
|
||||
// @summary Deletes an EdgeGroup
|
||||
// @description
|
||||
// @tags edge_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "EdgeGroup Id"
|
||||
// @success 204
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @failure 500
|
||||
// @router /edge_groups/{id} [delete]
|
||||
func (handler *Handler) edgeGroupDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,10 +6,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// @id EdgeGroupInspect
|
||||
// @summary Inspects an EdgeGroup
|
||||
// @description
|
||||
// @tags edge_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "EdgeGroup Id"
|
||||
// @success 200 {object} portainer.EdgeGroup
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @failure 500
|
||||
// @router /edge_groups/{id} [get]
|
||||
func (handler *Handler) edgeGroupInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type decoratedEdgeGroup struct {
|
||||
|
@ -13,6 +13,17 @@ type decoratedEdgeGroup struct {
|
|||
HasEdgeStack bool `json:"HasEdgeStack"`
|
||||
}
|
||||
|
||||
// @id EdgeGroupList
|
||||
// @summary list EdgeGroups
|
||||
// @description
|
||||
// @tags edge_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.EdgeGroup{HasEdgeStack=bool} "EdgeGroups"
|
||||
// @failure 500
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_groups [get]
|
||||
func (handler *Handler) edgeGroupList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeGroups, err := handler.DataStore.EdgeGroup().EdgeGroups()
|
||||
if err != nil {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
)
|
||||
|
@ -34,6 +34,19 @@ func (payload *edgeGroupUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id EgeGroupUpdate
|
||||
// @summary Updates an EdgeGroup
|
||||
// @description
|
||||
// @tags edge_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "EdgeGroup Id"
|
||||
// @param body body edgeGroupUpdatePayload true "EdgeGroup data"
|
||||
// @success 200 {object} portainer.EdgeGroup
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @failure 500
|
||||
// @router /edge_groups/{id} [put]
|
||||
func (handler *Handler) edgeGroupUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -11,10 +11,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
// POST /api/edge_jobs?method=file|string
|
||||
// @id EdgeJobCreate
|
||||
// @summary Create an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param method query string true "Creation Method" Enums(file, string)
|
||||
// @param body body edgeJobCreateFromFileContentPayload true "EdgeGroup data when method is string"
|
||||
// @param body body edgeJobCreateFromFilePayload true "EdgeGroup data when method is file"
|
||||
// @success 200 {object} portainer.EdgeGroup
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @failure 500
|
||||
// @router /edge_jobs [post]
|
||||
func (handler *Handler) edgeJobCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
|
|
|
@ -7,10 +7,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// @id EdgeJobDelete
|
||||
// @summary Delete an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @success 204
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id} [delete]
|
||||
func (handler *Handler) edgeJobDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -14,7 +14,19 @@ type edgeJobFileResponse struct {
|
|||
FileContent string `json:"FileContent"`
|
||||
}
|
||||
|
||||
// GET request on /api/edge_jobs/:id/file
|
||||
// @id EdgeJobFile
|
||||
// @summary Fetch a file of an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @success 200 {object} edgeJobFileResponse
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id}/file [get]
|
||||
func (handler *Handler) edgeJobFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -15,6 +15,19 @@ type edgeJobInspectResponse struct {
|
|||
Endpoints []portainer.EndpointID
|
||||
}
|
||||
|
||||
// @id EdgeJobInspect
|
||||
// @summary Inspect an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @success 200 {object} portainer.EdgeJob
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id} [get]
|
||||
func (handler *Handler) edgeJobInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,6 +7,18 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// @id EdgeJobList
|
||||
// @summary Fetch EdgeJobs list
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.EdgeJob
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs [get]
|
||||
// GET request on /api/edge_jobs
|
||||
func (handler *Handler) edgeJobList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobs, err := handler.DataStore.EdgeJob().EdgeJobs()
|
||||
|
|
|
@ -7,11 +7,24 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/edge_jobs/:id/tasks/:taskID/logs
|
||||
// @id EdgeJobTasksClear
|
||||
// @summary Clear the log for a specifc task on an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @param taskID path string true "Task Id"
|
||||
// @success 204
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id}/tasks/{taskID}/logs [delete]
|
||||
func (handler *Handler) edgeJobTasksClear(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,24 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// POST request on /api/edge_jobs/:id/tasks/:taskID/logs
|
||||
// @id EdgeJobTasksCollect
|
||||
// @summary Collect the log for a specifc task on an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @param taskID path string true "Task Id"
|
||||
// @success 204
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id}/tasks/{taskID}/logs [post]
|
||||
func (handler *Handler) edgeJobTasksCollect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -13,7 +13,20 @@ type fileResponse struct {
|
|||
FileContent string `json:"FileContent"`
|
||||
}
|
||||
|
||||
// GET request on /api/edge_jobs/:id/tasks/:taskID/logs
|
||||
// @id EdgeJobTaskLogsInspect
|
||||
// @summary Fetch the log for a specifc task on an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @param taskID path string true "Task Id"
|
||||
// @success 200 {object} fileResponse
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id}/tasks/{taskID}/logs [get]
|
||||
func (handler *Handler) edgeJobTaskLogsInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -17,7 +17,19 @@ type taskContainer struct {
|
|||
LogsStatus portainer.EdgeJobLogsStatus `json:"LogsStatus"`
|
||||
}
|
||||
|
||||
// GET request on /api/edge_jobs/:id/tasks
|
||||
// @id EdgeJobTasksList
|
||||
// @summary Fetch the list of tasks on an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @success 200 {array} taskContainer
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id}/tasks [get]
|
||||
func (handler *Handler) edgeJobTasksList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -28,6 +28,20 @@ func (payload *edgeJobUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id EdgeJobUpdate
|
||||
// @summary Update an EdgeJob
|
||||
// @description
|
||||
// @tags edge_jobs
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeJob Id"
|
||||
// @param body body edgeJobUpdatePayload true "EdgeGroup data"
|
||||
// @success 200 {object} portainer.EdgeJob
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_jobs/{id} [post]
|
||||
func (handler *Handler) edgeJobUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeJobID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -11,12 +11,26 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/filesystem"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
)
|
||||
|
||||
// POST request on /api/endpoint_groups
|
||||
// @id EdgeStackCreate
|
||||
// @summary Create an EdgeStack
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @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)
|
||||
if err != nil {
|
||||
|
@ -75,9 +89,12 @@ func (handler *Handler) createSwarmStack(method string, r *http.Request) (*porta
|
|||
}
|
||||
|
||||
type swarmStackFromFileContentPayload struct {
|
||||
Name string
|
||||
StackFileContent string
|
||||
EdgeGroups []portainer.EdgeGroupID
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
// Content of the Stack file
|
||||
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx" validate:"required"`
|
||||
// List of identifiers of EdgeGroups
|
||||
EdgeGroups []portainer.EdgeGroupID `example:"1"`
|
||||
}
|
||||
|
||||
func (payload *swarmStackFromFileContentPayload) Validate(r *http.Request) error {
|
||||
|
@ -132,14 +149,22 @@ func (handler *Handler) createSwarmStackFromFileContent(r *http.Request) (*porta
|
|||
}
|
||||
|
||||
type swarmStackFromGitRepositoryPayload struct {
|
||||
Name string
|
||||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
EdgeGroups []portainer.EdgeGroupID
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
// URL of a Git repository hosting the Stack file
|
||||
RepositoryURL string `example:"https://github.com/openfaas/faas" validate:"required"`
|
||||
// Reference name of a Git repository hosting the Stack file
|
||||
RepositoryReferenceName string `example:"refs/heads/master"`
|
||||
// Use basic authentication to clone the Git repository
|
||||
RepositoryAuthentication bool `example:"true"`
|
||||
// Username used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryUsername string `example:"myGitUsername"`
|
||||
// Password used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryPassword string `example:"myGitPassword"`
|
||||
// Path to the Stack file inside the Git repository
|
||||
ComposeFilePathInRepository string `example:"docker-compose.yml" default:"docker-compose.yml"`
|
||||
// List of identifiers of EdgeGroups
|
||||
EdgeGroups []portainer.EdgeGroupID `example:"1"`
|
||||
}
|
||||
|
||||
func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) error {
|
||||
|
|
|
@ -6,11 +6,24 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
)
|
||||
|
||||
// @id EdgeStackDelete
|
||||
// @summary Delete an EdgeStack
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeStack Id"
|
||||
// @success 204
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_stacks/{id} [delete]
|
||||
func (handler *Handler) edgeStackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeStackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,19 @@ type stackFileResponse struct {
|
|||
StackFileContent string `json:"StackFileContent"`
|
||||
}
|
||||
|
||||
// GET request on /api/edge_stacks/:id/file
|
||||
// @id EdgeStackFile
|
||||
// @summary Fetches the stack file for an EdgeStack
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeStack Id"
|
||||
// @success 200 {object} stackFileResponse
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_stacks/{id}/file [get]
|
||||
func (handler *Handler) edgeStackFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,10 +6,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// @id EdgeStackInspect
|
||||
// @summary Inspect an EdgeStack
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeStack Id"
|
||||
// @success 200 {object} portainer.EdgeStack
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_stacks/{id} [get]
|
||||
func (handler *Handler) edgeStackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeStackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,6 +7,18 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// @id EdgeStackList
|
||||
// @summary Fetches the list of EdgeStacks
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.EdgeStack
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_stacks [get]
|
||||
func (handler *Handler) edgeStackList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
edgeStacks, err := handler.DataStore.EdgeStack().EdgeStacks()
|
||||
if err != nil {
|
||||
|
|
|
@ -8,7 +8,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -31,6 +31,19 @@ func (payload *updateStatusPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id EdgeStackStatusUpdate
|
||||
// @summary Update an EdgeStack status
|
||||
// @description Authorized only if the request is done by an Edge Endpoint
|
||||
// @tags edge_stacks
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeStack Id"
|
||||
// @success 200 {object} portainer.EdgeStack
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 404
|
||||
// @failure 403
|
||||
// @router /edge_stacks/{id}/status [put]
|
||||
func (handler *Handler) edgeStackStatusUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -9,7 +9,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
)
|
||||
|
@ -31,6 +31,20 @@ func (payload *updateEdgeStackPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id EdgeStackUpdate
|
||||
// @summary Update an EdgeStack
|
||||
// @description
|
||||
// @tags edge_stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "EdgeStack Id"
|
||||
// @param body body updateEdgeStackPayload true "EdgeStack data"
|
||||
// @success 200 {object} portainer.EdgeStack
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 503 Edge compute features are disabled
|
||||
// @router /edge_stacks/{id} [put]
|
||||
func (handler *Handler) edgeStackUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/client"
|
||||
)
|
||||
|
||||
|
@ -15,7 +15,16 @@ type templateFileFormat struct {
|
|||
Templates []portainer.Template `json:"templates"`
|
||||
}
|
||||
|
||||
// GET request on /api/edgetemplates
|
||||
// @id EdgeTemplateList
|
||||
// @summary Fetches the list of Edge Templates
|
||||
// @description
|
||||
// @tags edge_templates
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.Template
|
||||
// @failure 500
|
||||
// @router /edge_templates [get]
|
||||
func (handler *Handler) edgeTemplateList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
settings, err := handler.DataStore.Settings().Settings()
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -19,7 +19,18 @@ func (payload *logsPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on api/endpoints/:id/edge/jobs/:jobID/logs
|
||||
// endpointEdgeJobsLogs
|
||||
// @summary Inspect an EdgeJob Log
|
||||
// @description
|
||||
// @tags edge, endpoints
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "Endpoint Id"
|
||||
// @param jobID path string true "Job Id"
|
||||
// @success 200
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @router /endpoints/{id}/edge/jobs/{jobID}/logs [post]
|
||||
func (handler *Handler) endpointEdgeJobsLogs(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -17,7 +17,18 @@ type configResponse struct {
|
|||
Name string
|
||||
}
|
||||
|
||||
// GET request on api/endpoints/:id/edge/stacks/:stackId
|
||||
// @summary Inspect an Edge Stack for an Endpoint
|
||||
// @description
|
||||
// @tags edge, endpoints, edge_stacks
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path string true "Endpoint Id"
|
||||
// @param stackID path string true "EdgeStack Id"
|
||||
// @success 200 {object} configResponse
|
||||
// @failure 500
|
||||
// @failure 400
|
||||
// @failure 404
|
||||
// @router /endpoints/{id}/edge/stacks/{stackId} [get]
|
||||
func (handler *Handler) endpointEdgeStackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,14 +8,18 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type endpointGroupCreatePayload struct {
|
||||
Name string
|
||||
Description string
|
||||
AssociatedEndpoints []portainer.EndpointID
|
||||
TagIDs []portainer.TagID
|
||||
// Endpoint group name
|
||||
Name string `validate:"required" example:"my-endpoint-group"`
|
||||
// Endpoint group description
|
||||
Description string `example:"description"`
|
||||
// List of endpoint identifiers that will be part of this group
|
||||
AssociatedEndpoints []portainer.EndpointID `example:"1,3"`
|
||||
// List of tag identifiers to which this endpoint group is associated
|
||||
TagIDs []portainer.TagID `example:"1,2"`
|
||||
}
|
||||
|
||||
func (payload *endpointGroupCreatePayload) Validate(r *http.Request) error {
|
||||
|
@ -28,7 +32,18 @@ func (payload *endpointGroupCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/endpoint_groups
|
||||
// @summary Create an Endpoint Group
|
||||
// @description Create a new endpoint group.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body endpointGroupCreatePayload true "Endpoint Group details"
|
||||
// @success 200 {object} portainer.EndpointGroup "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups [post]
|
||||
func (handler *Handler) endpointGroupCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload endpointGroupCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -7,11 +7,24 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/endpoint_groups/:id
|
||||
// @id EndpointGroupDelete
|
||||
// @summary Remove an endpoint group
|
||||
// @description Remove an endpoint group.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "EndpointGroup identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "EndpointGroup not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups/{id} [delete]
|
||||
func (handler *Handler) endpointGroupDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// PUT request on /api/endpoint_groups/:id/endpoints/:endpointId
|
||||
// @id EndpointGroupAddEndpoint
|
||||
// @summary Add an endpoint to an endpoint group
|
||||
// @description Add an endpoint to an endpoint group
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @param id path int true "EndpointGroup identifier"
|
||||
// @param endpointId path int true "Endpoint identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "EndpointGroup not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups/{id}/endpoints/{endpointId} [put]
|
||||
func (handler *Handler) endpointGroupAddEndpoint(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/endpoint_groups/:id/endpoints/:endpointId
|
||||
// @id EndpointGroupDeleteEndpoint
|
||||
// @summary Removes endpoint from an endpoint group
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @param id path int true "EndpointGroup identifier"
|
||||
// @param endpointId path int true "Endpoint identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "EndpointGroup not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups/{id}/endpoints/{endpointId} [delete]
|
||||
func (handler *Handler) endpointGroupDeleteEndpoint(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// GET request on /api/endpoint_groups/:id
|
||||
// @summary Inspect an Endpoint group
|
||||
// @description Retrieve details abont an endpoint group.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Endpoint group identifier"
|
||||
// @success 200 {object} portainer.EndpointGroup "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "EndpointGroup not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups/:id [get]
|
||||
func (handler *Handler) endpointGroupInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,7 +8,18 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/endpoint_groups
|
||||
// @id EndpointGroupList
|
||||
// @summary List Endpoint groups
|
||||
// @description List all endpoint groups based on the current user authorizations. Will
|
||||
// @description return all endpoint groups if using an administrator account otherwise it will
|
||||
// @description only return authorized endpoint groups.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.EndpointGroup "Endpoint group"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups [get]
|
||||
func (handler *Handler) endpointGroupList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroups, err := handler.DataStore.EndpointGroup().EndpointGroups()
|
||||
if err != nil {
|
||||
|
|
|
@ -7,15 +7,18 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/tag"
|
||||
)
|
||||
|
||||
type endpointGroupUpdatePayload struct {
|
||||
Name string
|
||||
Description string
|
||||
TagIDs []portainer.TagID
|
||||
// Endpoint group name
|
||||
Name string `example:"my-endpoint-group"`
|
||||
// Endpoint group description
|
||||
Description string `example:"description"`
|
||||
// List of tag identifiers associated to the endpoint group
|
||||
TagIDs []portainer.TagID `example:"3,4"`
|
||||
UserAccessPolicies portainer.UserAccessPolicies
|
||||
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||
}
|
||||
|
@ -24,7 +27,21 @@ func (payload *endpointGroupUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/endpoint_groups/:id
|
||||
// @id EndpointGroupUpdate
|
||||
// @summary Update an endpoint group
|
||||
// @description Update an endpoint group.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoint_groups
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "EndpointGroup identifier"
|
||||
// @param body body endpointGroupUpdatePayload true "EndpointGroup details"
|
||||
// @success 200 {object} portainer.EndpointGroup "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "EndpointGroup not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoint_groups/:id [put]
|
||||
func (handler *Handler) endpointGroupUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointGroupID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -147,7 +147,34 @@ func (payload *endpointCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/endpoints
|
||||
// @id EndpointCreate
|
||||
// @summary Create a new endpoint
|
||||
// @description Create a new endpoint that will be used to manage an environment.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @accept multipart/form-data
|
||||
// @produce json
|
||||
// @param Name formData string true "Name that will be used to identify this endpoint (example: my-endpoint)"
|
||||
// @param EndpointType formData integer true "Environment type. Value must be one of: 1 (Local Docker environment), 2 (Agent environment), 3 (Azure environment), 4 (Edge agent environment) or 5 (Local Kubernetes Environment" Enum(1,2,3,4,5)
|
||||
// @param URL formData string false "URL or IP address of a Docker host (example: docker.mydomain.tld:2375). Defaults to local if not specified (Linux: /var/run/docker.sock, Windows: //./pipe/docker_engine)"
|
||||
// @param PublicURL formData string false "URL or IP address where exposed containers will be reachable. Defaults to URL if not specified (example: docker.mydomain.tld:2375)"
|
||||
// @param GroupID formData int false "Endpoint group identifier. If not specified will default to 1 (unassigned)."
|
||||
// @param TLS formData bool false "Require TLS to connect against this endpoint"
|
||||
// @param TLSSkipVerify formData bool false "Skip server verification when using TLS"
|
||||
// @param TLSSkipClientVerify formData bool false "Skip client verification when using TLS"
|
||||
// @param TLSCACertFile formData file false "TLS CA certificate file"
|
||||
// @param TLSCertFile formData file false "TLS client certificate file"
|
||||
// @param TLSKeyFile formData file false "TLS client key file"
|
||||
// @param AzureApplicationID formData string false "Azure application ID. Required if endpoint type is set to 3"
|
||||
// @param AzureTenantID formData string false "Azure tenant ID. Required if endpoint type is set to 3"
|
||||
// @param AzureAuthenticationKey formData string false "Azure authentication key. Required if endpoint type is set to 3"
|
||||
// @param TagIDs formData []int false "List of tag identifiers to which this endpoint is associated"
|
||||
// @param EdgeCheckinInterval formData int false "The check in interval for edge agent (in seconds)"
|
||||
// @success 200 {object} portainer.Endpoint "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints [post]
|
||||
func (handler *Handler) endpointCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
payload := &endpointCreatePayload{}
|
||||
err := payload.Validate(r)
|
||||
|
|
|
@ -7,11 +7,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/endpoints/:id
|
||||
// @id EndpointDelete
|
||||
// @summary Remove an endpoint
|
||||
// @description Remove an endpoint.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints/{id} [delete]
|
||||
func (handler *Handler) endpointDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -10,7 +10,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
|
@ -29,7 +29,6 @@ func (payload *endpointExtensionAddPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/endpoints/:id/extensions
|
||||
func (handler *Handler) endpointExtensionAdd(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,11 +8,10 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/endpoints/:id/extensions/:extensionType
|
||||
func (handler *Handler) endpointExtensionRemove(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -10,7 +10,19 @@ import (
|
|||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// GET request on /api/endpoints/:id
|
||||
// @id EndpointInspect
|
||||
// @summary Inspect an endpoint
|
||||
// @description Retrieve details about an endpoint.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @success 200 {object} portainer.Endpoint "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints/{id} [get]
|
||||
func (handler *Handler) endpointInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -13,7 +13,26 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/endpoints?(start=<start>)&(limit=<limit>)&(search=<search>)&(groupId=<groupId)
|
||||
// @id EndpointList
|
||||
// @summary List endpoints
|
||||
// @description List all endpoints based on the current user authorizations. Will
|
||||
// @description return all endpoints if using an administrator account otherwise it will
|
||||
// @description only return authorized endpoints.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param start query int false "Start searching from"
|
||||
// @param search query string false "Search query"
|
||||
// @param groupId query int false "List endpoints of this group"
|
||||
// @param limit query int false "Limit results to this value"
|
||||
// @param type query int false "List endpoints of this type"
|
||||
// @param tagIds query []int false "search endpoints with these tags (depends on tagsPartialMatch)"
|
||||
// @param tagsPartialMatch query bool false "If true, will return endpoint which has one of tagIds, if false (or missing) will return only endpoints that has all the tags"
|
||||
// @param endpointIds query []int false "will return only these endpoints"
|
||||
// @success 200 {array} portainer.Endpoint "Endpoints"
|
||||
// @failure 500 Server error
|
||||
// @router /endpoints [get]
|
||||
func (handler *Handler) endpointList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
start, _ := request.RetrieveNumericQueryParameter(r, "start", true)
|
||||
if start != 0 {
|
||||
|
|
|
@ -11,21 +11,43 @@ import (
|
|||
)
|
||||
|
||||
type endpointSettingsUpdatePayload struct {
|
||||
AllowBindMountsForRegularUsers *bool `json:"allowBindMountsForRegularUsers"`
|
||||
AllowPrivilegedModeForRegularUsers *bool `json:"allowPrivilegedModeForRegularUsers"`
|
||||
AllowVolumeBrowserForRegularUsers *bool `json:"allowVolumeBrowserForRegularUsers"`
|
||||
AllowHostNamespaceForRegularUsers *bool `json:"allowHostNamespaceForRegularUsers"`
|
||||
AllowDeviceMappingForRegularUsers *bool `json:"allowDeviceMappingForRegularUsers"`
|
||||
AllowStackManagementForRegularUsers *bool `json:"allowStackManagementForRegularUsers"`
|
||||
AllowContainerCapabilitiesForRegularUsers *bool `json:"allowContainerCapabilitiesForRegularUsers"`
|
||||
EnableHostManagementFeatures *bool `json:"enableHostManagementFeatures"`
|
||||
// Whether non-administrator should be able to use bind mounts when creating containers
|
||||
AllowBindMountsForRegularUsers *bool `json:"allowBindMountsForRegularUsers" example:"false"`
|
||||
// Whether non-administrator should be able to use privileged mode when creating containers
|
||||
AllowPrivilegedModeForRegularUsers *bool `json:"allowPrivilegedModeForRegularUsers" example:"false"`
|
||||
// Whether non-administrator should be able to browse volumes
|
||||
AllowVolumeBrowserForRegularUsers *bool `json:"allowVolumeBrowserForRegularUsers" example:"true"`
|
||||
// Whether non-administrator should be able to use the host pid
|
||||
AllowHostNamespaceForRegularUsers *bool `json:"allowHostNamespaceForRegularUsers" example:"true"`
|
||||
// Whether non-administrator should be able to use device mapping
|
||||
AllowDeviceMappingForRegularUsers *bool `json:"allowDeviceMappingForRegularUsers" example:"true"`
|
||||
// Whether non-administrator should be able to manage stacks
|
||||
AllowStackManagementForRegularUsers *bool `json:"allowStackManagementForRegularUsers" example:"true"`
|
||||
// Whether non-administrator should be able to use container capabilities
|
||||
AllowContainerCapabilitiesForRegularUsers *bool `json:"allowContainerCapabilitiesForRegularUsers" example:"true"`
|
||||
// Whether host management features are enabled
|
||||
EnableHostManagementFeatures *bool `json:"enableHostManagementFeatures" example:"true"`
|
||||
}
|
||||
|
||||
func (payload *endpointSettingsUpdatePayload) Validate(r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/endpoints/:id/settings
|
||||
// @id EndpointSettingsUpdate
|
||||
// @summary Update settings for an endpoint
|
||||
// @description Update settings for an endpoint.
|
||||
// @description **Access policy**: administrator
|
||||
// @security jwt
|
||||
// @tags endpoints
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @param body body endpointSettingsUpdatePayload true "Endpoint details"
|
||||
// @success 200 {object} portainer.Endpoint "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /api/endpoints/:id/settings [put]
|
||||
func (handler *Handler) endpointSettingsUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,12 +6,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/snapshot"
|
||||
)
|
||||
|
||||
// POST request on /api/endpoints/:id/snapshot
|
||||
// @id EndpointSnapshot
|
||||
// @summary Snapshots an endpoint
|
||||
// @description Snapshots an endpoint
|
||||
// @description **Access policy**: restricted
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints/{id}/snapshot [post]
|
||||
func (handler *Handler) endpointSnapshot(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,19 @@ import (
|
|||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/internal/snapshot"
|
||||
)
|
||||
|
||||
// POST request on /api/endpoints/snapshot
|
||||
// @id EndpointSnapshots
|
||||
// @summary Snapshot all endpoints
|
||||
// @description Snapshot all endpoints
|
||||
// @description **Access policy**: administrator
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @success 204 "Success"
|
||||
// @failure 500 "Server Error"
|
||||
// @router /endpoints/snapshot [post]
|
||||
func (handler *Handler) endpointSnapshots(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpoints, err := handler.DataStore.Endpoint().Endpoints()
|
||||
if err != nil {
|
||||
|
|
|
@ -9,33 +9,58 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
type stackStatusResponse struct {
|
||||
ID portainer.EdgeStackID
|
||||
Version int
|
||||
// EdgeStack Identifier
|
||||
ID portainer.EdgeStackID `example:"1"`
|
||||
// Version of this stack
|
||||
Version int `example:"3"`
|
||||
}
|
||||
|
||||
type edgeJobResponse struct {
|
||||
ID portainer.EdgeJobID `json:"Id"`
|
||||
CollectLogs bool `json:"CollectLogs"`
|
||||
CronExpression string `json:"CronExpression"`
|
||||
Script string `json:"Script"`
|
||||
Version int `json:"Version"`
|
||||
// EdgeJob Identifier
|
||||
ID portainer.EdgeJobID `json:"Id" example:"2"`
|
||||
// Whether to collect logs
|
||||
CollectLogs bool `json:"CollectLogs" example:"true"`
|
||||
// A cron expression to schedule this job
|
||||
CronExpression string `json:"CronExpression" example:"* * * * *"`
|
||||
// Script to run
|
||||
Script string `json:"Script" example:"echo hello"`
|
||||
// Version of this EdgeJob
|
||||
Version int `json:"Version" example:"2"`
|
||||
}
|
||||
|
||||
type endpointStatusInspectResponse struct {
|
||||
Status string `json:"status"`
|
||||
Port int `json:"port"`
|
||||
Schedules []edgeJobResponse `json:"schedules"`
|
||||
CheckinInterval int `json:"checkin"`
|
||||
Credentials string `json:"credentials"`
|
||||
Stacks []stackStatusResponse `json:"stacks"`
|
||||
// Status represents the endpoint status
|
||||
Status string `json:"status" example:"REQUIRED"`
|
||||
// The tunnel port
|
||||
Port int `json:"port" example:"8732"`
|
||||
// List of requests for jobs to run on the endpoint
|
||||
Schedules []edgeJobResponse `json:"schedules"`
|
||||
// The current value of CheckinInterval
|
||||
CheckinInterval int `json:"checkin" example:"5"`
|
||||
//
|
||||
Credentials string `json:"credentials" example:""`
|
||||
// List of stacks to be deployed on the endpoints
|
||||
Stacks []stackStatusResponse `json:"stacks"`
|
||||
}
|
||||
|
||||
// GET request on /api/endpoints/:id/status
|
||||
// @id EndpointStatusInspect
|
||||
// @summary Get endpoint status
|
||||
// @description Endpoint for edge agent to check status of environment
|
||||
// @description **Access policy**: restricted only to Edge endpoints
|
||||
// @tags endpoints
|
||||
// @security jwt
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @success 200 {object} endpointStatusInspectResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied to access endpoint"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints/{id}/status [get]
|
||||
func (handler *Handler) endpointStatusInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -16,29 +16,58 @@ import (
|
|||
)
|
||||
|
||||
type endpointUpdatePayload struct {
|
||||
Name *string
|
||||
URL *string
|
||||
PublicURL *string
|
||||
GroupID *int
|
||||
TLS *bool
|
||||
TLSSkipVerify *bool
|
||||
TLSSkipClientVerify *bool
|
||||
Status *int
|
||||
AzureApplicationID *string
|
||||
AzureTenantID *string
|
||||
AzureAuthenticationKey *string
|
||||
TagIDs []portainer.TagID
|
||||
UserAccessPolicies portainer.UserAccessPolicies
|
||||
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||
EdgeCheckinInterval *int
|
||||
Kubernetes *portainer.KubernetesData
|
||||
// Name that will be used to identify this endpoint
|
||||
Name *string `example:"my-endpoint"`
|
||||
// URL or IP address of a Docker host
|
||||
URL *string `example:"docker.mydomain.tld:2375"`
|
||||
// URL or IP address where exposed containers will be reachable.\
|
||||
// Defaults to URL if not specified
|
||||
PublicURL *string `example:"docker.mydomain.tld:2375"`
|
||||
// Group identifier
|
||||
GroupID *int `example:"1"`
|
||||
// Require TLS to connect against this endpoint
|
||||
TLS *bool `example:"true"`
|
||||
// Skip server verification when using TLS
|
||||
TLSSkipVerify *bool `example:"false"`
|
||||
// Skip client verification when using TLS
|
||||
TLSSkipClientVerify *bool `example:"false"`
|
||||
// The status of the endpoint (1 - up, 2 - down)
|
||||
Status *int `example:"1"`
|
||||
// Azure application ID
|
||||
AzureApplicationID *string `example:"eag7cdo9-o09l-9i83-9dO9-f0b23oe78db4"`
|
||||
// Azure tenant ID
|
||||
AzureTenantID *string `example:"34ddc78d-4fel-2358-8cc1-df84c8o839f5"`
|
||||
// Azure authentication key
|
||||
AzureAuthenticationKey *string `example:"cOrXoK/1D35w8YQ8nH1/8ZGwzz45JIYD5jxHKXEQknk="`
|
||||
// List of tag identifiers to which this endpoint is associated
|
||||
TagIDs []portainer.TagID `example:"1,2"`
|
||||
UserAccessPolicies portainer.UserAccessPolicies
|
||||
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||
// The check in interval for edge agent (in seconds)
|
||||
EdgeCheckinInterval *int `example:"5"`
|
||||
// Associated Kubernetes data
|
||||
Kubernetes *portainer.KubernetesData
|
||||
}
|
||||
|
||||
func (payload *endpointUpdatePayload) Validate(r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/endpoints/:id
|
||||
// @id EndpointUpdate
|
||||
// @summary Update an endpoint
|
||||
// @description Update an endpoint.
|
||||
// @description **Access policy**: administrator
|
||||
// @security jwt
|
||||
// @tags endpoints
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Endpoint identifier"
|
||||
// @param body body endpointUpdatePayload true "Endpoint details"
|
||||
// @success 200 {object} portainer.Endpoint "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Endpoint not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /endpoints/{id} [put]
|
||||
func (handler *Handler) endpointUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -64,6 +64,77 @@ type Handler struct {
|
|||
WebhookHandler *webhooks.Handler
|
||||
}
|
||||
|
||||
// @title PortainerCE API
|
||||
// @version 2.1.1
|
||||
// @description.markdown api-description.md
|
||||
// @termsOfService
|
||||
|
||||
// @contact.email info@portainer.io
|
||||
|
||||
// @license.name
|
||||
// @license.url
|
||||
|
||||
// @host
|
||||
// @BasePath /api
|
||||
// @schemes http https
|
||||
|
||||
// @securitydefinitions.apikey jwt
|
||||
// @in header
|
||||
// @name Authorization
|
||||
|
||||
// @tag.name auth
|
||||
// @tag.description Authenticate against Portainer HTTP API
|
||||
// @tag.name custom_templates
|
||||
// @tag.description Manage Custom Templates
|
||||
// @tag.name dockerhub
|
||||
// @tag.description Manage how Portainer connects to the DockerHub
|
||||
// @tag.name edge_groups
|
||||
// @tag.description Manage Edge Groups
|
||||
// @tag.name edge_jobs
|
||||
// @tag.description Manage Edge Jobs
|
||||
// @tag.name edge_stacks
|
||||
// @tag.description Manage Edge Stacks
|
||||
// @tag.name edge_templates
|
||||
// @tag.description Manage Edge Templates
|
||||
// @tag.name edge
|
||||
// @tag.description Manage Edge related endpoint settings
|
||||
// @tag.name endpoints
|
||||
// @tag.description Manage Docker environments
|
||||
// @tag.name endpoint_groups
|
||||
// @tag.description Manage endpoint groups
|
||||
// @tag.name motd
|
||||
// @tag.description Fetch the message of the day
|
||||
// @tag.name registries
|
||||
// @tag.description Manage Docker registries
|
||||
// @tag.name resource_controls
|
||||
// @tag.description Manage access control on Docker resources
|
||||
// @tag.name roles
|
||||
// @tag.description Manage roles
|
||||
// @tag.name settings
|
||||
// @tag.description Manage Portainer settings
|
||||
// @tag.name status
|
||||
// @tag.description Information about the Portainer instance
|
||||
// @tag.name stacks
|
||||
// @tag.description Manage Docker stacks
|
||||
// @tag.name users
|
||||
// @tag.description Manage users
|
||||
// @tag.name tags
|
||||
// @tag.description Manage tags
|
||||
// @tag.name teams
|
||||
// @tag.description Manage teams
|
||||
// @tag.name team_memberships
|
||||
// @tag.description Manage team memberships
|
||||
// @tag.name templates
|
||||
// @tag.description Manage App Templates
|
||||
// @tag.name stacks
|
||||
// @tag.description Manage stacks
|
||||
// @tag.name upload
|
||||
// @tag.description Upload files
|
||||
// @tag.name webhooks
|
||||
// @tag.description Manage webhooks
|
||||
// @tag.name websocket
|
||||
// @tag.description Create exec sessions using websockets
|
||||
|
||||
// ServeHTTP delegates a request to the appropriate subhandler.
|
||||
func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
switch {
|
||||
|
|
|
@ -7,7 +7,7 @@ import (
|
|||
|
||||
"github.com/portainer/libcrypto"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/client"
|
||||
)
|
||||
|
||||
|
@ -26,6 +26,12 @@ type motdData struct {
|
|||
Style string `json:"style"`
|
||||
}
|
||||
|
||||
// @summary fetches the message of the day
|
||||
// @tags motd
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {object} motdResponse
|
||||
// @router /motd [get]
|
||||
func (handler *Handler) motd(w http.ResponseWriter, r *http.Request) {
|
||||
motd, err := client.Get(portainer.MessageOfTheDayURL, 0)
|
||||
if err != nil {
|
||||
|
|
|
@ -8,19 +8,28 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
type registryConfigurePayload struct {
|
||||
Authentication bool
|
||||
Username string
|
||||
Password string
|
||||
TLS bool
|
||||
TLSSkipVerify bool
|
||||
TLSCertFile []byte
|
||||
TLSKeyFile []byte
|
||||
TLSCACertFile []byte
|
||||
// Is authentication against this registry enabled
|
||||
Authentication bool `example:"false" validate:"required"`
|
||||
// Username used to authenticate against this registry. Required when Authentication is true
|
||||
Username string `example:"registry_user"`
|
||||
// Password used to authenticate against this registry. required when Authentication is true
|
||||
Password string `example:"registry_password"`
|
||||
|
||||
// Use TLS
|
||||
TLS bool `example:"true"`
|
||||
// Skip the verification of the server TLS certificate
|
||||
TLSSkipVerify bool `example:"false"`
|
||||
// The TLS CA certificate file
|
||||
TLSCACertFile []byte
|
||||
// The TLS client certificate file
|
||||
TLSCertFile []byte
|
||||
// The TLS client key file
|
||||
TLSKeyFile []byte
|
||||
}
|
||||
|
||||
func (payload *registryConfigurePayload) Validate(r *http.Request) error {
|
||||
|
@ -67,7 +76,22 @@ func (payload *registryConfigurePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/registries/:id/configure
|
||||
// @id RegistryConfigure
|
||||
// @summary Configures a registry
|
||||
// @description Configures a registry.
|
||||
// @description **Access policy**: admin
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Registry identifier"
|
||||
// @param body body registryConfigurePayload true "Registry configuration"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Registry not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries/{id}/configure [post]
|
||||
func (handler *Handler) registryConfigure(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
registryID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,17 +8,24 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type registryCreatePayload struct {
|
||||
Name string
|
||||
Type portainer.RegistryType
|
||||
URL string
|
||||
Authentication bool
|
||||
Username string
|
||||
Password string
|
||||
Gitlab portainer.GitlabRegistryData
|
||||
// Name that will be used to identify this registry
|
||||
Name string `example:"my-registry" validate:"required"`
|
||||
// Registry Type. Valid values are: 1 (Quay.io), 2 (Azure container registry), 3 (custom registry) or 4 (Gitlab registry)
|
||||
Type portainer.RegistryType `example:"1" validate:"required" enums:"1,2,3,4"`
|
||||
// URL or IP address of the Docker registry
|
||||
URL string `example:"registry.mydomain.tld:2375" validate:"required"`
|
||||
// Is authentication against this registry enabled
|
||||
Authentication bool `example:"false" validate:"required"`
|
||||
// Username used to authenticate against this registry. Required when Authentication is true
|
||||
Username string `example:"registry_user"`
|
||||
// Password used to authenticate against this registry. required when Authentication is true
|
||||
Password string `example:"registry_password"`
|
||||
// Gitlab specific details, required when type = 4
|
||||
Gitlab portainer.GitlabRegistryData
|
||||
}
|
||||
|
||||
func (payload *registryCreatePayload) Validate(r *http.Request) error {
|
||||
|
@ -37,6 +44,19 @@ func (payload *registryCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id RegistryCreate
|
||||
// @summary Create a new registry
|
||||
// @description Create a new registry.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body registryCreatePayload true "Registry details"
|
||||
// @success 200 {object} portainer.Registry "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries [post]
|
||||
func (handler *Handler) registryCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload registryCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -6,11 +6,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/registries/:id
|
||||
// @id RegistryDelete
|
||||
// @summary Remove a registry
|
||||
// @description Remove a registry
|
||||
// @description **Access policy**: administrator
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @param id path int true "Registry identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Registry not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries/{id} [delete]
|
||||
func (handler *Handler) registryDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
registryID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -3,16 +3,29 @@ package registries
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
// GET request on /api/registries/:id
|
||||
// @id RegistryInspect
|
||||
// @summary Inspect a registry
|
||||
// @description Retrieve details about a registry.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Registry identifier"
|
||||
// @success 200 {object} portainer.Registry "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied to access registry"
|
||||
// @failure 404 "Registry not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries/{id} [get]
|
||||
func (handler *Handler) registryInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
registryID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,7 +8,18 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/registries
|
||||
// @id RegistryList
|
||||
// @summary List Registries
|
||||
// @description List all registries based on the current user authorizations.
|
||||
// @description Will return all registries if using an administrator account otherwise it
|
||||
// @description will only return authorized registries.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.Registry "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries [get]
|
||||
func (handler *Handler) registryList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
registries, err := handler.DataStore.Registry().Registries()
|
||||
if err != nil {
|
||||
|
|
|
@ -12,11 +12,16 @@ import (
|
|||
)
|
||||
|
||||
type registryUpdatePayload struct {
|
||||
Name *string
|
||||
URL *string
|
||||
Authentication *bool
|
||||
Username *string
|
||||
Password *string
|
||||
// Name that will be used to identify this registry
|
||||
Name *string `validate:"required" example:"my-registry"`
|
||||
// URL or IP address of the Docker registry
|
||||
URL *string `validate:"required" example:"registry.mydomain.tld:2375"`
|
||||
// Is authentication against this registry enabled
|
||||
Authentication *bool `example:"false" validate:"required"`
|
||||
// Username used to authenticate against this registry. Required when Authentication is true
|
||||
Username *string `example:"registry_user"`
|
||||
// Password used to authenticate against this registry. required when Authentication is true
|
||||
Password *string `example:"registry_password"`
|
||||
UserAccessPolicies portainer.UserAccessPolicies
|
||||
TeamAccessPolicies portainer.TeamAccessPolicies
|
||||
}
|
||||
|
@ -25,7 +30,22 @@ func (payload *registryUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/registries/:id
|
||||
// @id RegistryUpdate
|
||||
// @summary Update a registry
|
||||
// @description Update a registry
|
||||
// @description **Access policy**: administrator
|
||||
// @tags registries
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Registry identifier"
|
||||
// @param body body registryUpdatePayload true "Registry details"
|
||||
// @success 200 {object} portainer.Registry "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Registry not found"
|
||||
// @failure 409 "Another registry with the same URL already exists"
|
||||
// @failure 500 "Server error"
|
||||
// @router /registries/{id} [put]
|
||||
func (handler *Handler) registryUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
registryID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,17 +8,25 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type resourceControlCreatePayload struct {
|
||||
ResourceID string
|
||||
Type string
|
||||
Public bool
|
||||
AdministratorsOnly bool
|
||||
Users []int
|
||||
Teams []int
|
||||
SubResourceIDs []string
|
||||
//
|
||||
ResourceID string `example:"617c5f22bb9b023d6daab7cba43a57576f83492867bc767d1c59416b065e5f08" validate:"required"`
|
||||
// Type of Docker resource. Valid values are: container, volume\
|
||||
// service, secret, config or stack
|
||||
Type string `example:"container" validate:"required"`
|
||||
// Permit access to the associated resource to any user
|
||||
Public bool `example:"true"`
|
||||
// Permit access to resource only to admins
|
||||
AdministratorsOnly bool `example:"true"`
|
||||
// List of user identifiers with access to the associated resource
|
||||
Users []int `example:"1,4"`
|
||||
// List of team identifiers with access to the associated resource
|
||||
Teams []int `example:"56,7"`
|
||||
// List of Docker resources that will inherit this access control
|
||||
SubResourceIDs []string `example:"617c5f22bb9b023d6daab7cba43a57576f83492867bc767d1c59416b065e5f08"`
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -45,7 +53,20 @@ func (payload *resourceControlCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/resource_controls
|
||||
// @id ResourceControlCreate
|
||||
// @summary Create a new resource control
|
||||
// @description Create a new resource control to restrict access to a Docker resource.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags resource_controls
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body resourceControlCreatePayload true "Resource control details"
|
||||
// @success 200 {object} portainer.ResourceControl "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 409 "Resource control already exists"
|
||||
// @failure 500 "Server error"
|
||||
// @router /resource_controls [post]
|
||||
func (handler *Handler) resourceControlCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload resourceControlCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -6,11 +6,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/resource_controls/:id
|
||||
// @id ResourceControlDelete
|
||||
// @summary Remove a resource control
|
||||
// @description Remove a resource control.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags resource_controls
|
||||
// @security jwt
|
||||
// @param id path int true "Resource control identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 404 "Resource control not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /resource_controls/{id} [delete]
|
||||
func (handler *Handler) resourceControlDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
resourceControlID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,17 +7,21 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
type resourceControlUpdatePayload struct {
|
||||
Public bool
|
||||
Users []int
|
||||
Teams []int
|
||||
AdministratorsOnly bool
|
||||
// Permit access to the associated resource to any user
|
||||
Public bool `example:"true"`
|
||||
// List of user identifiers with access to the associated resource
|
||||
Users []int `example:"4"`
|
||||
// List of team identifiers with access to the associated resource
|
||||
Teams []int `example:"7"`
|
||||
// Permit access to resource only to admins
|
||||
AdministratorsOnly bool `example:"true"`
|
||||
}
|
||||
|
||||
func (payload *resourceControlUpdatePayload) Validate(r *http.Request) error {
|
||||
|
@ -31,7 +35,22 @@ func (payload *resourceControlUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/resource_controls/:id
|
||||
// @id ResourceControlUpdate
|
||||
// @summary Update a resource control
|
||||
// @description Update a resource control
|
||||
// @description **Access policy**: restricted
|
||||
// @tags resource_controls
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Resource control identifier"
|
||||
// @param body body resourceControlUpdatePayload true "Resource control details"
|
||||
// @success 200 {object} portainer.ResourceControl "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Unauthorized"
|
||||
// @failure 404 "Resource control not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /resource_controls/{id} [put]
|
||||
func (handler *Handler) resourceControlUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
resourceControlID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,16 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// GET request on /api/Role
|
||||
// @id RoleList
|
||||
// @summary List roles
|
||||
// @description List all roles available for use
|
||||
// @description **Access policy**: administrator
|
||||
// @tags roles
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.Role "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /roles [get]
|
||||
func (handler *Handler) roleList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
roles, err := handler.DataStore.Role().Roles()
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,16 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// GET request on /api/settings
|
||||
// @id SettingsInspect
|
||||
// @summary Retrieve Portainer settings
|
||||
// @description Retrieve Portainer settings.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags settings
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {object} portainer.Settings "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /settings [get]
|
||||
func (handler *Handler) settingsInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
settings, err := handler.DataStore.Settings().Settings()
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/filesystem"
|
||||
)
|
||||
|
||||
|
@ -18,7 +18,18 @@ func (payload *settingsLDAPCheckPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /settings/ldap/check
|
||||
// @id SettingsLDAPCheck
|
||||
// @summary Test LDAP connectivity
|
||||
// @description Test LDAP connectivity using LDAP details
|
||||
// @description **Access policy**: administrator
|
||||
// @tags settings
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @param body body settingsLDAPCheckPayload true "details"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /settings/ldap/check [put]
|
||||
func (handler *Handler) settingsLDAPCheck(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload settingsLDAPCheckPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -10,14 +10,27 @@ import (
|
|||
)
|
||||
|
||||
type publicSettingsResponse struct {
|
||||
LogoURL string `json:"LogoURL"`
|
||||
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod"`
|
||||
EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures"`
|
||||
OAuthLoginURI string `json:"OAuthLoginURI"`
|
||||
EnableTelemetry bool `json:"EnableTelemetry"`
|
||||
// URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string
|
||||
LogoURL string `json:"LogoURL" example:"https://mycompany.mydomain.tld/logo.png"`
|
||||
// Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth
|
||||
AuthenticationMethod portainer.AuthenticationMethod `json:"AuthenticationMethod" example:"1"`
|
||||
// Whether edge compute features are enabled
|
||||
EnableEdgeComputeFeatures bool `json:"EnableEdgeComputeFeatures" example:"true"`
|
||||
// The URL used for oauth login
|
||||
OAuthLoginURI string `json:"OAuthLoginURI" example:"https://gitlab.com/oauth"`
|
||||
// Whether telemetry is enabled
|
||||
EnableTelemetry bool `json:"EnableTelemetry" example:"true"`
|
||||
}
|
||||
|
||||
// GET request on /api/settings/public
|
||||
// @id SettingsPublic
|
||||
// @summary Retrieve Portainer public settings
|
||||
// @description Retrieve public settings. Returns a small set of settings that are not reserved to administrators only.
|
||||
// @description **Access policy**: public
|
||||
// @tags settings
|
||||
// @produce json
|
||||
// @success 200 {object} publicSettingsResponse "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /settings/public [get]
|
||||
func (handler *Handler) settingsPublic(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
settings, err := handler.DataStore.Settings().Settings()
|
||||
if err != nil {
|
||||
|
|
|
@ -14,17 +14,26 @@ import (
|
|||
)
|
||||
|
||||
type settingsUpdatePayload struct {
|
||||
LogoURL *string
|
||||
BlackListedLabels []portainer.Pair
|
||||
AuthenticationMethod *int
|
||||
LDAPSettings *portainer.LDAPSettings
|
||||
OAuthSettings *portainer.OAuthSettings
|
||||
SnapshotInterval *string
|
||||
TemplatesURL *string
|
||||
EdgeAgentCheckinInterval *int
|
||||
EnableEdgeComputeFeatures *bool
|
||||
UserSessionTimeout *string
|
||||
EnableTelemetry *bool
|
||||
// URL to a logo that will be displayed on the login page as well as on top of the sidebar. Will use default Portainer logo when value is empty string
|
||||
LogoURL *string `example:"https://mycompany.mydomain.tld/logo.png"`
|
||||
// A list of label name & value that will be used to hide containers when querying containers
|
||||
BlackListedLabels []portainer.Pair
|
||||
// Active authentication method for the Portainer instance. Valid values are: 1 for internal, 2 for LDAP, or 3 for oauth
|
||||
AuthenticationMethod *int `example:"1"`
|
||||
LDAPSettings *portainer.LDAPSettings `example:""`
|
||||
OAuthSettings *portainer.OAuthSettings `example:""`
|
||||
// The interval in which endpoint snapshots are created
|
||||
SnapshotInterval *string `example:"5m"`
|
||||
// URL to the templates that will be displayed in the UI when navigating to App Templates
|
||||
TemplatesURL *string `example:"https://raw.githubusercontent.com/portainer/templates/master/templates.json"`
|
||||
// The default check in interval for edge agent (in seconds)
|
||||
EdgeAgentCheckinInterval *int `example:"5"`
|
||||
// Whether edge compute features are enabled
|
||||
EnableEdgeComputeFeatures *bool `example:"true"`
|
||||
// The duration of a user session
|
||||
UserSessionTimeout *string `example:"5m"`
|
||||
// Whether telemetry is enabled
|
||||
EnableTelemetry *bool `example:"false"`
|
||||
}
|
||||
|
||||
func (payload *settingsUpdatePayload) Validate(r *http.Request) error {
|
||||
|
@ -47,7 +56,19 @@ func (payload *settingsUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/settings
|
||||
// @id SettingsUpdate
|
||||
// @summary Update Portainer settings
|
||||
// @description Update Portainer settings.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags settings
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body settingsUpdatePayload true "New settings"
|
||||
// @success 200 {object} portainer.Settings "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /settings [put]
|
||||
func (handler *Handler) settingsUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload settingsUpdatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -25,9 +25,12 @@ func normalizeStackName(name string) string {
|
|||
}
|
||||
|
||||
type composeStackFromFileContentPayload struct {
|
||||
Name string
|
||||
StackFileContent string
|
||||
Env []portainer.Pair
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
// Content of the Stack file
|
||||
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx" validate:"required"`
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair `example:""`
|
||||
}
|
||||
|
||||
func (payload *composeStackFromFileContentPayload) Validate(r *http.Request) error {
|
||||
|
@ -103,14 +106,24 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
}
|
||||
|
||||
type composeStackFromGitRepositoryPayload struct {
|
||||
Name string
|
||||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
Env []portainer.Pair
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
|
||||
// URL of a Git repository hosting the Stack file
|
||||
RepositoryURL string `example:"https://github.com/openfaas/faas" validate:"required"`
|
||||
// Reference name of a Git repository hosting the Stack file
|
||||
RepositoryReferenceName string `example:"refs/heads/master"`
|
||||
// Use basic authentication to clone the Git repository
|
||||
RepositoryAuthentication bool `example:"true"`
|
||||
// Username used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryUsername string `example:"myGitUsername"`
|
||||
// Password used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryPassword string `example:"myGitPassword"`
|
||||
// Path to the Stack file inside the Git repository
|
||||
ComposeFilePathInRepository string `example:"docker-compose.yml" default:"docker-compose.yml"`
|
||||
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair
|
||||
}
|
||||
|
||||
func (payload *composeStackFromGitRepositoryPayload) Validate(r *http.Request) error {
|
||||
|
|
|
@ -17,10 +17,14 @@ import (
|
|||
)
|
||||
|
||||
type swarmStackFromFileContentPayload struct {
|
||||
Name string
|
||||
SwarmID string
|
||||
StackFileContent string
|
||||
Env []portainer.Pair
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
// Swarm cluster identifier
|
||||
SwarmID string `example:"jpofkc0i9uo9wtx1zesuk649w" validate:"required"`
|
||||
// Content of the Stack file
|
||||
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx" validate:"required"`
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair
|
||||
}
|
||||
|
||||
func (payload *swarmStackFromFileContentPayload) Validate(r *http.Request) error {
|
||||
|
@ -99,15 +103,25 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
}
|
||||
|
||||
type swarmStackFromGitRepositoryPayload struct {
|
||||
Name string
|
||||
SwarmID string
|
||||
Env []portainer.Pair
|
||||
RepositoryURL string
|
||||
RepositoryReferenceName string
|
||||
RepositoryAuthentication bool
|
||||
RepositoryUsername string
|
||||
RepositoryPassword string
|
||||
ComposeFilePathInRepository string
|
||||
// Name of the stack
|
||||
Name string `example:"myStack" validate:"required"`
|
||||
// Swarm cluster identifier
|
||||
SwarmID string `example:"jpofkc0i9uo9wtx1zesuk649w" validate:"required"`
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair
|
||||
|
||||
// URL of a Git repository hosting the Stack file
|
||||
RepositoryURL string `example:"https://github.com/openfaas/faas" validate:"required"`
|
||||
// Reference name of a Git repository hosting the Stack file
|
||||
RepositoryReferenceName string `example:"refs/heads/master"`
|
||||
// Use basic authentication to clone the Git repository
|
||||
RepositoryAuthentication bool `example:"true"`
|
||||
// Username used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryUsername string `example:"myGitUsername"`
|
||||
// Password used in basic authentication. Required when RepositoryAuthentication is true.
|
||||
RepositoryPassword string `example:"myGitPassword"`
|
||||
// Path to the Stack file inside the Git repository
|
||||
ComposeFilePathInRepository string `example:"docker-compose.yml" default:"docker-compose.yml"`
|
||||
}
|
||||
|
||||
func (payload *swarmStackFromGitRepositoryPayload) Validate(r *http.Request) error {
|
||||
|
|
|
@ -29,7 +29,29 @@ func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/stacks?type=<type>&method=<method>&endpointId=<endpointId>
|
||||
// @id StackCreate
|
||||
// @summary Deploy a new stack
|
||||
// @description Deploy a new stack into a Docker environment specified via the endpoint identifier.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @accept json, multipart/form-data
|
||||
// @produce json
|
||||
// @param type query int true "Stack deployment type. Possible values: 1 (Swarm stack) or 2 (Compose stack)." Enums(1,2)
|
||||
// @param method query string true "Stack deployment method. Possible values: file, string or repository." Enums(string, file, repository)
|
||||
// @param endpointId query int true "Identifier of the endpoint that will be used to deploy the stack"
|
||||
// @param body_swarm_string body swarmStackFromFileContentPayload false "Required when using method=string and type=1"
|
||||
// @param body_swarm_repository body swarmStackFromGitRepositoryPayload false "Required when using method=repository and type=1"
|
||||
// @param body_compose_string body composeStackFromFileContentPayload false "Required when using method=string and type=2"
|
||||
// @param body_compose_repository body composeStackFromGitRepositoryPayload false "Required when using method=repository and type=2"
|
||||
// @param Name formData string false "Name of the stack. required when method is file"
|
||||
// @param SwarmID formData string false "Swarm cluster identifier. Required when method equals file and type equals 1. required when method is file"
|
||||
// @param Env formData string false "Environment variables passed during deployment, represented as a JSON array [{'name': 'name', 'value': 'value'}]. Optional, used when method equals file and type equals 1."
|
||||
// @param file formData file false "Stack file. required when method is file"
|
||||
// @success 200 {object} portainer.CustomTemplate
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks [post]
|
||||
func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackType, err := request.RetrieveNumericQueryParameter(r, "type", false)
|
||||
if err != nil {
|
||||
|
|
|
@ -14,9 +14,21 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// DELETE request on /api/stacks/:id?external=<external>&endpointId=<endpointId>
|
||||
// If the external query parameter is set to true, the id route variable is expected to be
|
||||
// the name of an external stack as a string.
|
||||
// @id StackDelete
|
||||
// @summary Remove a stack
|
||||
// @description Remove a stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @param id path int true "Stack identifier"
|
||||
// @param external query boolean false "Set to true to delete an external stack. Only external Swarm stacks are supported"
|
||||
// @param endpointId query int false "Endpoint identifier used to remove an external stack (required when external is set to true)"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 " not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id} [delete]
|
||||
func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,17 +7,31 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
type stackFileResponse struct {
|
||||
StackFileContent string `json:"StackFileContent"`
|
||||
// Content of the Stack file
|
||||
StackFileContent string `json:"StackFileContent" example:"version: 3\n services:\n web:\n image:nginx"`
|
||||
}
|
||||
|
||||
// GET request on /api/stacks/:id/file
|
||||
// @id StackFileInspect
|
||||
// @summary Retrieve the content of the Stack file for the specified stack
|
||||
// @description Get Stack file content.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Stack identifier"
|
||||
// @success 200 {object} stackFileResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Stack not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id}/file [get]
|
||||
func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,13 +6,26 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/stacks/:id
|
||||
// @id StackInspect
|
||||
// @summary Inspect a stack
|
||||
// @description Retrieve details about a stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Stack identifier"
|
||||
// @success 200 {object} portainer.Stack "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Stack not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id} [get]
|
||||
func (handler *Handler) stackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,7 +6,7 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
"github.com/portainer/portainer/api/internal/authorization"
|
||||
)
|
||||
|
@ -16,7 +16,20 @@ type stackListOperationFilters struct {
|
|||
EndpointID int `json:"EndpointID"`
|
||||
}
|
||||
|
||||
// GET request on /api/stacks?(filters=<filters>)
|
||||
// @id StackList
|
||||
// @summary List stacks
|
||||
// @description List all stacks based on the current user authorizations.
|
||||
// @description Will return all stacks if using an administrator account otherwise it
|
||||
// @description will only return the list of stacks the user have access to.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @param filters query string false "Filters to process on the stack list. Encoded as JSON (a map[string]string). For example, {"SwarmID": "jpofkc0i9uo9wtx1zesuk649w"} will only return stacks that are part of the specified Swarm cluster. Available filters: EndpointID, SwarmID."
|
||||
// @success 200 {array} portainer.Stack "Success"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks [get]
|
||||
func (handler *Handler) stackList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var filters stackListOperationFilters
|
||||
err := request.RetrieveJSONQueryParameter(r, "filters", &filters, true)
|
||||
|
|
|
@ -7,16 +7,19 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
type stackMigratePayload struct {
|
||||
EndpointID int
|
||||
SwarmID string
|
||||
Name string
|
||||
// Endpoint identifier of the target endpoint where the stack will be relocated
|
||||
EndpointID int `example:"2" validate:"required"`
|
||||
// Swarm cluster identifier, must match the identifier of the cluster where the stack will be relocated
|
||||
SwarmID string `example:"jpofkc0i9uo9wtx1zesuk649w"`
|
||||
// If provided will rename the migrated stack
|
||||
Name string `example:"new-stack"`
|
||||
}
|
||||
|
||||
func (payload *stackMigratePayload) Validate(r *http.Request) error {
|
||||
|
@ -26,7 +29,22 @@ func (payload *stackMigratePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/stacks/:id/migrate?endpointId=<endpointId>
|
||||
// @id StackMigrate
|
||||
// @summary Migrate a stack to another endpoint
|
||||
// @description Migrate a stack from an endpoint to another endpoint. It will re-create the stack inside the target endpoint before removing the original stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Stack identifier"
|
||||
// @param endpointId query int false "Stacks created before version 1.18.0 might not have an associated endpoint identifier. Use this optional parameter to set the endpoint identifier used by the stack."
|
||||
// @param body body stackMigratePayload true "Stack migration details"
|
||||
// @success 200 {object} portainer.Stack "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Stack not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id}/migrate [post]
|
||||
func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -14,7 +14,19 @@ import (
|
|||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// POST request on /api/stacks/:id/start
|
||||
// @id StackStart
|
||||
// @summary Starts a stopped Stack
|
||||
// @description Starts a stopped Stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @param id path int true "Stack identifier"
|
||||
// @success 200 {object} portainer.Stack "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 " not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id}/start [post]
|
||||
func (handler *Handler) stackStart(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,14 +7,25 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// POST request on /api/stacks/:id/stop
|
||||
// @id StackStop
|
||||
// @summary Stops a stopped Stack
|
||||
// @description Stops a stopped Stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @param id path int true "Stack identifier"
|
||||
// @success 200 {object} portainer.Stack "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 " not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id}/stop [post]
|
||||
func (handler *Handler) stackStop(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -17,8 +17,10 @@ import (
|
|||
)
|
||||
|
||||
type updateComposeStackPayload struct {
|
||||
StackFileContent string
|
||||
Env []portainer.Pair
|
||||
// New content of the Stack file
|
||||
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx"`
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair
|
||||
}
|
||||
|
||||
func (payload *updateComposeStackPayload) Validate(r *http.Request) error {
|
||||
|
@ -29,9 +31,12 @@ func (payload *updateComposeStackPayload) Validate(r *http.Request) error {
|
|||
}
|
||||
|
||||
type updateSwarmStackPayload struct {
|
||||
StackFileContent string
|
||||
Env []portainer.Pair
|
||||
Prune bool
|
||||
// New content of the Stack file
|
||||
StackFileContent string `example:"version: 3\n services:\n web:\n image:nginx"`
|
||||
// A list of environment variables used during stack deployment
|
||||
Env []portainer.Pair
|
||||
// Prune services that are no longer referenced (only available for Swarm stacks)
|
||||
Prune bool `example:"true"`
|
||||
}
|
||||
|
||||
func (payload *updateSwarmStackPayload) Validate(r *http.Request) error {
|
||||
|
@ -41,7 +46,23 @@ func (payload *updateSwarmStackPayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/stacks/:id?endpointId=<endpointId>
|
||||
// @id StackUpdate
|
||||
// @summary Update a stack
|
||||
// @description Update a stack.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags stacks
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Stack identifier"
|
||||
// @param endpointId query int false "Stacks created before version 1.18.0 might not have an associated endpoint identifier. Use this optional parameter to set the endpoint identifier used by the stack."
|
||||
// @param body body updateSwarmStackPayload true "Stack details"
|
||||
// @success 200 {object} portainer.Stack "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 " not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /stacks/{id} [put]
|
||||
func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,14 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// GET request on /api/status
|
||||
// @id StatusInspect
|
||||
// @summary Check Portainer status
|
||||
// @description Retrieve Portainer status
|
||||
// @description **Access policy**: public
|
||||
// @tags status
|
||||
// @produce json
|
||||
// @success 200 {object} portainer.Status "Success"
|
||||
// @router /status [get]
|
||||
func (handler *Handler) statusInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
return response.JSON(w, handler.Status)
|
||||
}
|
||||
|
|
|
@ -13,15 +13,25 @@ import (
|
|||
)
|
||||
|
||||
type inspectVersionResponse struct {
|
||||
UpdateAvailable bool `json:"UpdateAvailable"`
|
||||
LatestVersion string `json:"LatestVersion"`
|
||||
// Whether portainer has an update available
|
||||
UpdateAvailable bool `json:"UpdateAvailable" example:"false"`
|
||||
// The latest version available
|
||||
LatestVersion string `json:"LatestVersion" example:"2.0.0"`
|
||||
}
|
||||
|
||||
type githubData struct {
|
||||
TagName string `json:"tag_name"`
|
||||
}
|
||||
|
||||
// GET request on /api/status/version
|
||||
// @id StatusInspectVersion
|
||||
// @summary Check for portainer updates
|
||||
// @description Check if portainer has an update available
|
||||
// @description **Access policy**: authenticated
|
||||
// @security jwt
|
||||
// @tags status
|
||||
// @produce json
|
||||
// @success 200 {object} inspectVersionResponse "Success"
|
||||
// @router /status/version [get]
|
||||
func (handler *Handler) statusInspectVersion(w http.ResponseWriter, r *http.Request) {
|
||||
motd, err := client.Get(portainer.VersionCheckURL, 5)
|
||||
if err != nil {
|
||||
|
|
|
@ -8,11 +8,12 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
type tagCreatePayload struct {
|
||||
Name string
|
||||
// Name
|
||||
Name string `validate:"required" example:"org/acme"`
|
||||
}
|
||||
|
||||
func (payload *tagCreatePayload) Validate(r *http.Request) error {
|
||||
|
@ -22,7 +23,18 @@ func (payload *tagCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/tags
|
||||
// @id TagCreate
|
||||
// @summary Create a new tag
|
||||
// @description Create a new tag.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags tags
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param body body tagCreatePayload true "Tag details"
|
||||
// @success 200 {object} portainer.Tag "Success"
|
||||
// @failure 409 "Tag name exists"
|
||||
// @failure 500 "Server error"
|
||||
// @router /tags [post]
|
||||
func (handler *Handler) tagCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload tagCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -6,12 +6,26 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/internal/edge"
|
||||
)
|
||||
|
||||
// DELETE request on /api/tags/:id
|
||||
// @id TagDelete
|
||||
// @summary Remove a tag
|
||||
// @description Remove a tag.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags tags
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Tag identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Tag not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /tags/{id} [delete]
|
||||
func (handler *Handler) tagDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
id, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -7,7 +7,16 @@ import (
|
|||
"github.com/portainer/libhttp/response"
|
||||
)
|
||||
|
||||
// GET request on /api/tags
|
||||
// @id TagList
|
||||
// @summary List tags
|
||||
// @description List tags.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags tags
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.Tag "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /tags [get]
|
||||
func (handler *Handler) tagList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
tags, err := handler.DataStore.Tag().Tags()
|
||||
if err != nil {
|
||||
|
|
|
@ -7,15 +7,18 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
type teamMembershipCreatePayload struct {
|
||||
UserID int
|
||||
TeamID int
|
||||
Role int
|
||||
// User identifier
|
||||
UserID int `validate:"required" example:"1"`
|
||||
// Team identifier
|
||||
TeamID int `validate:"required" example:"1"`
|
||||
// Role for the user inside the team (1 for leader and 2 for regular member)
|
||||
Role int `validate:"required" example:"1" enums:"1,2"`
|
||||
}
|
||||
|
||||
func (payload *teamMembershipCreatePayload) Validate(r *http.Request) error {
|
||||
|
@ -31,7 +34,22 @@ func (payload *teamMembershipCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// POST request on /api/team_memberships
|
||||
// @id TeamMembershipCreate
|
||||
// @summary Create a new team membership
|
||||
// @description Create a new team memberships. Access is only available to administrators leaders of the associated team.
|
||||
// @description **Access policy**: admin
|
||||
// @tags team_memberships
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body teamMembershipCreatePayload true "Team membership details"
|
||||
// @success 200 {object} portainer.TeamMembership "Success"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied to manage memberships"
|
||||
// @failure 409 "Team membership already registered"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team_memberships [post]
|
||||
func (handler *Handler) teamMembershipCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload teamMembershipCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -6,13 +6,25 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// DELETE request on /api/team_memberships/:id
|
||||
// @id TeamMembershipDelete
|
||||
// @summary Remove a team membership
|
||||
// @description Remove a team membership. Access is only available to administrators leaders of the associated team.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags team_memberships
|
||||
// @security jwt
|
||||
// @param id path int true "TeamMembership identifier"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "TeamMembership not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team_memberships/{id} [delete]
|
||||
func (handler *Handler) teamMembershipDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
membershipID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -9,7 +9,18 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/team_memberships
|
||||
// @id TeamMembershipList
|
||||
// @summary List team memberships
|
||||
// @description List team memberships. Access is only available to administrators and team leaders.
|
||||
// @description **Access policy**: admin
|
||||
// @tags team_memberships
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.TeamMembership "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team_memberships [get]
|
||||
func (handler *Handler) teamMembershipList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
|
|
|
@ -7,16 +7,19 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
httperrors "github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
type teamMembershipUpdatePayload struct {
|
||||
UserID int
|
||||
TeamID int
|
||||
Role int
|
||||
// User identifier
|
||||
UserID int `validate:"required" example:"1"`
|
||||
// Team identifier
|
||||
TeamID int `validate:"required" example:"1"`
|
||||
// Role for the user inside the team (1 for leader and 2 for regular member)
|
||||
Role int `validate:"required" example:"1" enums:"1,2"`
|
||||
}
|
||||
|
||||
func (payload *teamMembershipUpdatePayload) Validate(r *http.Request) error {
|
||||
|
@ -32,7 +35,22 @@ func (payload *teamMembershipUpdatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/team_memberships/:id
|
||||
// @id TeamMembershipUpdate
|
||||
// @summary Update a team membership
|
||||
// @description Update a team membership. Access is only available to administrators leaders of the associated team.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags team_memberships
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Team membership identifier"
|
||||
// @param body body teamMembershipUpdatePayload true "Team membership details"
|
||||
// @success 200 {object} portainer.TeamMembership "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "TeamMembership not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team_memberships/{id} [put]
|
||||
func (handler *Handler) teamMembershipUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
membershipID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,12 +8,13 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
type teamCreatePayload struct {
|
||||
Name string
|
||||
// Name
|
||||
Name string `example:"developers" validate:"required"`
|
||||
}
|
||||
|
||||
func (payload *teamCreatePayload) Validate(r *http.Request) error {
|
||||
|
@ -23,6 +24,20 @@ func (payload *teamCreatePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id TeamCreate
|
||||
// @summary Create a new team
|
||||
// @description Create a new team.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags teams
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body teamCreatePayload true "details"
|
||||
// @success 200 {object} portainer.Team "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 409 "Team already exists"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team [post]
|
||||
func (handler *Handler) teamCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload teamCreatePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -6,11 +6,22 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// DELETE request on /api/teams/:id
|
||||
// @id TeamDelete
|
||||
// @summary Remove a team
|
||||
// @description Remove a team.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags teams
|
||||
// @security jwt
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Team not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /teams/{id} [delete]
|
||||
func (handler *Handler) teamDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
teamID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,13 +6,27 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
bolterrors "github.com/portainer/portainer/api/bolt/errors"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/teams/:id
|
||||
// @id TeamInspect
|
||||
// @summary Inspect a team
|
||||
// @description Retrieve details about a team. Access is only available for administrator and leaders of that team.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags teams
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param id path int true "Team identifier"
|
||||
// @success 200 {object} portainer.Team "Success"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Team not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /teams/{id} [get]
|
||||
func (handler *Handler) teamInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
teamID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -8,7 +8,16 @@ import (
|
|||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/teams
|
||||
// @id TeamList
|
||||
// @summary List teams
|
||||
// @description List teams. For non-administrator users, will only list the teams they are member of.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags teams
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.Team "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /teams [get]
|
||||
func (handler *Handler) teamList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
teams, err := handler.DataStore.Team().Teams()
|
||||
if err != nil {
|
||||
|
|
|
@ -6,12 +6,23 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/http/errors"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
)
|
||||
|
||||
// GET request on /api/teams/:id/memberships
|
||||
// @id TeamMemberships
|
||||
// @summary List team memberships
|
||||
// @description List team memberships. Access is only available to administrators and team leaders.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags team_memberships
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {array} portainer.TeamMembership "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 500 "Server error"
|
||||
// @router /teams/{id}/memberships [get]
|
||||
func (handler *Handler) teamMemberships(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
teamID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -6,19 +6,36 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
type teamUpdatePayload struct {
|
||||
Name string
|
||||
// Name
|
||||
Name string `example:"developers"`
|
||||
}
|
||||
|
||||
func (payload *teamUpdatePayload) Validate(r *http.Request) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PUT request on /api/teams/:id
|
||||
// @id TeamUpdate
|
||||
// @summary Update a team
|
||||
// @description Update a team.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param id path int true "Team identifier"
|
||||
// @param body body teamUpdatePayload true "Team details"
|
||||
// @success 200 {object} portainer.Team "Success"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 403 "Permission denied"
|
||||
// @failure 404 "Team not found"
|
||||
// @failure 500 "Server error"
|
||||
// @router /team/{id} [put]
|
||||
func (handler *Handler) teamUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
teamID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
|
|
|
@ -13,12 +13,15 @@ import (
|
|||
)
|
||||
|
||||
type filePayload struct {
|
||||
RepositoryURL string
|
||||
ComposeFilePathInRepository string
|
||||
// URL of a git repository where the file is stored
|
||||
RepositoryURL string `example:"https://github.com/portainer/portainer-compose" validate:"required"`
|
||||
// Path to the file inside the git repository
|
||||
ComposeFilePathInRepository string `example:"./subfolder/docker-compose.yml" validate:"required"`
|
||||
}
|
||||
|
||||
type fileResponse struct {
|
||||
FileContent string
|
||||
// The requested file content
|
||||
FileContent string `example: "version:2"`
|
||||
}
|
||||
|
||||
func (payload *filePayload) Validate(r *http.Request) error {
|
||||
|
@ -33,6 +36,19 @@ func (payload *filePayload) Validate(r *http.Request) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// @id TemplateFile
|
||||
// @summary Get a template's file
|
||||
// @description Get a template's file
|
||||
// @description **Access policy**: restricted
|
||||
// @tags templates
|
||||
// @security jwt
|
||||
// @accept json
|
||||
// @produce json
|
||||
// @param body body filePayload true "File details"
|
||||
// @success 200 {object} fileResponse "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /templates/file [post]
|
||||
func (handler *Handler) templateFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
var payload filePayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
|
|
|
@ -5,9 +5,25 @@ import (
|
|||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
)
|
||||
|
||||
// GET request on /api/templates
|
||||
// introduced for swagger
|
||||
type listResponse struct {
|
||||
Version string
|
||||
Templates []portainer.Template
|
||||
}
|
||||
|
||||
// @id TemplateList
|
||||
// @summary List available templates
|
||||
// @description List available templates.
|
||||
// @description **Access policy**: restricted
|
||||
// @tags templates
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @success 200 {object} listResponse "Success"
|
||||
// @failure 500 "Server error"
|
||||
// @router /templates [get]
|
||||
func (handler *Handler) templateList(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
settings, err := handler.DataStore.Settings().Settings()
|
||||
if err != nil {
|
||||
|
|
|
@ -6,11 +6,25 @@ import (
|
|||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/request"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/filesystem"
|
||||
)
|
||||
|
||||
// POST request on /api/upload/tls/{certificate:(?:ca|cert|key)}?folder=<folder>
|
||||
// @id UploadTLS
|
||||
// @summary Upload TLS files
|
||||
// @description Use this endpoint to upload TLS files.
|
||||
// @description **Access policy**: administrator
|
||||
// @tags upload
|
||||
// @security jwt
|
||||
// @accept multipart/form-data
|
||||
// @produce json
|
||||
// @param certificate path string true "TLS file type. Valid values are 'ca', 'cert' or 'key'." Enums(ca,cert,key)
|
||||
// @param folder formData string true "Folder where the TLS file will be stored. Will be created if not existing"
|
||||
// @param file formData file true "The file to upload"
|
||||
// @success 204 "Success"
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @router /upload/tls/{certificate} [post]
|
||||
func (handler *Handler) uploadTLS(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
certificate, err := request.RetrieveRouteVariableValue(r, "certificate")
|
||||
if err != nil {
|
||||
|
|
|
@ -5,11 +5,18 @@ import (
|
|||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
"github.com/portainer/libhttp/response"
|
||||
"github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/bolt/errors"
|
||||
)
|
||||
|
||||
// GET request on /api/users/admin/check
|
||||
// @id UserAdminCheck
|
||||
// @summary Check administrator account existence
|
||||
// @description Check if an administrator account exists in the database.
|
||||
// @description **Access policy**: public
|
||||
// @tags users
|
||||
// @success 204 "Success"
|
||||
// @failure 404 "User not found"
|
||||
// @router /users/admin/check [get]
|
||||
func (handler *Handler) adminCheck(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
users, err := handler.DataStore.User().UsersByRole(portainer.AdministratorRole)
|
||||
if err != nil {
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue