1
0
Fork 0
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:
andres-portainer 2022-09-14 20:42:39 -03:00 committed by GitHub
parent 7accdf704c
commit 9ef5636718
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
157 changed files with 1123 additions and 1147 deletions

View file

@ -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)
}
}

View file

@ -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)

View file

@ -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

View file

@ -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)

View file

@ -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

View file

@ -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

View file

@ -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)

View file

@ -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)})

View file

@ -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 {

View file

@ -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)

View file

@ -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

View file

@ -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 != "" {

View file

@ -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 != "" {

View file

@ -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)

View file

@ -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 != "" {

View file

@ -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

View file

@ -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

View file

@ -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)