diff --git a/app/kubernetes/converters/configMap.js b/app/kubernetes/converters/configMap.js index 820765519..262fb65cf 100644 --- a/app/kubernetes/converters/configMap.js +++ b/app/kubernetes/converters/configMap.js @@ -1,10 +1,32 @@ import _ from 'lodash-es'; -import { KubernetesConfigMap } from 'Kubernetes/models/config-map/models'; +import { KubernetesConfigMap, KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models'; import { KubernetesConfigMapCreatePayload, KubernetesConfigMapUpdatePayload } from 'Kubernetes/models/config-map/payloads'; import { KubernetesPortainerConfigurationOwnerLabel } from 'Kubernetes/models/configuration/models'; import { KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues'; class KubernetesConfigMapConverter { + static apiToPortainerAccessConfigMap(data) { + const res = new KubernetesPortainerAccessConfigMap(); + res.Id = data.metadata.uid; + res.Data = data.data; + return res; + } + + static createAccessPayload(data) { + const res = new KubernetesConfigMapCreatePayload(); + _.unset(res, 'binaryData'); + res.metadata.name = data.Name; + res.metadata.namespace = data.Namespace; + res.data = data.Data; + return res; + } + + static updateAccessPayload(data) { + const res = KubernetesConfigMapConverter.createAccessPayload(data); + res.metadata.uid = data.Id; + return res; + } + /** * API ConfigMap to front ConfigMap */ diff --git a/app/kubernetes/models/config-map/models.js b/app/kubernetes/models/config-map/models.js index 151a03764..0ff339385 100644 --- a/app/kubernetes/models/config-map/models.js +++ b/app/kubernetes/models/config-map/models.js @@ -2,6 +2,15 @@ export const KubernetesPortainerConfigMapNamespace = 'portainer'; export const KubernetesPortainerConfigMapConfigName = 'portainer-config'; export const KubernetesPortainerConfigMapAccessKey = 'NamespaceAccessPolicies'; +export function KubernetesPortainerAccessConfigMap() { + return { + Id: 0, + Name: KubernetesPortainerConfigMapConfigName, + Namespace: KubernetesPortainerConfigMapNamespace, + Data: {}, + }; +} + /** * ConfigMap Model */ diff --git a/app/kubernetes/services/configMapService.js b/app/kubernetes/services/configMapService.js index b8ebbe38b..8e7cee884 100644 --- a/app/kubernetes/services/configMapService.js +++ b/app/kubernetes/services/configMapService.js @@ -3,6 +3,7 @@ import _ from 'lodash-es'; import PortainerError from 'Portainer/error'; import KubernetesConfigMapConverter from 'Kubernetes/converters/configMap'; import { KubernetesCommonParams } from 'Kubernetes/models/common/params'; +import { KubernetesPortainerAccessConfigMap } from 'Kubernetes/models/config-map/models'; class KubernetesConfigMapService { /* @ngInject */ @@ -17,6 +18,54 @@ class KubernetesConfigMapService { this.deleteAsync = this.deleteAsync.bind(this); } + getAccess(namespace, name) { + return this.$async(async () => { + try { + const params = new KubernetesCommonParams(); + params.id = name; + const raw = await this.KubernetesConfigMaps(namespace).get(params).$promise; + return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(raw); + } catch (err) { + if (err.status === 404) { + return new KubernetesPortainerAccessConfigMap(); + } + throw new PortainerError('Unable to retrieve Portainer accesses', err); + } + }); + } + + createAccess(config) { + return this.$async(async () => { + try { + const payload = KubernetesConfigMapConverter.createAccessPayload(config); + const params = {}; + const namespace = payload.metadata.namespace; + const data = await this.KubernetesConfigMaps(namespace).create(params, payload).$promise; + return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data); + } catch (err) { + throw new PortainerError('Unable to create Portainer accesses', err); + } + }); + } + + updateAccess(config) { + return this.$async(async () => { + try { + if (!config.Id) { + return await this.createAccess(config); + } + const payload = KubernetesConfigMapConverter.updateAccessPayload(config); + const params = new KubernetesCommonParams(); + params.id = payload.metadata.name; + const namespace = payload.metadata.namespace; + const data = await this.KubernetesConfigMaps(namespace).update(params, payload).$promise; + return KubernetesConfigMapConverter.apiToPortainerAccessConfigMap(data); + } catch (err) { + throw new PortainerError('Unable to update Portainer accesses', err); + } + }); + } + /** * GET */ @@ -29,12 +78,12 @@ class KubernetesConfigMapService { this.KubernetesConfigMaps(namespace).getYaml(params).$promise, ]); - if (_.get(rawPromise, 'reason.status') == 404 && _.get(yamlPromise, 'reason.status') == 404) { + if (_.get(rawPromise, 'reason.status') === 404 && _.get(yamlPromise, 'reason.status') === 404) { return KubernetesConfigMapConverter.defaultConfigMap(namespace, name); } - // Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get - // an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we + // Saving binary data to 'data' field in configMap Object is not allowed by kubernetes and getYaml() may get + // an error. We should keep binary data to 'binaryData' field instead of 'data'. Before that, we // use response from get() and ignore 500 error as a workaround. if (rawPromise.value) { return KubernetesConfigMapConverter.apiToConfigMap(rawPromise.value, yamlPromise.value); diff --git a/app/kubernetes/views/resource-pools/access/resourcePoolAccessController.js b/app/kubernetes/views/resource-pools/access/resourcePoolAccessController.js index 1c458a339..aef2a497d 100644 --- a/app/kubernetes/views/resource-pools/access/resourcePoolAccessController.js +++ b/app/kubernetes/views/resource-pools/access/resourcePoolAccessController.js @@ -52,7 +52,7 @@ class KubernetesResourcePoolAccessController { let [endpoint, pool, configMap] = await Promise.all([ this.EndpointService.endpoint(this.endpointId), this.KubernetesResourcePoolService.get(name), - this.KubernetesConfigMapService.get(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName), + this.KubernetesConfigMapService.getAccess(KubernetesPortainerConfigMapNamespace, KubernetesPortainerConfigMapConfigName), ]); const group = await this.GroupService.group(endpoint.GroupId); const roles = []; @@ -96,7 +96,7 @@ class KubernetesResourcePoolAccessController { this.state.actionInProgress = true; const newAccesses = _.concat(this.authorizedUsersAndTeams, this.formValues.multiselectOutput); const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses); - await this.KubernetesConfigMapService.update(accessConfigMap); + await this.KubernetesConfigMapService.updateAccess(accessConfigMap); this.Notifications.success('Access successfully created'); this.$state.reload(); } catch (err) { @@ -116,7 +116,7 @@ class KubernetesResourcePoolAccessController { this.state.actionInProgress = true; const newAccesses = _.without(this.authorizedUsersAndTeams, ...selectedItems); const accessConfigMap = KubernetesConfigMapHelper.modifiyNamespaceAccesses(angular.copy(this.accessConfigMap), this.pool.Namespace.Name, newAccesses); - await this.KubernetesConfigMapService.update(accessConfigMap); + await this.KubernetesConfigMapService.updateAccess(accessConfigMap); this.Notifications.success('Access successfully removed'); this.$state.reload(); } catch (err) { diff --git a/app/portainer/views/stacks/create/createStackController.js b/app/portainer/views/stacks/create/createStackController.js index 9510d82ae..df7892365 100644 --- a/app/portainer/views/stacks/create/createStackController.js +++ b/app/portainer/views/stacks/create/createStackController.js @@ -167,7 +167,6 @@ angular async function initView() { var endpointMode = $scope.applicationState.endpoint.mode; - const endpointId = +$state.params.endpointId; $scope.state.StackType = 2; if (endpointMode.provider === 'DOCKER_SWARM_MODE' && endpointMode.role === 'MANAGER') { $scope.state.StackType = 1;