mirror of https://github.com/portainer/portainer
fix(api): restore deleted apis [EE-6090] (#10267)
parent
14853f6da0
commit
af7834174a
|
@ -1,7 +1,7 @@
|
|||
package datastore
|
||||
|
||||
import (
|
||||
portaineree "github.com/portainer/portainer/api"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/database/models"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
)
|
||||
|
@ -72,7 +72,7 @@ func dbVersionToSemanticVersion(dbVersion int) string {
|
|||
func (store *Store) getOrMigrateLegacyVersion() (*models.Version, error) {
|
||||
// Very old versions of portainer did not have a version bucket, lets set some defaults
|
||||
dbVersion := 24
|
||||
edition := int(portaineree.PortainerCE)
|
||||
edition := int(portainer.PortainerCE)
|
||||
instanceId := ""
|
||||
|
||||
// If we already have a version key, we don't need to migrate
|
||||
|
|
|
@ -3,6 +3,7 @@ package customtemplates
|
|||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"regexp"
|
||||
|
@ -473,3 +474,29 @@ func (handler *Handler) createCustomTemplateFromFileUpload(r *http.Request) (*po
|
|||
|
||||
return customTemplate, nil
|
||||
}
|
||||
|
||||
// @id CustomTemplateCreate
|
||||
// @summary Create a custom template
|
||||
// @description Create a custom template.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags custom_templates
|
||||
// @security ApiKeyAuth
|
||||
// @security jwt
|
||||
// @accept json,multipart/form-data
|
||||
// @produce json
|
||||
// @param method query string true "method for creating template" Enums(string, file, repository)
|
||||
// @param body body object true "for body documentation see the relevant /custom_templates/{method} endpoint"
|
||||
// @success 200 {object} portainer.CustomTemplate
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @deprecated
|
||||
// @router /custom_templates [post]
|
||||
func deprecatedCustomTemplateCreateUrlParser(w http.ResponseWriter, r *http.Request) (string, *httperror.HandlerError) {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
return "", httperror.BadRequest("Invalid query parameter: method", err)
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("/custom_templates/create/%s", method)
|
||||
return url, nil
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"github.com/gorilla/mux"
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
"github.com/portainer/portainer/api/http/middlewares"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
||||
)
|
||||
|
@ -32,6 +33,7 @@ func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStor
|
|||
|
||||
h.Handle("/custom_templates/create/{method}",
|
||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.customTemplateCreate))).Methods(http.MethodPost)
|
||||
h.Handle("/custom_templates", middlewares.Deprecated(h, deprecatedCustomTemplateCreateUrlParser)).Methods(http.MethodPost) // Deprecated
|
||||
h.Handle("/custom_templates",
|
||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.customTemplateList))).Methods(http.MethodGet)
|
||||
h.Handle("/custom_templates/{id}",
|
||||
|
|
|
@ -2,6 +2,7 @@ package edgejobs
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"maps"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -278,3 +279,26 @@ func (handler *Handler) addAndPersistEdgeJob(tx dataservices.DataStoreTx, edgeJo
|
|||
|
||||
return tx.EdgeJob().CreateWithID(edgeJob.ID, edgeJob)
|
||||
}
|
||||
|
||||
// @id EdgeJobCreate
|
||||
// @summary Create an EdgeJob
|
||||
// @description **Access policy**: administrator
|
||||
// @tags edge_jobs
|
||||
// @security ApiKeyAuth
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param method query string true "Creation Method" Enums(file, string)
|
||||
// @param body body object true "for body documentation see the relevant /edge_jobs/create/{method} endpoint"
|
||||
// @success 200 {object} portainer.EdgeGroup
|
||||
// @failure 503 "Edge compute features are disabled"
|
||||
// @failure 500
|
||||
// @deprecated
|
||||
// @router /edge_jobs [post]
|
||||
func deprecatedEdgeJobCreateUrlParser(w http.ResponseWriter, r *http.Request) (string, *httperror.HandlerError) {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
return "", httperror.BadRequest("Invalid query parameter: method. Valid values are: file or string", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("/edge_jobs/create/%s", method), nil
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
"github.com/portainer/portainer/api/http/middlewares"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
||||
"github.com/portainer/portainer/pkg/libhttp/response"
|
||||
|
@ -29,6 +30,8 @@ func NewHandler(bouncer security.BouncerService) *Handler {
|
|||
|
||||
h.Handle("/edge_jobs",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeJobList)))).Methods(http.MethodGet)
|
||||
h.Handle("/edge_jobs",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(middlewares.Deprecated(h, deprecatedEdgeJobCreateUrlParser)))).Methods(http.MethodPost)
|
||||
h.Handle("/edge_jobs/create/{method}",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeJobCreate)))).Methods(http.MethodPost)
|
||||
h.Handle("/edge_jobs/{id}",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package edgestacks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
|
@ -17,6 +18,7 @@ func (handler *Handler) edgeStackCreate(w http.ResponseWriter, r *http.Request)
|
|||
if err != nil {
|
||||
return httperror.BadRequest("Invalid query parameter: method", err)
|
||||
}
|
||||
|
||||
dryrun, _ := request.RetrieveBooleanQueryParameter(r, "dryrun", true)
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
|
@ -55,3 +57,26 @@ func (handler *Handler) createSwarmStack(tx dataservices.DataStoreTx, method str
|
|||
|
||||
return nil, httperrors.NewInvalidPayloadError("Invalid value for query parameter: method. Value must be one of: string, repository or file")
|
||||
}
|
||||
|
||||
// @id EdgeStackCreate
|
||||
// @summary Create an EdgeStack
|
||||
// @description **Access policy**: administrator
|
||||
// @tags edge_stacks
|
||||
// @security ApiKeyAuth
|
||||
// @security jwt
|
||||
// @produce json
|
||||
// @param method query string true "Creation Method" Enums(file,string,repository)
|
||||
// @param body body object true "for body documentation see the relevant /edge_stacks/create/{method} endpoint"
|
||||
// @success 200 {object} portainer.EdgeStack
|
||||
// @failure 500
|
||||
// @failure 503 "Edge compute features are disabled"
|
||||
// @deprecated
|
||||
// @router /edge_stacks [post]
|
||||
func deprecatedEdgeStackCreateUrlParser(w http.ResponseWriter, r *http.Request) (string, *httperror.HandlerError) {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
return "", httperror.BadRequest("Invalid query parameter: method. Valid values are: file or string", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("/edge_stacks/create/%s", method), nil
|
||||
}
|
||||
|
|
|
@ -39,6 +39,8 @@ func NewHandler(bouncer security.BouncerService, dataStore dataservices.DataStor
|
|||
|
||||
h.Handle("/edge_stacks/create/{method}",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeStackCreate)))).Methods(http.MethodPost)
|
||||
h.Handle("/edge_stacks",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(middlewares.Deprecated(h, deprecatedEdgeStackCreateUrlParser)))).Methods(http.MethodPost) // Deprecated
|
||||
h.Handle("/edge_stacks",
|
||||
bouncer.AdminAccess(bouncer.EdgeComputeOperation(httperror.LoggerHandler(h.edgeStackList)))).Methods(http.MethodGet)
|
||||
h.Handle("/edge_stacks/{id}",
|
||||
|
|
|
@ -10,6 +10,7 @@ import (
|
|||
portainer "github.com/portainer/portainer/api"
|
||||
"github.com/portainer/portainer/api/dataservices"
|
||||
dockerclient "github.com/portainer/portainer/api/docker/client"
|
||||
"github.com/portainer/portainer/api/http/middlewares"
|
||||
"github.com/portainer/portainer/api/http/security"
|
||||
"github.com/portainer/portainer/api/internal/authorization"
|
||||
"github.com/portainer/portainer/api/internal/endpointutils"
|
||||
|
@ -59,6 +60,8 @@ func NewHandler(bouncer security.BouncerService) *Handler {
|
|||
|
||||
h.Handle("/stacks/create/{type}/{method}",
|
||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.stackCreate))).Methods(http.MethodPost)
|
||||
h.Handle("/stacks",
|
||||
bouncer.AuthenticatedAccess(middlewares.Deprecated(h, deprecatedStackCreateUrlParser))).Methods(http.MethodPost) // Deprecated
|
||||
h.Handle("/stacks",
|
||||
bouncer.AuthenticatedAccess(httperror.LoggerHandler(h.stackList))).Methods(http.MethodGet)
|
||||
h.Handle("/stacks/{id}",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package stacks
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
portainer "github.com/portainer/portainer/api"
|
||||
|
@ -140,3 +141,53 @@ func (handler *Handler) decorateStackResponse(w http.ResponseWriter, stack *port
|
|||
|
||||
return response.JSON(w, stack)
|
||||
}
|
||||
|
||||
func getStackTypeFromQueryParameter(r *http.Request) (string, error) {
|
||||
stackType, err := request.RetrieveNumericQueryParameter(r, "type", false)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
switch stackType {
|
||||
case 1:
|
||||
return "swarm", nil
|
||||
case 2:
|
||||
return "standalone", nil
|
||||
case 3:
|
||||
return "kubernetes", nil
|
||||
}
|
||||
|
||||
return "", errors.New(request.ErrInvalidQueryParameter)
|
||||
}
|
||||
|
||||
// @id StackCreate
|
||||
// @summary Deploy a new stack
|
||||
// @description Deploy a new stack into a Docker environment(endpoint) specified via the environment(endpoint) identifier.
|
||||
// @description **Access policy**: authenticated
|
||||
// @tags stacks
|
||||
// @security ApiKeyAuth
|
||||
// @security jwt
|
||||
// @accept json,multipart/form-data
|
||||
// @produce json
|
||||
// @param type query int true "Stack deployment type. Possible values: 1 (Swarm stack), 2 (Compose stack) or 3 (Kubernetes stack)." Enums(1,2,3)
|
||||
// @param method query string true "Stack deployment method. Possible values: file, string, repository or url." Enums(string, file, repository, url)
|
||||
// @param endpointId query int true "Identifier of the environment(endpoint) that will be used to deploy the stack"
|
||||
// @param body body object true "for body documentation see the relevant /stacks/create/{type}/{method} endpoint"
|
||||
// @success 200 {object} portainer.Stack
|
||||
// @failure 400 "Invalid request"
|
||||
// @failure 500 "Server error"
|
||||
// @deprecated
|
||||
// @router /stacks [post]
|
||||
func deprecatedStackCreateUrlParser(w http.ResponseWriter, r *http.Request) (string, *httperror.HandlerError) {
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
return "", httperror.BadRequest("Invalid query parameter: method. Valid values are: file or string", err)
|
||||
}
|
||||
|
||||
stackType, err := getStackTypeFromQueryParameter(r)
|
||||
if err != nil {
|
||||
return "", httperror.BadRequest("Invalid query parameter: type", err)
|
||||
}
|
||||
|
||||
return fmt.Sprintf("/stacks/create/%s/%s", stackType, method), nil
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
package middlewares
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
httperror "github.com/portainer/portainer/pkg/libhttp/error"
|
||||
"github.com/rs/zerolog/log"
|
||||
)
|
||||
|
||||
// deprecate api route
|
||||
func Deprecated(router http.Handler, urlBuilder func(w http.ResponseWriter, r *http.Request) (string, *httperror.HandlerError)) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
newUrl, err := urlBuilder(w, r)
|
||||
if err != nil {
|
||||
httperror.WriteError(w, err.StatusCode, err.Error(), err)
|
||||
return
|
||||
}
|
||||
|
||||
log.Warn().Msgf("This api is deprecated. Use %s instead", newUrl)
|
||||
|
||||
redirectedRequest := r.Clone(r.Context())
|
||||
redirectedRequest.URL.Path = newUrl
|
||||
router.ServeHTTP(w, redirectedRequest)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue