diff --git a/api/portainer.go b/api/portainer.go index 0921f723b..1647e0846 100644 --- a/api/portainer.go +++ b/api/portainer.go @@ -322,21 +322,21 @@ type ( // EndpointSecuritySettings represents settings for an endpoint EndpointSecuritySettings struct { // Whether non-administrator should be able to use bind mounts when creating containers - AllowBindMountsForRegularUsers bool `json:"AllowBindMountsForRegularUsers" example:"false"` + AllowBindMountsForRegularUsers bool `json:"allowBindMountsForRegularUsers" example:"false"` // Whether non-administrator should be able to use privileged mode when creating containers - AllowPrivilegedModeForRegularUsers bool `json:"AllowPrivilegedModeForRegularUsers" example:"false"` + AllowPrivilegedModeForRegularUsers bool `json:"allowPrivilegedModeForRegularUsers" example:"false"` // Whether non-administrator should be able to browse volumes - AllowVolumeBrowserForRegularUsers bool `json:"AllowVolumeBrowserForRegularUsers" example:""` + AllowVolumeBrowserForRegularUsers bool `json:"allowVolumeBrowserForRegularUsers" example:"true"` // Whether non-administrator should be able to use the host pid - AllowHostNamespaceForRegularUsers bool `json:"AllowHostNamespaceForRegularUsers" example:""` + AllowHostNamespaceForRegularUsers bool `json:"allowHostNamespaceForRegularUsers" example:"true"` // Whether non-administrator should be able to use device mapping - AllowDeviceMappingForRegularUsers bool `json:"AllowDeviceMappingForRegularUsers" example:""` + AllowDeviceMappingForRegularUsers bool `json:"allowDeviceMappingForRegularUsers" example:"true"` // Whether non-administrator should be able to manage stacks - AllowStackManagementForRegularUsers bool `json:"AllowStackManagementForRegularUsers" example:""` + AllowStackManagementForRegularUsers bool `json:"allowStackManagementForRegularUsers" example:"true"` // Whether non-administrator should be able to use container capabilities - AllowContainerCapabilitiesForRegularUsers bool `json:"AllowContainerCapabilitiesForRegularUsers" example:""` + AllowContainerCapabilitiesForRegularUsers bool `json:"allowContainerCapabilitiesForRegularUsers" example:"true"` // Whether host management features are enabled - EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures" example:""` + EnableHostManagementFeatures bool `json:"enableHostManagementFeatures" example:"true"` } // EndpointType represents the type of an endpoint diff --git a/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationData.html b/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationData.html index 3d8ac4e91..22abaf506 100644 --- a/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationData.html +++ b/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationData.html @@ -53,9 +53,7 @@
This field is required.
diff --git a/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationDataController.js b/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationDataController.js index cac565252..593fdc347 100644 --- a/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationDataController.js +++ b/app/kubernetes/components/kubernetes-configuration-data/kubernetesConfigurationDataController.js @@ -20,7 +20,7 @@ class KubernetesConfigurationDataController { } onChangeKey(entry) { - if (entry.Used) { + if (entry && entry.Used) { return; } @@ -86,6 +86,7 @@ class KubernetesConfigurationDataController { showSimpleMode() { this.formValues.IsSimple = true; this.formValues.Data = KubernetesConfigurationHelper.parseYaml(this.formValues); + this.onChangeKey(); } showAdvancedMode() { @@ -95,7 +96,7 @@ class KubernetesConfigurationDataController { $onInit() { this.state = { - duplicateKeys: {}, + duplicateKeys: [], invalidKeys: {}, }; } diff --git a/app/kubernetes/helpers/application/index.js b/app/kubernetes/helpers/application/index.js index 429803b06..dd93beef7 100644 --- a/app/kubernetes/helpers/application/index.js +++ b/app/kubernetes/helpers/application/index.js @@ -115,7 +115,11 @@ class KubernetesApplicationHelper { const env = _.map(envVariables, (item) => { const res = new KubernetesApplicationEnvPayload(); res.name = item.Name; - res.value = item.Value; + if (item.Value === undefined) { + delete res.value; + } else { + res.value = item.Value; + } return res; }); return env; @@ -123,6 +127,9 @@ class KubernetesApplicationHelper { static generateEnvVariablesFromEnv(env) { const envVariables = _.map(env, (item) => { + if (item.valueFrom) { + return; + } const res = new KubernetesApplicationEnvironmentVariableFormValue(); res.Name = item.name; res.Value = item.value; diff --git a/app/kubernetes/views/configure/configureController.js b/app/kubernetes/views/configure/configureController.js index 8c53ce502..a66bf5a19 100644 --- a/app/kubernetes/views/configure/configureController.js +++ b/app/kubernetes/views/configure/configureController.js @@ -8,11 +8,19 @@ import { KubernetesIngressClassTypes } from 'Kubernetes/ingress/constants'; class KubernetesConfigureController { /* #region CONSTRUCTOR */ + + // TODO: technical debt + // $transition$ cannot be injected as bindings: { $transition$: '<' } inside app/portainer/__module.js + // because this view is not using a component (https://ui-router.github.io/guide/ng1/route-to-component#accessing-transition) + // and will cause + // >> Error: Cannot combine: component|bindings|componentProvider + // >> with: templateProvider|templateUrl|template|notify|async|controller|controllerProvider|controllerAs|resolveAs + // >> in stateview: 'content@@portainer.endpoints.endpoint.kubernetesConfig' /* @ngInject */ constructor( $async, $state, - $stateParams, + $transition$, Notifications, KubernetesStorageService, EndpointService, @@ -24,7 +32,7 @@ class KubernetesConfigureController { ) { this.$async = $async; this.$state = $state; - this.$stateParams = $stateParams; + this.$transition$ = $transition$; this.Notifications = Notifications; this.KubernetesStorageService = KubernetesStorageService; this.EndpointService = EndpointService; @@ -210,7 +218,7 @@ class KubernetesConfigureController { actionInProgress: false, displayConfigureClassPanel: {}, viewReady: false, - endpointId: this.$stateParams.id, + endpointId: this.$transition$.params().id, duplicates: { ingressClasses: new KubernetesFormValidationReferences(), }, diff --git a/app/portainer/services/endpointProvider.js b/app/portainer/services/endpointProvider.js index 1a49f1321..ea18ca01d 100644 --- a/app/portainer/services/endpointProvider.js +++ b/app/portainer/services/endpointProvider.js @@ -1,8 +1,9 @@ import _ from 'lodash-es'; -angular.module('portainer.app').factory('EndpointProvider', [ - 'LocalStorage', - function EndpointProviderFactory(LocalStorage) { +angular.module('portainer.app').factory( + 'EndpointProvider', + /* @ngInject */ + function EndpointProviderFactory(LocalStorage, $uiRouterGlobals) { 'use strict'; var service = {}; var endpoint = {}; @@ -36,9 +37,36 @@ angular.module('portainer.app').factory('EndpointProvider', [ if (endpoint.ID === undefined) { endpoint.ID = LocalStorage.getEndpointID(); } + if (endpoint.ID === null || endpoint.ID === undefined) { + return service.getUrlEndpointID(); + } return endpoint.ID; }; + // TODO: technical debt + // Reference issue: JIRA CE-463 + // Documentation (https://ui-router.github.io/ng1/docs/latest/modules/injectables.html) show the usage of either + // * $stateParams + // * $transition$ + // * $uiRouterGlobals + // to retrieve the URL params + // + // * $stateParams: is deprecated and will cause a circular dependency injection error + // because EndpointProvider is used by EndpointStatusInterceptor which is injected inside $httpProvider + // >> [$injector:cdep] Circular dependency found: $uiRouter <- $stateParams <- EndpointProvider <- EndpointStatusInterceptor <- $http <- $uiRouter + // For more details, see https://stackoverflow.com/questions/20230691/injecting-state-ui-router-into-http-interceptor-causes-circular-dependency#20230786 + // + // * $transition$: mentionned as the replacement of $stateParams (https://ui-router.github.io/guide/ng1/migrate-to-1_0#stateparams-deprecation) + // but is not injectable without tweaks inside a service + // + // * $uiRouterGlobal: per https://github.com/angular-ui/ui-router/issues/3237#issuecomment-271979688 + // seems the recommanded way to retrieve params inside a service/factory + // + // We need this function to fallback on URL endpoint ID when no endpoint has been selected + service.getUrlEndpointID = () => { + return $uiRouterGlobals.params.id; + }; + service.setEndpointID = function (id) { endpoint.ID = id; LocalStorage.storeEndpointID(id); @@ -88,5 +116,5 @@ angular.module('portainer.app').factory('EndpointProvider', [ }; return service; - }, -]); + } +); diff --git a/app/portainer/views/templates/templatesController.js b/app/portainer/views/templates/templatesController.js index 34f90a9d6..cdf36a38a 100644 --- a/app/portainer/views/templates/templatesController.js +++ b/app/portainer/views/templates/templatesController.js @@ -254,7 +254,7 @@ angular.module('portainer.app').controller('TemplatesController', [ var endpointMode = $scope.applicationState.endpoint.mode; var apiVersion = $scope.applicationState.endpoint.apiVersion; - this.state.provider = endpointMode.provider === 'DOCKER_STANDALONE' ? 2 : 1; + $scope.state.provider = endpointMode.provider === 'DOCKER_STANDALONE' ? 2 : 1; $q.all({ templates: TemplateService.templates(),