From 79958b02548ee8a6baafa67d1a89a54cb548f0c1 Mon Sep 17 00:00:00 2001 From: fhanportainer <79428273+fhanportainer@users.noreply.github.com> Date: Thu, 30 Sep 2021 09:49:30 +1300 Subject: [PATCH] fix(stack): remove stack when no app. (#5769) * fix(stack): remove stack when no app. * support compose format in delete Co-authored-by: ArrisLee --- api/http/handler/stacks/stack_delete.go | 39 ++++++++++++++++++- .../applications/applicationsController.js | 8 ++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/api/http/handler/stacks/stack_delete.go b/api/http/handler/stacks/stack_delete.go index ee36da7d4..799f6f612 100644 --- a/api/http/handler/stacks/stack_delete.go +++ b/api/http/handler/stacks/stack_delete.go @@ -3,7 +3,10 @@ package stacks import ( "context" "fmt" + "io/ioutil" "net/http" + "os" + "path" "strconv" "github.com/pkg/errors" @@ -12,6 +15,7 @@ import ( "github.com/portainer/libhttp/response" portainer "github.com/portainer/portainer/api" bolterrors "github.com/portainer/portainer/api/bolt/errors" + "github.com/portainer/portainer/api/filesystem" httperrors "github.com/portainer/portainer/api/http/errors" "github.com/portainer/portainer/api/http/security" "github.com/portainer/portainer/api/internal/stackutils" @@ -181,7 +185,40 @@ func (handler *Handler) deleteStack(userID portainer.UserID, stack *portainer.St return handler.ComposeStackManager.Down(context.TODO(), stack, endpoint) } if stack.Type == portainer.KubernetesStack { - out, err := handler.KubernetesDeployer.Remove(userID, endpoint, stackutils.GetStackFilePaths(stack), stack.Namespace) + var manifestFiles []string + + //if it is a compose format kub stack, create a temp dir and convert the manifest files into it + //then process the remove operation + if stack.IsComposeFormat { + fileNames := append([]string{stack.EntryPoint}, stack.AdditionalFiles...) + tmpDir, err := ioutil.TempDir("", "kub_delete") + if err != nil { + return errors.Wrap(err, "failed to create temp directory for deleting kub stack") + } + defer os.RemoveAll(tmpDir) + + for _, fileName := range fileNames { + manifestFilePath := path.Join(tmpDir, fileName) + manifestContent, err := ioutil.ReadFile(path.Join(stack.ProjectPath, fileName)) + if err != nil { + return errors.Wrap(err, "failed to read manifest file") + } + + manifestContent, err = handler.KubernetesDeployer.ConvertCompose(manifestContent) + if err != nil { + return errors.Wrap(err, "failed to convert docker compose file to a kube manifest") + } + + err = filesystem.WriteToFile(manifestFilePath, []byte(manifestContent)) + if err != nil { + return errors.Wrap(err, "failed to create temp manifest file") + } + manifestFiles = append(manifestFiles, manifestFilePath) + } + } else { + manifestFiles = stackutils.GetStackFilePaths(stack) + } + out, err := handler.KubernetesDeployer.Remove(userID, endpoint, manifestFiles, stack.Namespace) return errors.WithMessagef(err, "failed to remove kubernetes resources: %q", out) } return fmt.Errorf("unsupported stack type: %v", stack.Type) diff --git a/app/kubernetes/views/applications/applicationsController.js b/app/kubernetes/views/applications/applicationsController.js index f32d2fe58..3825fb1ba 100644 --- a/app/kubernetes/views/applications/applicationsController.js +++ b/app/kubernetes/views/applications/applicationsController.js @@ -81,6 +81,14 @@ class KubernetesApplicationsController { await this.HelmService.uninstall(this.endpoint.Id, application); } else { await this.KubernetesApplicationService.delete(application); + // Update applications in stack + const stack = this.state.stacks.find((x) => x.Name === application.StackName); + const index = stack.Applications.indexOf(application); + stack.Applications.splice(index, 1); + // remove stack if no app left in the stack + if (stack.Applications.length === 0 && application.StackId) { + await this.StackService.remove({ Id: application.StackId }, false, this.endpoint.Id); + } } this.Notifications.success('Application successfully removed', application.Name); const index = this.state.applications.indexOf(application);