From 86335a4357b307cf19dca8951a426bc0b574f16c Mon Sep 17 00:00:00 2001 From: cong meng Date: Thu, 18 Feb 2021 14:52:59 +1300 Subject: [PATCH] fix(ingress): remove associated ingresses while removing ingress controller (#4722) (#4780) Co-authored-by: Simon Meng --- app/constants.js | 1 + app/kubernetes/helpers/namespaceHelper.js | 7 ++- .../views/configure/configureController.js | 45 ++++++++++++++++++- 3 files changed, 50 insertions(+), 3 deletions(-) diff --git a/app/constants.js b/app/constants.js index 3dba966dc..547c7d518 100644 --- a/app/constants.js +++ b/app/constants.js @@ -27,4 +27,5 @@ angular .constant('APPLICATION_CACHE_VALIDITY', 3600) .constant('CONSOLE_COMMANDS_LABEL_PREFIX', 'io.portainer.commands.') .constant('PREDEFINED_NETWORKS', ['host', 'bridge', 'none']) + .constant('KUBERNETES_DEFAULT_NAMESPACE', 'default') .constant('KUBERNETES_SYSTEM_NAMESPACES', ['kube-system', 'kube-public', 'kube-node-lease', 'portainer']); diff --git a/app/kubernetes/helpers/namespaceHelper.js b/app/kubernetes/helpers/namespaceHelper.js index a3878ba08..f41f393c0 100644 --- a/app/kubernetes/helpers/namespaceHelper.js +++ b/app/kubernetes/helpers/namespaceHelper.js @@ -3,13 +3,18 @@ import angular from 'angular'; class KubernetesNamespaceHelper { /* @ngInject */ - constructor(KUBERNETES_SYSTEM_NAMESPACES) { + constructor(KUBERNETES_SYSTEM_NAMESPACES, KUBERNETES_DEFAULT_NAMESPACE) { this.KUBERNETES_SYSTEM_NAMESPACES = KUBERNETES_SYSTEM_NAMESPACES; + this.KUBERNETES_DEFAULT_NAMESPACE = KUBERNETES_DEFAULT_NAMESPACE; } isSystemNamespace(namespace) { return _.includes(this.KUBERNETES_SYSTEM_NAMESPACES, namespace); } + + isDefaultNamespace(namespace) { + return namespace === this.KUBERNETES_DEFAULT_NAMESPACE; + } } export default KubernetesNamespaceHelper; diff --git a/app/kubernetes/views/configure/configureController.js b/app/kubernetes/views/configure/configureController.js index 2e7216c26..b4b296e99 100644 --- a/app/kubernetes/views/configure/configureController.js +++ b/app/kubernetes/views/configure/configureController.js @@ -9,7 +9,19 @@ import { KubernetesIngressClassTypes } from 'Kubernetes/ingress/constants'; class KubernetesConfigureController { /* #region CONSTRUCTOR */ /* @ngInject */ - constructor($async, $state, $stateParams, Notifications, KubernetesStorageService, EndpointService, EndpointProvider, ModalService) { + constructor( + $async, + $state, + $stateParams, + Notifications, + KubernetesStorageService, + EndpointService, + EndpointProvider, + ModalService, + KubernetesNamespaceHelper, + KubernetesResourcePoolService, + KubernetesIngressService + ) { this.$async = $async; this.$state = $state; this.$stateParams = $stateParams; @@ -18,6 +30,9 @@ class KubernetesConfigureController { this.EndpointService = EndpointService; this.EndpointProvider = EndpointProvider; this.ModalService = ModalService; + this.KubernetesNamespaceHelper = KubernetesNamespaceHelper; + this.KubernetesResourcePoolService = KubernetesResourcePoolService; + this.KubernetesIngressService = KubernetesIngressService; this.IngressClassTypes = KubernetesIngressClassTypes; @@ -115,11 +130,37 @@ class KubernetesConfigureController { return [storageClasses, ingressClasses]; } + async removeIngressesAcrossNamespaces() { + const promises = []; + const ingressesToDel = _.filter(this.formValues.IngressClasses, { NeedsDeletion: true }); + const allResourcePools = await this.KubernetesResourcePoolService.get(); + const resourcePools = _.filter( + allResourcePools, + (resourcePool) => + !this.KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name) && !this.KubernetesNamespaceHelper.isDefaultNamespace(resourcePool.Namespace.Name) + ); + + ingressesToDel.forEach((ingress) => { + resourcePools.forEach((resourcePool) => { + promises.push(this.KubernetesIngressService.delete({ IngressClass: ingress, Namespace: resourcePool.Namespace.Name })); + }); + }); + + const responses = await Promise.allSettled(promises); + responses.forEach((respons) => { + if (respons.status == 'rejected' && respons.reason.err.status != 404) { + throw respons.reason; + } + }); + } + async configureAsync() { try { this.state.actionInProgress = true; const [storageClasses, ingressClasses] = this.transformFormValues(); + await this.removeIngressesAcrossNamespaces(); + this.assignFormValuesToEndpoint(this.endpoint, storageClasses, ingressClasses); await this.EndpointService.updateEndpoint(this.endpoint.Id, this.endpoint); @@ -150,7 +191,7 @@ class KubernetesConfigureController { const toDel = _.filter(this.formValues.IngressClasses, { NeedsDeletion: true }); if (toDel.length) { this.ModalService.confirmUpdate( - `Removing ingress controllers will make them unavailable for future use.
Existing resources linked to these ingress controllers will continue to live in cluster but you will not be able to remove them from Portainer.

Do you wish to continue?`, + `Removing ingress controllers may cause applications to be unaccessible. All ingress configurations from affected applications will be removed.

Do you wish to continue?`, (confirmed) => { if (confirmed) { return this.$async(this.configureAsync);