mirror of
https://github.com/portainer/portainer.git
synced 2025-08-04 21:35:23 +02:00
chore(handlers): replace structs by functions for HTTP errors EE-4227 (#7664)
This commit is contained in:
parent
7accdf704c
commit
9ef5636718
157 changed files with 1123 additions and 1147 deletions
|
@ -2,7 +2,6 @@ package stacks
|
|||
|
||||
import (
|
||||
"log"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
httperror "github.com/portainer/libhttp/error"
|
||||
|
@ -15,7 +14,7 @@ import (
|
|||
func startAutoupdate(stackID portainer.StackID, interval string, scheduler *scheduler.Scheduler, stackDeployer stacks.StackDeployer, datastore dataservices.DataStore, gitService portainer.GitService) (jobID string, e *httperror.HandlerError) {
|
||||
d, err := time.ParseDuration(interval)
|
||||
if err != nil {
|
||||
return "", &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Unable to parse stack's auto update interval", Err: err}
|
||||
return "", httperror.BadRequest("Unable to parse stack's auto update interval", err)
|
||||
}
|
||||
|
||||
jobID = scheduler.StartJobEvery(d, func() error {
|
||||
|
@ -33,5 +32,4 @@ func stopAutoupdate(stackID portainer.StackID, jobID string, scheduler scheduler
|
|||
if err := scheduler.StopJob(jobID); err != nil {
|
||||
log.Printf("[WARN] could not stop the job for the stack %v", stackID)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -74,14 +74,14 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
var payload composeStackFromFileContentPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.ComposeStackManager.NormalizeStackName(payload.Name)
|
||||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to check for name collision", err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
|
||||
if !isUnique {
|
||||
|
@ -93,7 +93,7 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
|
||||
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
} else {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -117,7 +117,7 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, []byte(payload.StackFileContent))
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist Compose file on disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist Compose file on disk", err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -131,14 +131,14 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
|
|||
|
||||
err = handler.deployComposeStack(config, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
stack.CreatedBy = config.user.Username
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -190,7 +190,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
var payload composeStackFromGitRepositoryPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.ComposeStackManager.NormalizeStackName(payload.Name)
|
||||
|
@ -200,7 +200,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
|
||||
if !isUnique {
|
||||
|
@ -212,7 +212,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
|
||||
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
} else {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -224,7 +224,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
if payload.AutoUpdate != nil && payload.AutoUpdate.Webhook != "" {
|
||||
isUnique, err := handler.checkUniqueWebhookID(payload.AutoUpdate.Webhook)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for webhook ID collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for webhook ID collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("Webhook ID: %s already exists", payload.AutoUpdate.Webhook), Err: errWebhookIDAlreadyExists}
|
||||
|
@ -266,12 +266,12 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
|
||||
err = handler.clone(projectPath, payload.RepositoryURL, payload.RepositoryReferenceName, payload.RepositoryAuthentication, payload.RepositoryUsername, payload.RepositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to clone git repository", Err: err}
|
||||
return httperror.InternalServerError("Unable to clone git repository", err)
|
||||
}
|
||||
|
||||
commitID, err := handler.latestCommitID(payload.RepositoryURL, payload.RepositoryReferenceName, payload.RepositoryAuthentication, payload.RepositoryUsername, payload.RepositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository id", Err: err}
|
||||
return httperror.InternalServerError("Unable to fetch git repository id", err)
|
||||
}
|
||||
stack.GitConfig.ConfigHash = commitID
|
||||
|
||||
|
@ -282,7 +282,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
|
||||
err = handler.deployComposeStack(config, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
if payload.AutoUpdate != nil && payload.AutoUpdate.Interval != "" {
|
||||
|
@ -298,7 +298,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
|
|||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -337,14 +337,14 @@ func decodeRequestForm(r *http.Request) (*composeStackFromFileUploadPayload, err
|
|||
func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter, r *http.Request, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
payload, err := decodeRequestForm(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.ComposeStackManager.NormalizeStackName(payload.Name)
|
||||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
|
||||
if !isUnique {
|
||||
|
@ -356,7 +356,7 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
|
|||
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
|
||||
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
} else {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -379,7 +379,7 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
|
|||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, payload.StackFileContent)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist Compose file on disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist Compose file on disk", err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -393,14 +393,14 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
|
|||
|
||||
err = handler.deployComposeStack(config, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
stack.CreatedBy = config.user.Username
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -418,17 +418,17 @@ type composeStackDeploymentConfig struct {
|
|||
func (handler *Handler) createComposeDeployConfig(r *http.Request, stack *portainer.Stack, endpoint *portainer.Endpoint) (*composeStackDeploymentConfig, *httperror.HandlerError) {
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to load user information from the database", Err: err}
|
||||
return nil, httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
|
||||
registries, err := handler.DataStore.Registry().Registries()
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve registries from the database", Err: err}
|
||||
return nil, httperror.InternalServerError("Unable to retrieve registries from the database", err)
|
||||
}
|
||||
filteredRegistries := security.FilterRegistries(registries, user, securityContext.UserMemberships, endpoint.ID)
|
||||
|
||||
|
|
|
@ -96,16 +96,16 @@ type createKubernetesStackResponse struct {
|
|||
func (handler *Handler) createKubernetesStackFromFileContent(w http.ResponseWriter, r *http.Request, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
var payload kubernetesStringDeploymentPayload
|
||||
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(userID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to load user information from the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
isUnique, err := handler.checkUniqueStackNameInKubernetes(endpoint, payload.StackName, 0, payload.Namespace)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("A stack with the name '%s' already exists", payload.StackName), Err: errStackAlreadyExists}
|
||||
|
@ -133,7 +133,7 @@ func (handler *Handler) createKubernetesStackFromFileContent(w http.ResponseWrit
|
|||
fileType = "Compose"
|
||||
}
|
||||
errMsg := fmt.Sprintf("Unable to persist Kubernetes %s file on disk", fileType)
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: errMsg, Err: err}
|
||||
return httperror.InternalServerError(errMsg, err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -148,12 +148,12 @@ func (handler *Handler) createKubernetesStackFromFileContent(w http.ResponseWrit
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to deploy Kubernetes stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to deploy Kubernetes stack", err)
|
||||
}
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the Kubernetes stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the Kubernetes stack inside the database", err)
|
||||
}
|
||||
|
||||
resp := &createKubernetesStackResponse{
|
||||
|
@ -167,16 +167,16 @@ func (handler *Handler) createKubernetesStackFromFileContent(w http.ResponseWrit
|
|||
func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWriter, r *http.Request, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
var payload kubernetesGitDeploymentPayload
|
||||
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(userID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to load user information from the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
isUnique, err := handler.checkUniqueStackNameInKubernetes(endpoint, payload.StackName, 0, payload.Namespace)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("A stack with the name '%s' already exists", payload.StackName), Err: errStackAlreadyExists}
|
||||
|
@ -186,7 +186,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
if payload.AutoUpdate != nil && payload.AutoUpdate.Webhook != "" {
|
||||
isUnique, err := handler.checkUniqueWebhookID(payload.AutoUpdate.Webhook)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for webhook ID collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for webhook ID collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("Webhook ID: %s already exists", payload.AutoUpdate.Webhook), Err: errWebhookIDAlreadyExists}
|
||||
|
@ -229,7 +229,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
|
||||
commitID, err := handler.latestCommitID(payload.RepositoryURL, payload.RepositoryReferenceName, payload.RepositoryAuthentication, payload.RepositoryUsername, payload.RepositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository id", Err: err}
|
||||
return httperror.InternalServerError("Unable to fetch git repository id", err)
|
||||
}
|
||||
stack.GitConfig.ConfigHash = commitID
|
||||
|
||||
|
@ -242,7 +242,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
|
||||
err = handler.GitService.CloneRepository(projectPath, payload.RepositoryURL, payload.RepositoryReferenceName, repositoryUsername, repositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Failed to clone git repository", Err: err}
|
||||
return httperror.InternalServerError("Failed to clone git repository", err)
|
||||
}
|
||||
|
||||
output, err := handler.deployKubernetesStack(user.ID, endpoint, stack, k.KubeAppLabels{
|
||||
|
@ -253,7 +253,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to deploy Kubernetes stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to deploy Kubernetes stack", err)
|
||||
}
|
||||
|
||||
if payload.AutoUpdate != nil && payload.AutoUpdate.Interval != "" {
|
||||
|
@ -267,7 +267,7 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
resp := &createKubernetesStackResponse{
|
||||
|
@ -281,16 +281,16 @@ func (handler *Handler) createKubernetesStackFromGitRepository(w http.ResponseWr
|
|||
func (handler *Handler) createKubernetesStackFromManifestURL(w http.ResponseWriter, r *http.Request, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
var payload kubernetesManifestURLDeploymentPayload
|
||||
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(userID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to load user information from the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
isUnique, err := handler.checkUniqueStackNameInKubernetes(endpoint, payload.StackName, 0, payload.Namespace)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("A stack with the name '%s' already exists", payload.StackName), Err: errStackAlreadyExists}
|
||||
|
@ -313,13 +313,13 @@ func (handler *Handler) createKubernetesStackFromManifestURL(w http.ResponseWrit
|
|||
var manifestContent []byte
|
||||
manifestContent, err = client.Get(payload.ManifestURL, 30)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve manifest from URL", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve manifest from URL", err)
|
||||
}
|
||||
|
||||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, manifestContent)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist Kubernetes manifest file on disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist Kubernetes manifest file on disk", err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -333,12 +333,12 @@ func (handler *Handler) createKubernetesStackFromManifestURL(w http.ResponseWrit
|
|||
Kind: "url",
|
||||
})
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to deploy Kubernetes stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to deploy Kubernetes stack", err)
|
||||
}
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the Kubernetes stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the Kubernetes stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
|
|
@ -47,7 +47,7 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
var payload swarmStackFromFileContentPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid request payload", err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.SwarmStackManager.NormalizeStackName(payload.Name)
|
||||
|
@ -55,7 +55,7 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, true)
|
||||
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to check for name collision", err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -78,7 +78,7 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, []byte(payload.StackFileContent))
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist Compose file on disk", err}
|
||||
return httperror.InternalServerError("Unable to persist Compose file on disk", err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -92,14 +92,14 @@ func (handler *Handler) createSwarmStackFromFileContent(w http.ResponseWriter, r
|
|||
|
||||
err = handler.deploySwarmStack(config)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, err.Error(), err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
stack.CreatedBy = config.user.Username
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the stack inside the database", err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -157,14 +157,14 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
var payload swarmStackFromGitRepositoryPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.SwarmStackManager.NormalizeStackName(payload.Name)
|
||||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -174,7 +174,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
if payload.AutoUpdate != nil && payload.AutoUpdate.Webhook != "" {
|
||||
isUnique, err := handler.checkUniqueWebhookID(payload.AutoUpdate.Webhook)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for webhook ID collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for webhook ID collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: fmt.Sprintf("Webhook ID: %s already exists", payload.AutoUpdate.Webhook), Err: errWebhookIDAlreadyExists}
|
||||
|
@ -217,12 +217,12 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
|
||||
err = handler.clone(projectPath, payload.RepositoryURL, payload.RepositoryReferenceName, payload.RepositoryAuthentication, payload.RepositoryUsername, payload.RepositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to clone git repository", Err: err}
|
||||
return httperror.InternalServerError("Unable to clone git repository", err)
|
||||
}
|
||||
|
||||
commitID, err := handler.latestCommitID(payload.RepositoryURL, payload.RepositoryReferenceName, payload.RepositoryAuthentication, payload.RepositoryUsername, payload.RepositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository id", Err: err}
|
||||
return httperror.InternalServerError("Unable to fetch git repository id", err)
|
||||
}
|
||||
stack.GitConfig.ConfigHash = commitID
|
||||
|
||||
|
@ -233,7 +233,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
|
||||
err = handler.deploySwarmStack(config)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
if payload.AutoUpdate != nil && payload.AutoUpdate.Interval != "" {
|
||||
|
@ -249,7 +249,7 @@ func (handler *Handler) createSwarmStackFromGitRepository(w http.ResponseWriter,
|
|||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -295,7 +295,7 @@ func (handler *Handler) createSwarmStackFromFileUpload(w http.ResponseWriter, r
|
|||
payload := &swarmStackFromFileUploadPayload{}
|
||||
err := payload.Validate(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid request payload", err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
payload.Name = handler.SwarmStackManager.NormalizeStackName(payload.Name)
|
||||
|
@ -303,7 +303,7 @@ func (handler *Handler) createSwarmStackFromFileUpload(w http.ResponseWriter, r
|
|||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, true)
|
||||
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to check for name collision", err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
return stackExistsError(payload.Name)
|
||||
|
@ -325,7 +325,7 @@ func (handler *Handler) createSwarmStackFromFileUpload(w http.ResponseWriter, r
|
|||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
projectPath, err := handler.FileService.StoreStackFileFromBytes(stackFolder, stack.EntryPoint, []byte(payload.StackFileContent))
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist Compose file on disk", err}
|
||||
return httperror.InternalServerError("Unable to persist Compose file on disk", err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
@ -339,14 +339,14 @@ func (handler *Handler) createSwarmStackFromFileUpload(w http.ResponseWriter, r
|
|||
|
||||
err = handler.deploySwarmStack(config)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, err.Error(), err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
stack.CreatedBy = config.user.Username
|
||||
|
||||
err = handler.DataStore.Stack().Create(stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the stack inside the database", err}
|
||||
return httperror.InternalServerError("Unable to persist the stack inside the database", err)
|
||||
}
|
||||
|
||||
doCleanUp = false
|
||||
|
@ -365,17 +365,17 @@ type swarmStackDeploymentConfig struct {
|
|||
func (handler *Handler) createSwarmDeployConfig(r *http.Request, stack *portainer.Stack, endpoint *portainer.Endpoint, prune bool) (*swarmStackDeploymentConfig, *httperror.HandlerError) {
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return nil, httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to load user information from the database", err}
|
||||
return nil, httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
|
||||
registries, err := handler.DataStore.Registry().Registries()
|
||||
if err != nil {
|
||||
return nil, &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve registries from the database", err}
|
||||
return nil, httperror.InternalServerError("Unable to retrieve registries from the database", err)
|
||||
}
|
||||
filteredRegistries := security.FilterRegistries(registries, user, securityContext.UserMemberships, endpoint.ID)
|
||||
|
||||
|
|
|
@ -33,44 +33,44 @@ import (
|
|||
func (handler *Handler) stackAssociate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: endpointId", err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
|
||||
swarmId, err := request.RetrieveQueryParameter(r, "swarmId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: swarmId", err}
|
||||
return httperror.BadRequest("Invalid query parameter: swarmId", err)
|
||||
}
|
||||
|
||||
orphanedRunning, err := request.RetrieveBooleanQueryParameter(r, "orphanedRunning", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: orphanedRunning", err}
|
||||
return httperror.BadRequest("Invalid query parameter: orphanedRunning", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to load user information from the database", err}
|
||||
return httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
if resourceControl != nil {
|
||||
|
@ -78,24 +78,24 @@ func (handler *Handler) stackAssociate(w http.ResponseWriter, r *http.Request) *
|
|||
|
||||
err = handler.DataStore.ResourceControl().UpdateResourceControl(resourceControl.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist resource control changes inside the database", err}
|
||||
return httperror.InternalServerError("Unable to persist resource control changes inside the database", err)
|
||||
}
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find an environment with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find an environment with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: fmt.Errorf(errMsg)}
|
||||
return httperror.Forbidden(errMsg, fmt.Errorf(errMsg))
|
||||
}
|
||||
|
||||
stack.EndpointID = portainer.EndpointID(endpointID)
|
||||
|
@ -114,7 +114,7 @@ func (handler *Handler) stackAssociate(w http.ResponseWriter, r *http.Request) *
|
|||
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the stack changes inside the database", err}
|
||||
return httperror.InternalServerError("Unable to persist the stack changes inside the database", err)
|
||||
}
|
||||
|
||||
stack.ResourceControl = resourceControl
|
||||
|
|
|
@ -55,48 +55,48 @@ func (handler *Handler) cleanUp(stack *portainer.Stack, doCleanUp *bool) error {
|
|||
func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackType, err := request.RetrieveNumericQueryParameter(r, "type", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: type", err}
|
||||
return httperror.BadRequest("Invalid query parameter: type", err)
|
||||
}
|
||||
|
||||
method, err := request.RetrieveQueryParameter(r, "method", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: method", err}
|
||||
return httperror.BadRequest("Invalid query parameter: method", err)
|
||||
}
|
||||
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: endpointId", err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve user info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve user info from request context", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack creation is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user details from authentication token", err}
|
||||
return httperror.InternalServerError("Unable to retrieve user details from authentication token", err)
|
||||
}
|
||||
|
||||
switch portainer.StackType(stackType) {
|
||||
|
@ -108,7 +108,7 @@ func (handler *Handler) stackCreate(w http.ResponseWriter, r *http.Request) *htt
|
|||
return handler.createKubernetesStack(w, r, method, endpoint, tokenData.ID)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid value for query parameter: type. Value must be one of: 1 (Swarm stack) or 2 (Compose stack)", errors.New(request.ErrInvalidQueryParameter)}
|
||||
return httperror.BadRequest("Invalid value for query parameter: type. Value must be one of: 1 (Swarm stack) or 2 (Compose stack)", errors.New(request.ErrInvalidQueryParameter))
|
||||
}
|
||||
|
||||
func (handler *Handler) createComposeStack(w http.ResponseWriter, r *http.Request, method string, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
|
@ -122,7 +122,7 @@ func (handler *Handler) createComposeStack(w http.ResponseWriter, r *http.Reques
|
|||
return handler.createComposeStackFromFileUpload(w, r, endpoint, userID)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid value for query parameter: method. Value must be one of: string, repository or file", Err: errors.New(request.ErrInvalidQueryParameter)}
|
||||
return httperror.BadRequest("Invalid value for query parameter: method. Value must be one of: string, repository or file", errors.New(request.ErrInvalidQueryParameter))
|
||||
}
|
||||
|
||||
func (handler *Handler) createSwarmStack(w http.ResponseWriter, r *http.Request, method string, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
|
@ -135,7 +135,7 @@ func (handler *Handler) createSwarmStack(w http.ResponseWriter, r *http.Request,
|
|||
return handler.createSwarmStackFromFileUpload(w, r, endpoint, userID)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid value for query parameter: method. Value must be one of: string, repository or file", Err: errors.New(request.ErrInvalidQueryParameter)}
|
||||
return httperror.BadRequest("Invalid value for query parameter: method. Value must be one of: string, repository or file", errors.New(request.ErrInvalidQueryParameter))
|
||||
}
|
||||
|
||||
func (handler *Handler) createKubernetesStack(w http.ResponseWriter, r *http.Request, method string, endpoint *portainer.Endpoint, userID portainer.UserID) *httperror.HandlerError {
|
||||
|
@ -147,7 +147,7 @@ func (handler *Handler) createKubernetesStack(w http.ResponseWriter, r *http.Req
|
|||
case "url":
|
||||
return handler.createKubernetesStackFromManifestURL(w, r, endpoint, userID)
|
||||
}
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid value for query parameter: method. Value must be one of: string or repository", Err: errors.New(request.ErrInvalidQueryParameter)}
|
||||
return httperror.BadRequest("Invalid value for query parameter: method. Value must be one of: string or repository", errors.New(request.ErrInvalidQueryParameter))
|
||||
}
|
||||
|
||||
func (handler *Handler) isValidStackFile(stackFileContent []byte, securitySettings *portainer.EndpointSecuritySettings) error {
|
||||
|
@ -212,7 +212,7 @@ func (handler *Handler) decorateStackResponse(w http.ResponseWriter, stack *port
|
|||
|
||||
isAdmin, err := handler.userIsAdmin(userID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to load user information from the database", err}
|
||||
return httperror.InternalServerError("Unable to load user information from the database", err)
|
||||
}
|
||||
|
||||
if isAdmin {
|
||||
|
@ -223,7 +223,7 @@ func (handler *Handler) decorateStackResponse(w http.ResponseWriter, stack *port
|
|||
|
||||
err = handler.DataStore.ResourceControl().Create(resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist resource control inside the database", err}
|
||||
return httperror.InternalServerError("Unable to persist resource control inside the database", err)
|
||||
}
|
||||
|
||||
stack.ResourceControl = resourceControl
|
||||
|
|
|
@ -38,12 +38,12 @@ import (
|
|||
func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
externalStack, _ := request.RetrieveBooleanQueryParameter(r, "external", true)
|
||||
|
@ -53,63 +53,63 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
id, err := strconv.Atoi(stackID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(id))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
|
||||
isOrphaned := portainer.EndpointID(endpointID) != stack.EndpointID
|
||||
|
||||
if isOrphaned && !securityContext.IsAdmin {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to remove orphaned stack", Err: errors.New("Permission denied to remove orphaned stack")}
|
||||
return httperror.Forbidden("Permission denied to remove orphaned stack", errors.New("Permission denied to remove orphaned stack"))
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the endpoint associated to the stack inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find the endpoint associated to the stack inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the endpoint associated to the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find the endpoint associated to the stack inside the database", err)
|
||||
}
|
||||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
if !isOrphaned {
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access endpoint", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access endpoint", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack {
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack deletion is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: fmt.Errorf(errMsg)}
|
||||
return httperror.Forbidden(errMsg, fmt.Errorf(errMsg))
|
||||
}
|
||||
|
||||
// stop scheduler updates of the stack before removal
|
||||
|
@ -119,24 +119,24 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
err = handler.deleteStack(securityContext.UserID, stack, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
err = handler.DataStore.Stack().DeleteStack(portainer.StackID(id))
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to remove the stack from the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to remove the stack from the database", err)
|
||||
}
|
||||
|
||||
if resourceControl != nil {
|
||||
err = handler.DataStore.ResourceControl().DeleteResourceControl(resourceControl.ID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to remove the associated resource control from the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to remove the associated resource control from the database", err)
|
||||
}
|
||||
}
|
||||
|
||||
err = handler.FileService.RemoveDirectory(stack.ProjectPath)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to remove stack files from disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to remove stack files from disk", err)
|
||||
}
|
||||
|
||||
return response.Empty(w)
|
||||
|
@ -145,7 +145,7 @@ func (handler *Handler) stackDelete(w http.ResponseWriter, r *http.Request) *htt
|
|||
func (handler *Handler) deleteExternalStack(r *http.Request, w http.ResponseWriter, stackName string, securityContext *security.RestrictedRequestContext) *httperror.HandlerError {
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
|
||||
if !securityContext.IsAdmin {
|
||||
|
@ -154,22 +154,22 @@ func (handler *Handler) deleteExternalStack(r *http.Request, w http.ResponseWrit
|
|||
|
||||
stack, err := handler.DataStore.Stack().StackByName(stackName)
|
||||
if err != nil && !handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for stack existence inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for stack existence inside the database", err)
|
||||
}
|
||||
if stack != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "A stack with this name exists inside the database. Cannot use external delete method", Err: errors.New("A tag already exists with this name")}
|
||||
return httperror.BadRequest("A stack with this name exists inside the database. Cannot use external delete method", errors.New("A tag already exists with this name"))
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(endpointID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the endpoint associated to the stack inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find the endpoint associated to the stack inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the endpoint associated to the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find the endpoint associated to the stack inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access endpoint", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access endpoint", err)
|
||||
}
|
||||
|
||||
stack = &portainer.Stack{
|
||||
|
@ -179,7 +179,7 @@ func (handler *Handler) deleteExternalStack(r *http.Request, w http.ResponseWrit
|
|||
|
||||
err = handler.deleteStack(securityContext.UserID, stack, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to delete stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to delete stack", err)
|
||||
}
|
||||
|
||||
return response.Empty(w)
|
||||
|
|
|
@ -36,64 +36,64 @@ type stackFileResponse struct {
|
|||
func (handler *Handler) stackFile(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
if !securityContext.IsAdmin {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
if endpoint != nil {
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack {
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify user authorizations to validate stack access", err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Access denied to resource", httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stackFileContent, err := handler.FileService.GetFileContent(stack.ProjectPath, stack.EntryPoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve Compose file from disk", err}
|
||||
return httperror.InternalServerError("Unable to retrieve Compose file from disk", err)
|
||||
}
|
||||
|
||||
return response.JSON(w, &stackFileResponse{StackFileContent: string(stackFileContent)})
|
||||
|
|
|
@ -31,57 +31,57 @@ import (
|
|||
func (handler *Handler) stackInspect(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
if !securityContext.IsAdmin {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
if endpoint != nil {
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack {
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify user authorizations to validate stack access", err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Access denied to resource", httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
|
||||
if resourceControl != nil {
|
||||
|
|
|
@ -38,40 +38,40 @@ func (handler *Handler) stackList(w http.ResponseWriter, r *http.Request) *httpe
|
|||
var filters stackListOperationFilters
|
||||
err := request.RetrieveJSONQueryParameter(r, "filters", &filters, true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid query parameter: filters", err}
|
||||
return httperror.BadRequest("Invalid query parameter: filters", err)
|
||||
}
|
||||
|
||||
endpoints, err := handler.DataStore.Endpoint().Endpoints()
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve environments from database", err}
|
||||
return httperror.InternalServerError("Unable to retrieve environments from database", err)
|
||||
}
|
||||
|
||||
stacks, err := handler.DataStore.Stack().Stacks()
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve stacks from the database", err}
|
||||
return httperror.InternalServerError("Unable to retrieve stacks from the database", err)
|
||||
}
|
||||
stacks = filterStacks(stacks, &filters, endpoints)
|
||||
|
||||
resourceControls, err := handler.DataStore.ResourceControl().ResourceControls()
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve resource controls from the database", err}
|
||||
return httperror.InternalServerError("Unable to retrieve resource controls from the database", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
stacks = authorization.DecorateStacks(stacks, resourceControls)
|
||||
|
||||
if !securityContext.IsAdmin {
|
||||
if filters.IncludeOrphanedStacks {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access orphaned stacks", httperrors.ErrUnauthorized}
|
||||
return httperror.Forbidden("Permission denied to access orphaned stacks", httperrors.ErrUnauthorized)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve user information from the database", err}
|
||||
return httperror.InternalServerError("Unable to retrieve user information from the database", err)
|
||||
}
|
||||
|
||||
userTeamIDs := make([]portainer.TeamID, 0)
|
||||
|
|
|
@ -50,63 +50,63 @@ func (payload *stackMigratePayload) Validate(r *http.Request) error {
|
|||
func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
var payload stackMigratePayload
|
||||
err = request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.KubernetesStack {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Migrating a kubernetes stack is not supported", Err: err}
|
||||
return httperror.BadRequest("Migrating a kubernetes stack is not supported", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access endpoint", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access endpoint", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack migration is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
|
||||
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
||||
|
@ -114,7 +114,7 @@ func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *ht
|
|||
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
if endpointID != int(stack.EndpointID) {
|
||||
stack.EndpointID = portainer.EndpointID(endpointID)
|
||||
|
@ -122,9 +122,9 @@ func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *ht
|
|||
|
||||
targetEndpoint, err := handler.DataStore.Endpoint().Endpoint(portainer.EndpointID(payload.EndpointID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
stack.EndpointID = portainer.EndpointID(payload.EndpointID)
|
||||
|
@ -139,7 +139,7 @@ func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *ht
|
|||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(targetEndpoint, stack.Name, stack.ID, stack.SwarmID != "")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
|
||||
if !isUnique {
|
||||
|
@ -156,20 +156,20 @@ func (handler *Handler) stackMigrate(w http.ResponseWriter, r *http.Request) *ht
|
|||
stack.Name = oldName
|
||||
err = handler.deleteStack(securityContext.UserID, stack, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
stack.Name = newName
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack changes inside the database", err)
|
||||
}
|
||||
|
||||
if resourceControl != nil {
|
||||
resourceControl.ResourceID = stackutils.ResourceControlID(stack.EndpointID, stack.Name)
|
||||
err := handler.DataStore.ResourceControl().UpdateResourceControl(resourceControl.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to persist the resource control changes", err}
|
||||
return httperror.InternalServerError("Unable to persist the resource control changes", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,7 +196,7 @@ func (handler *Handler) migrateComposeStack(r *http.Request, stack *portainer.St
|
|||
|
||||
err := handler.deployComposeStack(config, false)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
@ -210,7 +210,7 @@ func (handler *Handler) migrateSwarmStack(r *http.Request, stack *portainer.Stac
|
|||
|
||||
err := handler.deploySwarmStack(config)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -33,49 +33,49 @@ import (
|
|||
func (handler *Handler) stackStart(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.KubernetesStack {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Starting a kubernetes stack is not supported", Err: err}
|
||||
return httperror.BadRequest("Starting a kubernetes stack is not supported", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find an endpoint with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find an endpoint with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access endpoint", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access endpoint", err)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, stack.Name, stack.ID, stack.SwarmID != "")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to check for name collision", Err: err}
|
||||
return httperror.InternalServerError("Unable to check for name collision", err)
|
||||
}
|
||||
if !isUnique {
|
||||
errorMessage := fmt.Sprintf("A stack with the name '%s' is already running", stack.Name)
|
||||
|
@ -84,19 +84,19 @@ func (handler *Handler) stackStart(w http.ResponseWriter, r *http.Request) *http
|
|||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
|
||||
if stack.Status == portainer.StackStatusActive {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Stack is already active", Err: errors.New("Stack is already active")}
|
||||
return httperror.BadRequest("Stack is already active", errors.New("Stack is already active"))
|
||||
}
|
||||
|
||||
if stack.AutoUpdate != nil && stack.AutoUpdate.Interval != "" {
|
||||
|
@ -112,13 +112,13 @@ func (handler *Handler) stackStart(w http.ResponseWriter, r *http.Request) *http
|
|||
|
||||
err = handler.startStack(stack, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to start stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to start stack", err)
|
||||
}
|
||||
|
||||
stack.Status = portainer.StackStatusActive
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to update stack status", Err: err}
|
||||
return httperror.InternalServerError("Unable to update stack status", err)
|
||||
}
|
||||
|
||||
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
|
||||
|
|
|
@ -31,61 +31,61 @@ import (
|
|||
func (handler *Handler) stackStop(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve info from request context", err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find a stack with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
if stack.Type == portainer.KubernetesStack {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Stopping a kubernetes stack is not supported", Err: err}
|
||||
return httperror.BadRequest("Stopping a kubernetes stack is not supported", err)
|
||||
}
|
||||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{http.StatusNotFound, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.NotFound("Unable to find an environment with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to find an environment with the specified identifier inside the database", err}
|
||||
return httperror.InternalServerError("Unable to find an environment with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Permission denied to access environment", err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to retrieve a resource control associated to the stack", err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to verify user authorizations to validate stack access", err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{http.StatusForbidden, "Access denied to resource", httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
if stack.Status == portainer.StackStatusInactive {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Stack is already inactive", errors.New("Stack is already inactive")}
|
||||
return httperror.BadRequest("Stack is already inactive", errors.New("Stack is already inactive"))
|
||||
}
|
||||
|
||||
// stop scheduler updates of the stack before stopping
|
||||
|
@ -96,13 +96,13 @@ func (handler *Handler) stackStop(w http.ResponseWriter, r *http.Request) *httpe
|
|||
|
||||
err = handler.stopStack(stack, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to stop stack", err}
|
||||
return httperror.InternalServerError("Unable to stop stack", err)
|
||||
}
|
||||
|
||||
stack.Status = portainer.StackStatusInactive
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusInternalServerError, "Unable to update stack status", err}
|
||||
return httperror.InternalServerError("Unable to update stack status", err)
|
||||
}
|
||||
|
||||
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
|
||||
|
|
|
@ -69,14 +69,14 @@ func (payload *updateSwarmStackPayload) Validate(r *http.Request) error {
|
|||
func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{http.StatusBadRequest, "Invalid stack identifier route variable", err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
||||
|
@ -84,7 +84,7 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt
|
|||
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
if endpointID != int(stack.EndpointID) {
|
||||
stack.EndpointID = portainer.EndpointID(endpointID)
|
||||
|
@ -92,19 +92,19 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find the environment associated to the stack inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find the environment associated to the stack inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access environment", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
//only check resource control when it is a DockerSwarmStack or a DockerComposeStack
|
||||
|
@ -112,25 +112,25 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack editing is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
updateError := handler.updateAndDeployStack(r, stack, endpoint)
|
||||
|
@ -140,7 +140,7 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Cannot find context user", Err: errors.Wrap(err, "failed to fetch the user")}
|
||||
return httperror.BadRequest("Cannot find context user", errors.Wrap(err, "failed to fetch the user"))
|
||||
}
|
||||
stack.UpdatedBy = user.Username
|
||||
stack.UpdateDate = time.Now().Unix()
|
||||
|
@ -148,7 +148,7 @@ func (handler *Handler) stackUpdate(w http.ResponseWriter, r *http.Request) *htt
|
|||
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack changes inside the database", err)
|
||||
}
|
||||
|
||||
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
|
||||
|
@ -167,7 +167,7 @@ func (handler *Handler) updateAndDeployStack(r *http.Request, stack *portainer.S
|
|||
} else if stack.Type == portainer.KubernetesStack {
|
||||
return handler.updateKubernetesStack(r, stack, endpoint)
|
||||
} else {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unsupported stack", Err: errors.Errorf("unsupported stack type: %v", stack.Type)}
|
||||
return httperror.InternalServerError("Unsupported stack", errors.Errorf("unsupported stack type: %v", stack.Type))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -184,7 +184,7 @@ func (handler *Handler) updateComposeStack(r *http.Request, stack *portainer.Sta
|
|||
var payload updateComposeStackPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack.Env = payload.Env
|
||||
|
@ -196,7 +196,7 @@ func (handler *Handler) updateComposeStack(r *http.Request, stack *portainer.Sta
|
|||
log.Printf("[WARN] [stack,update] [message: rollback stack file error] [err: %s]", rollbackErr)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist updated Compose file on disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist updated Compose file on disk", err)
|
||||
}
|
||||
|
||||
config, configErr := handler.createComposeDeployConfig(r, stack, endpoint)
|
||||
|
@ -214,7 +214,7 @@ func (handler *Handler) updateComposeStack(r *http.Request, stack *portainer.Sta
|
|||
log.Printf("[WARN] [stack,update] [message: rollback stack file error] [err: %s]", rollbackErr)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
handler.FileService.RemoveStackFileBackup(stackFolder, stack.EntryPoint)
|
||||
|
@ -235,7 +235,7 @@ func (handler *Handler) updateSwarmStack(r *http.Request, stack *portainer.Stack
|
|||
var payload updateSwarmStackPayload
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack.Env = payload.Env
|
||||
|
@ -247,7 +247,7 @@ func (handler *Handler) updateSwarmStack(r *http.Request, stack *portainer.Stack
|
|||
log.Printf("[WARN] [swarm,stack,update] [message: rollback stack file error] [err: %s]", rollbackErr)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist updated Compose file on disk", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist updated Compose file on disk", err)
|
||||
}
|
||||
|
||||
config, configErr := handler.createSwarmDeployConfig(r, stack, endpoint, payload.Prune)
|
||||
|
@ -265,7 +265,7 @@ func (handler *Handler) updateSwarmStack(r *http.Request, stack *portainer.Stack
|
|||
log.Printf("[WARN] [swarm,stack,update] [message: rollback stack file error] [err: %s]", rollbackErr)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
handler.FileService.RemoveStackFileBackup(stackFolder, stack.EntryPoint)
|
||||
|
|
|
@ -53,23 +53,23 @@ func (payload *stackGitUpdatePayload) Validate(r *http.Request) error {
|
|||
func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
var payload stackGitUpdatePayload
|
||||
err = request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if stack.GitConfig == nil {
|
||||
msg := "No Git config in the found stack"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: msg, Err: errors.New(msg)}
|
||||
return httperror.InternalServerError(msg, errors.New(msg))
|
||||
}
|
||||
|
||||
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
||||
|
@ -77,7 +77,7 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
|
|||
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
if endpointID != int(stack.EndpointID) {
|
||||
stack.EndpointID = portainer.EndpointID(endpointID)
|
||||
|
@ -85,48 +85,48 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
|
|||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find the environment associated to the stack inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find the environment associated to the stack inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access environment", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Cannot find context user", Err: errors.Wrap(err, "failed to fetch the user")}
|
||||
return httperror.BadRequest("Cannot find context user", errors.Wrap(err, "failed to fetch the user"))
|
||||
}
|
||||
|
||||
if stack.Type == portainer.DockerSwarmStack || stack.Type == portainer.DockerComposeStack {
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack editing is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
//stop the autoupdate job if there is any
|
||||
|
@ -158,7 +158,7 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
|
|||
}
|
||||
_, err = handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, stack.GitConfig.Authentication.Username, stack.GitConfig.Authentication.Password)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository", Err: err}
|
||||
return httperror.InternalServerError("Unable to fetch git repository", err)
|
||||
}
|
||||
} else {
|
||||
stack.GitConfig.Authentication = nil
|
||||
|
@ -176,7 +176,7 @@ func (handler *Handler) stackUpdateGit(w http.ResponseWriter, r *http.Request) *
|
|||
//save the updated stack to DB
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to persist the stack changes inside the database", err)
|
||||
}
|
||||
|
||||
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
|
||||
|
|
|
@ -52,18 +52,18 @@ func (payload *stackGitRedployPayload) Validate(r *http.Request) error {
|
|||
func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
stackID, err := request.RetrieveNumericRouteVariableValue(r, "id")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid stack identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid stack identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().Stack(portainer.StackID(stackID))
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find a stack with the specified identifier inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find a stack with the specified identifier inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find a stack with the specified identifier inside the database", err)
|
||||
}
|
||||
|
||||
if stack.GitConfig == nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Stack is not created from git", Err: err}
|
||||
return httperror.BadRequest("Stack is not created from git", err)
|
||||
}
|
||||
|
||||
// TODO: this is a work-around for stacks created with Portainer version >= 1.17.1
|
||||
|
@ -71,7 +71,7 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
// can use the optional EndpointID query parameter to associate a valid environment(endpoint) identifier to the stack.
|
||||
endpointID, err := request.RetrieveNumericQueryParameter(r, "endpointId", true)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid query parameter: endpointId", Err: err}
|
||||
return httperror.BadRequest("Invalid query parameter: endpointId", err)
|
||||
}
|
||||
if endpointID != int(stack.EndpointID) {
|
||||
stack.EndpointID = portainer.EndpointID(endpointID)
|
||||
|
@ -79,19 +79,19 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
endpoint, err := handler.DataStore.Endpoint().Endpoint(stack.EndpointID)
|
||||
if handler.DataStore.IsErrObjectNotFound(err) {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusNotFound, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.NotFound("Unable to find the environment associated to the stack inside the database", err)
|
||||
} else if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to find the environment associated to the stack inside the database", Err: err}
|
||||
return httperror.InternalServerError("Unable to find the environment associated to the stack inside the database", err)
|
||||
}
|
||||
|
||||
err = handler.requestBouncer.AuthorizedEndpointOperation(r, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Permission denied to access environment", Err: err}
|
||||
return httperror.Forbidden("Permission denied to access environment", err)
|
||||
}
|
||||
|
||||
securityContext, err := security.RetrieveRestrictedRequestContext(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve info from request context", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve info from request context", err)
|
||||
}
|
||||
|
||||
//only check resource control when it is a DockerSwarmStack or a DockerComposeStack
|
||||
|
@ -99,31 +99,31 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
resourceControl, err := handler.DataStore.ResourceControl().ResourceControlByResourceIDAndType(stackutils.ResourceControlID(stack.EndpointID, stack.Name), portainer.StackResourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to retrieve a resource control associated to the stack", Err: err}
|
||||
return httperror.InternalServerError("Unable to retrieve a resource control associated to the stack", err)
|
||||
}
|
||||
|
||||
access, err := handler.userCanAccessStack(securityContext, endpoint.ID, resourceControl)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack access", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack access", err)
|
||||
}
|
||||
if !access {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: "Access denied to resource", Err: httperrors.ErrResourceAccessDenied}
|
||||
return httperror.Forbidden("Access denied to resource", httperrors.ErrResourceAccessDenied)
|
||||
}
|
||||
}
|
||||
|
||||
canManage, err := handler.userCanManageStacks(securityContext, endpoint)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to verify user authorizations to validate stack deletion", Err: err}
|
||||
return httperror.InternalServerError("Unable to verify user authorizations to validate stack deletion", err)
|
||||
}
|
||||
if !canManage {
|
||||
errMsg := "Stack management is disabled for non-admin users"
|
||||
return &httperror.HandlerError{StatusCode: http.StatusForbidden, Message: errMsg, Err: errors.New(errMsg)}
|
||||
return httperror.Forbidden(errMsg, errors.New(errMsg))
|
||||
}
|
||||
|
||||
var payload stackGitRedployPayload
|
||||
err = request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack.GitConfig.ReferenceName = payload.RepositoryReferenceName
|
||||
|
@ -137,7 +137,7 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
backupProjectPath := fmt.Sprintf("%s-old", stack.ProjectPath)
|
||||
err = filesystem.MoveDirectory(stack.ProjectPath, backupProjectPath)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to move git repository directory", Err: err}
|
||||
return httperror.InternalServerError("Unable to move git repository directory", err)
|
||||
}
|
||||
|
||||
repositoryUsername := ""
|
||||
|
@ -157,7 +157,7 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
log.Printf("[WARN] [http,stacks,git] [error: %s] [message: failed restoring backup folder]", restoreError)
|
||||
}
|
||||
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to clone git repository", Err: err}
|
||||
return httperror.InternalServerError("Unable to clone git repository", err)
|
||||
}
|
||||
|
||||
defer func() {
|
||||
|
@ -174,13 +174,13 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
newHash, err := handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, repositoryUsername, repositoryPassword)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable get latest commit id", Err: errors.WithMessagef(err, "failed to fetch latest commit id of the stack %v", stack.ID)}
|
||||
return httperror.InternalServerError("Unable get latest commit id", errors.WithMessagef(err, "failed to fetch latest commit id of the stack %v", stack.ID))
|
||||
}
|
||||
stack.GitConfig.ConfigHash = newHash
|
||||
|
||||
user, err := handler.DataStore.User().User(securityContext.UserID)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Cannot find context user", Err: errors.Wrap(err, "failed to fetch the user")}
|
||||
return httperror.BadRequest("Cannot find context user", errors.Wrap(err, "failed to fetch the user"))
|
||||
}
|
||||
stack.UpdatedBy = user.Username
|
||||
stack.UpdateDate = time.Now().Unix()
|
||||
|
@ -188,7 +188,7 @@ func (handler *Handler) stackGitRedeploy(w http.ResponseWriter, r *http.Request)
|
|||
|
||||
err = handler.DataStore.Stack().UpdateStack(stack.ID, stack)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to persist the stack changes inside the database", Err: errors.Wrap(err, "failed to update the stack")}
|
||||
return httperror.InternalServerError("Unable to persist the stack changes inside the database", errors.Wrap(err, "failed to update the stack"))
|
||||
}
|
||||
|
||||
if stack.GitConfig != nil && stack.GitConfig.Authentication != nil && stack.GitConfig.Authentication.Password != "" {
|
||||
|
@ -212,7 +212,7 @@ func (handler *Handler) deployStack(r *http.Request, stack *portainer.Stack, end
|
|||
}
|
||||
|
||||
if err := handler.deploySwarmStack(config); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
case portainer.DockerComposeStack:
|
||||
|
@ -222,13 +222,13 @@ func (handler *Handler) deployStack(r *http.Request, stack *portainer.Stack, end
|
|||
}
|
||||
|
||||
if err := handler.deployComposeStack(config, true); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: err.Error(), Err: err}
|
||||
return httperror.InternalServerError(err.Error(), err)
|
||||
}
|
||||
|
||||
case portainer.KubernetesStack:
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Failed to retrieve user token data", Err: err}
|
||||
return httperror.BadRequest("Failed to retrieve user token data", err)
|
||||
}
|
||||
_, err = handler.deployKubernetesStack(tokenData.ID, endpoint, stack, k.KubeAppLabels{
|
||||
StackID: int(stack.ID),
|
||||
|
@ -237,11 +237,11 @@ func (handler *Handler) deployStack(r *http.Request, stack *portainer.Stack, end
|
|||
Kind: "git",
|
||||
})
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to redeploy Kubernetes stack", Err: errors.WithMessage(err, "failed to deploy kube application")}
|
||||
return httperror.InternalServerError("Unable to redeploy Kubernetes stack", errors.WithMessage(err, "failed to deploy kube application"))
|
||||
}
|
||||
|
||||
default:
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unsupported stack", Err: errors.Errorf("unsupported stack type: %v", stack.Type)}
|
||||
return httperror.InternalServerError("Unsupported stack", errors.Errorf("unsupported stack type: %v", stack.Type))
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -56,7 +56,7 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
|
|||
var payload kubernetesGitStackUpdatePayload
|
||||
|
||||
if err := request.DecodeAndValidateJSONPayload(r, &payload); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
stack.GitConfig.ReferenceName = payload.RepositoryReferenceName
|
||||
|
@ -73,7 +73,7 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
|
|||
}
|
||||
_, err := handler.GitService.LatestCommitID(stack.GitConfig.URL, stack.GitConfig.ReferenceName, stack.GitConfig.Authentication.Username, stack.GitConfig.Authentication.Password)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to fetch git repository", Err: err}
|
||||
return httperror.InternalServerError("Unable to fetch git repository", err)
|
||||
}
|
||||
} else {
|
||||
stack.GitConfig.Authentication = nil
|
||||
|
@ -94,19 +94,19 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
|
|||
|
||||
err := request.DecodeAndValidateJSONPayload(r, &payload)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid request payload", Err: err}
|
||||
return httperror.BadRequest("Invalid request payload", err)
|
||||
}
|
||||
|
||||
tokenData, err := security.RetrieveTokenData(r)
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Failed to retrieve user token data", Err: err}
|
||||
return httperror.BadRequest("Failed to retrieve user token data", err)
|
||||
}
|
||||
|
||||
tempFileDir, _ := ioutil.TempDir("", "kub_file_content")
|
||||
defer os.RemoveAll(tempFileDir)
|
||||
|
||||
if err := filesystem.WriteToFile(filesystem.JoinPaths(tempFileDir, stack.EntryPoint), []byte(payload.StackFileContent)); err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Failed to persist deployment file in a temp directory", Err: err}
|
||||
return httperror.InternalServerError("Failed to persist deployment file in a temp directory", err)
|
||||
}
|
||||
|
||||
//use temp dir as the stack project path for deployment
|
||||
|
@ -121,7 +121,7 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
|
|||
})
|
||||
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Unable to deploy Kubernetes stack via file content", Err: err}
|
||||
return httperror.InternalServerError("Unable to deploy Kubernetes stack via file content", err)
|
||||
}
|
||||
|
||||
stackFolder := strconv.Itoa(int(stack.ID))
|
||||
|
@ -136,7 +136,7 @@ func (handler *Handler) updateKubernetesStack(r *http.Request, stack *portainer.
|
|||
fileType = "Compose"
|
||||
}
|
||||
errMsg := fmt.Sprintf("Unable to persist Kubernetes %s file on disk", fileType)
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: errMsg, Err: err}
|
||||
return httperror.InternalServerError(errMsg, err)
|
||||
}
|
||||
stack.ProjectPath = projectPath
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import (
|
|||
func (handler *Handler) webhookInvoke(w http.ResponseWriter, r *http.Request) *httperror.HandlerError {
|
||||
webhookID, err := retrieveUUIDRouteVariableValue(r, "webhookID")
|
||||
if err != nil {
|
||||
return &httperror.HandlerError{StatusCode: http.StatusBadRequest, Message: "Invalid webhook identifier route variable", Err: err}
|
||||
return httperror.BadRequest("Invalid webhook identifier route variable", err)
|
||||
}
|
||||
|
||||
stack, err := handler.DataStore.Stack().StackByWebhookID(webhookID.String())
|
||||
|
@ -44,7 +44,7 @@ func (handler *Handler) webhookInvoke(w http.ResponseWriter, r *http.Request) *h
|
|||
return &httperror.HandlerError{StatusCode: http.StatusConflict, Message: "Autoupdate for the stack isn't available", Err: err}
|
||||
}
|
||||
logrus.WithError(err).Error("failed to update the stack")
|
||||
return &httperror.HandlerError{StatusCode: http.StatusInternalServerError, Message: "Failed to update the stack", Err: err}
|
||||
return httperror.InternalServerError("Failed to update the stack", err)
|
||||
}
|
||||
|
||||
return response.Empty(w)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue