chore(stackbuilders): simplify the code BE-12800 (#2230)

This commit is contained in:
andres-portainer
2026-04-09 17:45:24 -03:00
committed by GitHub
parent 635c49d04d
commit 68453ebcb8
25 changed files with 512 additions and 1401 deletions
+47 -72
View File
@@ -46,7 +46,7 @@ func (payload *composeStackFromFileContentPayload) Validate(r *http.Request) err
func createStackPayloadFromComposeFileContentPayload(name string, fileContent string, env []portainer.Pair, fromAppTemplate bool) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
StackFileContent: fileContent,
StackFileContent: []byte(fileContent),
Env: env,
FromAppTemplate: fromAppTemplate,
}
@@ -89,6 +89,38 @@ func (handler *Handler) checkAndCleanStackDupFromSwarm(w http.ResponseWriter, r
return nil
}
func (handler *Handler) ensureUniqueComposeStackName(w http.ResponseWriter, r *http.Request, endpoint *portainer.Endpoint, userID portainer.UserID, name string) *httperror.HandlerError {
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, name, 0, false)
if err != nil {
return httperror.InternalServerError("Unable to check for name collision", err)
} else if isUnique {
return nil
}
stacks, err := handler.DataStore.Stack().StacksByName(name)
if err != nil {
return httperror.InternalServerError("Unable to retrieve the stack from the database", err)
}
for _, stack := range stacks {
if stack.EndpointID != endpoint.ID {
continue
}
if stack.Type != portainer.DockerComposeStack {
if err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack); err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
continue
}
return stackExistsError(name)
}
return nil
}
// @id StackCreateDockerStandaloneString
// @summary Deploy a new compose stack from a text
// @description Deploy a new stack into a Docker environment specified via the environment identifier.
@@ -113,26 +145,8 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
payload.Name = handler.ComposeStackManager.NormalizeStackName(payload.Name)
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
if err != nil {
return httperror.InternalServerError("Unable to check for name collision", err)
}
if !isUnique {
stacks, err := handler.DataStore.Stack().StacksByName(payload.Name)
if err != nil {
return stackExistsError(payload.Name)
}
for _, stack := range stacks {
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
if err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
} else {
return stackExistsError(payload.Name)
}
}
if err := handler.ensureUniqueComposeStackName(w, r, endpoint, userID, payload.Name); err != nil {
return err
}
securityContext, err := security.RetrieveRestrictedRequestContext(r)
@@ -142,13 +156,12 @@ func (handler *Handler) createComposeStackFromFileContent(w http.ResponseWriter,
stackPayload := createStackPayloadFromComposeFileContentPayload(payload.Name, payload.StackFileContent, payload.Env, payload.FromAppTemplate)
composeStackBuilder := stackbuilders.CreateComposeStackFileContentBuilder(securityContext,
composeStackBuilder := stackbuilders.CreateComposeStackFileBuilder(securityContext,
handler.DataStore,
handler.FileService,
handler.StackDeployer)
stackBuilderDirector := stackbuilders.NewStackBuilderDirector(handler.DataStore, composeStackBuilder)
stack, httpErr := stackBuilderDirector.Build(context.TODO(), &stackPayload, endpoint)
stack, httpErr := stackbuilders.Build(context.TODO(), handler.DataStore, composeStackBuilder, &stackPayload, endpoint)
if httpErr != nil {
return httpErr
}
@@ -244,26 +257,8 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
payload.ComposeFile = filesystem.ComposeFileDefaultName
}
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
if err != nil {
return httperror.InternalServerError("Unable to check for name collision", err)
}
if !isUnique {
stacks, err := handler.DataStore.Stack().StacksByName(payload.Name)
if err != nil {
return stackExistsError(payload.Name)
}
for _, stack := range stacks {
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
if err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
} else {
return stackExistsError(payload.Name)
}
}
if err := handler.ensureUniqueComposeStackName(w, r, endpoint, userID, payload.Name); err != nil {
return err
}
//make sure the webhook ID is unique
@@ -303,8 +298,7 @@ func (handler *Handler) createComposeStackFromGitRepository(w http.ResponseWrite
handler.Scheduler,
handler.StackDeployer)
stackBuilderDirector := stackbuilders.NewStackBuilderDirector(handler.DataStore, composeStackBuilder)
stack, httpErr := stackBuilderDirector.Build(context.TODO(), &stackPayload, endpoint)
stack, httpErr := stackbuilders.Build(context.TODO(), handler.DataStore, composeStackBuilder, &stackPayload, endpoint)
if httpErr != nil {
return httpErr
}
@@ -320,9 +314,9 @@ type composeStackFromFileUploadPayload struct {
func createStackPayloadFromComposeFileUploadPayload(name string, fileContentBytes []byte, env []portainer.Pair) stackbuilders.StackPayload {
return stackbuilders.StackPayload{
Name: name,
StackFileContentBytes: fileContentBytes,
Env: env,
Name: name,
StackFileContent: fileContentBytes,
Env: env,
}
}
@@ -374,26 +368,8 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
payload.Name = handler.ComposeStackManager.NormalizeStackName(payload.Name)
isUnique, err := handler.checkUniqueStackNameInDocker(endpoint, payload.Name, 0, false)
if err != nil {
return httperror.InternalServerError("Unable to check for name collision", err)
}
if !isUnique {
stacks, err := handler.DataStore.Stack().StacksByName(payload.Name)
if err != nil {
return stackExistsError(payload.Name)
}
for _, stack := range stacks {
if stack.Type != portainer.DockerComposeStack && stack.EndpointID == endpoint.ID {
err := handler.checkAndCleanStackDupFromSwarm(w, r, endpoint, userID, &stack)
if err != nil {
return httperror.BadRequest("Invalid request payload", err)
}
} else {
return stackExistsError(payload.Name)
}
}
if err := handler.ensureUniqueComposeStackName(w, r, endpoint, userID, payload.Name); err != nil {
return err
}
securityContext, err := security.RetrieveRestrictedRequestContext(r)
@@ -403,13 +379,12 @@ func (handler *Handler) createComposeStackFromFileUpload(w http.ResponseWriter,
stackPayload := createStackPayloadFromComposeFileUploadPayload(payload.Name, payload.StackFileContent, payload.Env)
composeStackBuilder := stackbuilders.CreateComposeStackFileUploadBuilder(securityContext,
composeStackBuilder := stackbuilders.CreateComposeStackFileBuilder(securityContext,
handler.DataStore,
handler.FileService,
handler.StackDeployer)
stackBuilderDirector := stackbuilders.NewStackBuilderDirector(handler.DataStore, composeStackBuilder)
stack, httpErr := stackBuilderDirector.Build(context.TODO(), &stackPayload, endpoint)
stack, httpErr := stackbuilders.Build(context.TODO(), handler.DataStore, composeStackBuilder, &stackPayload, endpoint)
if httpErr != nil {
return httpErr
}