diff --git a/api/kubernetes/cli/role.go b/api/kubernetes/cli/role.go index d75afa3c1..7c22f1b32 100644 --- a/api/kubernetes/cli/role.go +++ b/api/kubernetes/cli/role.go @@ -18,15 +18,10 @@ func getPortainerUserDefaultPolicies() []rbacv1.PolicyRule { Resources: []string{"storageclasses"}, APIGroups: []string{"storage.k8s.io"}, }, - { - Verbs: []string{"list"}, - Resources: []string{"ingresses"}, - APIGroups: []string{"networking.k8s.io"}, - }, } } -func (kcl *KubeClient) createPortainerUserClusterRole() error { +func (kcl *KubeClient) upsertPortainerK8sClusterRoles() error { clusterRole := &rbacv1.ClusterRole{ ObjectMeta: metav1.ObjectMeta{ Name: portainerUserCRName, @@ -35,8 +30,13 @@ func (kcl *KubeClient) createPortainerUserClusterRole() error { } _, err := kcl.cli.RbacV1().ClusterRoles().Create(clusterRole) - if err != nil && !k8serrors.IsAlreadyExists(err) { - return err + if err != nil { + if k8serrors.IsAlreadyExists(err) { + _, err = kcl.cli.RbacV1().ClusterRoles().Update(clusterRole) + } + if err != nil { + return err + } } return nil diff --git a/api/kubernetes/cli/service_account.go b/api/kubernetes/cli/service_account.go index ddb852b3c..95dc4e897 100644 --- a/api/kubernetes/cli/service_account.go +++ b/api/kubernetes/cli/service_account.go @@ -63,7 +63,7 @@ func (kcl *KubeClient) SetupUserServiceAccount(userID int, teamIDs []int, restri } func (kcl *KubeClient) ensureRequiredResourcesExist() error { - return kcl.createPortainerUserClusterRole() + return kcl.upsertPortainerK8sClusterRoles() } func (kcl *KubeClient) createUserServiceAccount(namespace, serviceAccountName string) error { diff --git a/app/kubernetes/views/applications/create/createApplication.html b/app/kubernetes/views/applications/create/createApplication.html index 2a432fcf1..0a84c5e13 100644 --- a/app/kubernetes/views/applications/create/createApplication.html +++ b/app/kubernetes/views/applications/create/createApplication.html @@ -1347,7 +1347,7 @@ class="form-control" name="ingress_class_{{ $index }}" ng-model="publishedPort.IngressName" - ng-options="ingress.Name as ingress.Name for ingress in ctrl.filteredIngresses" + ng-options="ingress.Name as ingress.Name for ingress in ctrl.ingresses" ng-required="!publishedPort.NeedsDeletion" ng-change="ctrl.onChangePortMappingIngress($index)" ng-disabled="ctrl.disableLoadBalancerEdit() || ctrl.isEditAndNotNewPublishedPort($index)" diff --git a/app/kubernetes/views/applications/create/createApplicationController.js b/app/kubernetes/views/applications/create/createApplicationController.js index 9a4ff4e38..31ca80f16 100644 --- a/app/kubernetes/views/applications/create/createApplicationController.js +++ b/app/kubernetes/views/applications/create/createApplicationController.js @@ -371,7 +371,7 @@ class KubernetesCreateApplicationController { /* #region PUBLISHED PORTS UI MANAGEMENT */ addPublishedPort() { const p = new KubernetesApplicationPublishedPortFormValue(); - const ingresses = this.filteredIngresses; + const ingresses = this.ingresses; p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined; p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined; p.IngressHosts = ingresses && ingresses.length ? ingresses[0].Hosts : undefined; @@ -382,7 +382,7 @@ class KubernetesCreateApplicationController { } resetPublishedPorts() { - const ingresses = this.filteredIngresses; + const ingresses = this.ingresses; _.forEach(this.formValues.PublishedPorts, (p) => { p.IngressName = ingresses && ingresses.length ? ingresses[0].Name : undefined; p.IngressHost = ingresses && ingresses.length ? ingresses[0].Hosts[0] : undefined; @@ -441,7 +441,7 @@ class KubernetesCreateApplicationController { onChangePortMappingIngress(index) { const publishedPort = this.formValues.PublishedPorts[index]; - const ingress = _.find(this.filteredIngresses, { Name: publishedPort.IngressName }); + const ingress = _.find(this.ingresses, { Name: publishedPort.IngressName }); publishedPort.IngressHosts = ingress.Hosts; this.ingressHostnames = ingress.Hosts; publishedPort.IngressHost = this.ingressHostnames.length ? this.ingressHostnames[0] : []; @@ -650,7 +650,7 @@ class KubernetesCreateApplicationController { } publishViaIngressEnabled() { - return this.filteredIngresses.length; + return this.ingresses.length; } isEditAndNoChangesMade() { @@ -871,16 +871,22 @@ class KubernetesCreateApplicationController { } refreshIngresses(namespace) { - this.filteredIngresses = _.filter(this.ingresses, { Namespace: namespace }); - this.ingressHostnames = this.filteredIngresses.length ? this.filteredIngresses[0].Hosts : []; - if (!this.publishViaIngressEnabled()) { - if (this.savedFormValues) { - this.formValues.PublishingType = this.savedFormValues.PublishingType; - } else { - this.formValues.PublishingType = this.ApplicationPublishingTypes.INTERNAL; + return this.$async(async () => { + try { + this.ingresses = await this.KubernetesIngressService.get(namespace); + this.ingressHostnames = this.ingresses.length ? this.ingresses[0].Hosts : []; + if (!this.publishViaIngressEnabled()) { + if (this.savedFormValues) { + this.formValues.PublishingType = this.savedFormValues.PublishingType; + } else { + this.formValues.PublishingType = this.ApplicationPublishingTypes.INTERNAL; + } + } + this.formValues.OriginalIngresses = this.ingresses; + } catch (err) { + this.Notifications.error('Failure', err, 'Unable to retrieve ingresses'); } - } - this.formValues.OriginalIngresses = this.filteredIngresses; + }); } refreshNamespaceData(namespace) { @@ -990,13 +996,11 @@ class KubernetesCreateApplicationController { this.state.useLoadBalancer = this.endpoint.Kubernetes.Configuration.UseLoadBalancer; this.state.useServerMetrics = this.endpoint.Kubernetes.Configuration.UseServerMetrics; - const [resourcePools, nodes, ingresses, nodesLimits] = await Promise.all([ + const [resourcePools, nodes, nodesLimits] = await Promise.all([ this.KubernetesResourcePoolService.get(), this.KubernetesNodeService.get(), - this.KubernetesIngressService.get(), this.KubernetesNodesLimitsService.get(), ]); - this.ingresses = ingresses; this.nodesLimits = nodesLimits; this.resourcePools = _.filter(resourcePools, (resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name)); @@ -1023,9 +1027,9 @@ class KubernetesCreateApplicationController { this.configurations, this.persistentVolumeClaims, this.nodesLabels, - this.filteredIngresses + this.ingresses ); - this.formValues.OriginalIngresses = this.filteredIngresses; + this.formValues.OriginalIngresses = this.ingresses; this.formValues.ImageModel = await this.parseImageConfiguration(this.formValues.ImageModel); this.savedFormValues = angular.copy(this.formValues); delete this.formValues.ApplicationType; @@ -1042,7 +1046,6 @@ class KubernetesCreateApplicationController { await this.refreshNamespaceData(namespace); } else { this.formValues.AutoScaler = KubernetesApplicationHelper.generateAutoScalerFormValueFromHorizontalPodAutoScaler(null, this.formValues.ReplicaCount); - this.formValues.OriginalIngressClasses = angular.copy(this.ingresses); } if (this.state.isEdit) { diff --git a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js index a38e9ac78..a2f94db49 100644 --- a/app/kubernetes/views/resource-pools/edit/resourcePoolController.js +++ b/app/kubernetes/views/resource-pools/edit/resourcePoolController.js @@ -293,7 +293,7 @@ class KubernetesResourcePoolController { this.state.ingressesLoading = true; try { const namespace = this.pool.Namespace.Name; - this.allIngresses = await this.KubernetesIngressService.get(); + this.allIngresses = await this.KubernetesIngressService.get(this.state.hasWriteAuthorization ? '' : namespace); this.ingresses = _.filter(this.allIngresses, { Namespace: namespace }); _.forEach(this.ingresses, (ing) => { ing.Namespace = namespace;