mirror of https://github.com/portainer/portainer
Merge changes from release 2.2 (#4930)
* fix windows build * fix(endpoints): show correct values of security settings (#4889) * fix(app): EndpointProvider fallback on URL EndpointID when no endpoint is selected (#4892) * fix(templates): App templates not loading with error in browser console (#4895) * fix(kube/config): show used key warning when needed (#4890) fix [CE-469] - recalculate duplcate keys when they are changed - show used warning on duplicate keys * fix(k8s): CE-471 variables from configuration showing on environment variables section on application edit screen (#4896) * fix(k8s): CE-471 variables from configuration showing on environment variables section on application edit screen * fix(k8s): CE-471 avoid to remove value path of env when patch k8s deployment, as the value path does not exist if env variable has empty value. Co-authored-by: Simon Meng <simon.meng@portainer.io> Co-authored-by: Dmitry Salakhov <to@dimasalakhov.com> Co-authored-by: Chaim Lev-Ari <chiptus@users.noreply.github.com> Co-authored-by: LP B <xAt0mZ@users.noreply.github.com> Co-authored-by: Maxime Bajeux <max.bajeux@gmail.com> Co-authored-by: cong meng <mcpacino@gmail.com> Co-authored-by: Simon Meng <simon.meng@portainer.io>pull/4834/head
parent
239e434522
commit
572b64b68e
|
@ -322,21 +322,21 @@ type (
|
||||||
// EndpointSecuritySettings represents settings for an endpoint
|
// EndpointSecuritySettings represents settings for an endpoint
|
||||||
EndpointSecuritySettings struct {
|
EndpointSecuritySettings struct {
|
||||||
// Whether non-administrator should be able to use bind mounts when creating containers
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// Whether host management features are enabled
|
||||||
EnableHostManagementFeatures bool `json:"EnableHostManagementFeatures" example:""`
|
EnableHostManagementFeatures bool `json:"enableHostManagementFeatures" example:"true"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// EndpointType represents the type of an endpoint
|
// EndpointType represents the type of an endpoint
|
||||||
|
|
|
@ -53,9 +53,7 @@
|
||||||
<div
|
<div
|
||||||
class="col-sm-11 small text-warning"
|
class="col-sm-11 small text-warning"
|
||||||
style="margin-top: 5px;"
|
style="margin-top: 5px;"
|
||||||
ng-show="
|
ng-show="kubernetesConfigurationDataCreationForm['configuration_data_key_' + index].$invalid || (!entry.Used && $ctrl.state.duplicateKeys[index] !== undefined) || $ctrl.state.invalidKeys[index]"
|
||||||
kubernetesConfigurationDataCreationForm['configuration_data_key_' + index].$invalid || $ctrl.state.duplicateKeys[index] !== undefined || $ctrl.state.invalidKeys[index]
|
|
||||||
"
|
|
||||||
>
|
>
|
||||||
<ng-messages for="kubernetesConfigurationDataCreationForm['configuration_data_key_' + index].$error">
|
<ng-messages for="kubernetesConfigurationDataCreationForm['configuration_data_key_' + index].$error">
|
||||||
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
<p ng-message="required"><i class="fa fa-exclamation-triangle" aria-hidden="true"></i> This field is required.</p>
|
||||||
|
|
|
@ -20,7 +20,7 @@ class KubernetesConfigurationDataController {
|
||||||
}
|
}
|
||||||
|
|
||||||
onChangeKey(entry) {
|
onChangeKey(entry) {
|
||||||
if (entry.Used) {
|
if (entry && entry.Used) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -86,6 +86,7 @@ class KubernetesConfigurationDataController {
|
||||||
showSimpleMode() {
|
showSimpleMode() {
|
||||||
this.formValues.IsSimple = true;
|
this.formValues.IsSimple = true;
|
||||||
this.formValues.Data = KubernetesConfigurationHelper.parseYaml(this.formValues);
|
this.formValues.Data = KubernetesConfigurationHelper.parseYaml(this.formValues);
|
||||||
|
this.onChangeKey();
|
||||||
}
|
}
|
||||||
|
|
||||||
showAdvancedMode() {
|
showAdvancedMode() {
|
||||||
|
@ -95,7 +96,7 @@ class KubernetesConfigurationDataController {
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
this.state = {
|
this.state = {
|
||||||
duplicateKeys: {},
|
duplicateKeys: [],
|
||||||
invalidKeys: {},
|
invalidKeys: {},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,11 @@ class KubernetesApplicationHelper {
|
||||||
const env = _.map(envVariables, (item) => {
|
const env = _.map(envVariables, (item) => {
|
||||||
const res = new KubernetesApplicationEnvPayload();
|
const res = new KubernetesApplicationEnvPayload();
|
||||||
res.name = item.Name;
|
res.name = item.Name;
|
||||||
res.value = item.Value;
|
if (item.Value === undefined) {
|
||||||
|
delete res.value;
|
||||||
|
} else {
|
||||||
|
res.value = item.Value;
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
});
|
});
|
||||||
return env;
|
return env;
|
||||||
|
@ -123,6 +127,9 @@ class KubernetesApplicationHelper {
|
||||||
|
|
||||||
static generateEnvVariablesFromEnv(env) {
|
static generateEnvVariablesFromEnv(env) {
|
||||||
const envVariables = _.map(env, (item) => {
|
const envVariables = _.map(env, (item) => {
|
||||||
|
if (item.valueFrom) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
const res = new KubernetesApplicationEnvironmentVariableFormValue();
|
const res = new KubernetesApplicationEnvironmentVariableFormValue();
|
||||||
res.Name = item.name;
|
res.Name = item.name;
|
||||||
res.Value = item.value;
|
res.Value = item.value;
|
||||||
|
|
|
@ -8,11 +8,19 @@ import { KubernetesIngressClassTypes } from 'Kubernetes/ingress/constants';
|
||||||
|
|
||||||
class KubernetesConfigureController {
|
class KubernetesConfigureController {
|
||||||
/* #region CONSTRUCTOR */
|
/* #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 */
|
/* @ngInject */
|
||||||
constructor(
|
constructor(
|
||||||
$async,
|
$async,
|
||||||
$state,
|
$state,
|
||||||
$stateParams,
|
$transition$,
|
||||||
Notifications,
|
Notifications,
|
||||||
KubernetesStorageService,
|
KubernetesStorageService,
|
||||||
EndpointService,
|
EndpointService,
|
||||||
|
@ -24,7 +32,7 @@ class KubernetesConfigureController {
|
||||||
) {
|
) {
|
||||||
this.$async = $async;
|
this.$async = $async;
|
||||||
this.$state = $state;
|
this.$state = $state;
|
||||||
this.$stateParams = $stateParams;
|
this.$transition$ = $transition$;
|
||||||
this.Notifications = Notifications;
|
this.Notifications = Notifications;
|
||||||
this.KubernetesStorageService = KubernetesStorageService;
|
this.KubernetesStorageService = KubernetesStorageService;
|
||||||
this.EndpointService = EndpointService;
|
this.EndpointService = EndpointService;
|
||||||
|
@ -210,7 +218,7 @@ class KubernetesConfigureController {
|
||||||
actionInProgress: false,
|
actionInProgress: false,
|
||||||
displayConfigureClassPanel: {},
|
displayConfigureClassPanel: {},
|
||||||
viewReady: false,
|
viewReady: false,
|
||||||
endpointId: this.$stateParams.id,
|
endpointId: this.$transition$.params().id,
|
||||||
duplicates: {
|
duplicates: {
|
||||||
ingressClasses: new KubernetesFormValidationReferences(),
|
ingressClasses: new KubernetesFormValidationReferences(),
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
import _ from 'lodash-es';
|
import _ from 'lodash-es';
|
||||||
|
|
||||||
angular.module('portainer.app').factory('EndpointProvider', [
|
angular.module('portainer.app').factory(
|
||||||
'LocalStorage',
|
'EndpointProvider',
|
||||||
function EndpointProviderFactory(LocalStorage) {
|
/* @ngInject */
|
||||||
|
function EndpointProviderFactory(LocalStorage, $uiRouterGlobals) {
|
||||||
'use strict';
|
'use strict';
|
||||||
var service = {};
|
var service = {};
|
||||||
var endpoint = {};
|
var endpoint = {};
|
||||||
|
@ -36,9 +37,36 @@ angular.module('portainer.app').factory('EndpointProvider', [
|
||||||
if (endpoint.ID === undefined) {
|
if (endpoint.ID === undefined) {
|
||||||
endpoint.ID = LocalStorage.getEndpointID();
|
endpoint.ID = LocalStorage.getEndpointID();
|
||||||
}
|
}
|
||||||
|
if (endpoint.ID === null || endpoint.ID === undefined) {
|
||||||
|
return service.getUrlEndpointID();
|
||||||
|
}
|
||||||
return endpoint.ID;
|
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) {
|
service.setEndpointID = function (id) {
|
||||||
endpoint.ID = id;
|
endpoint.ID = id;
|
||||||
LocalStorage.storeEndpointID(id);
|
LocalStorage.storeEndpointID(id);
|
||||||
|
@ -88,5 +116,5 @@ angular.module('portainer.app').factory('EndpointProvider', [
|
||||||
};
|
};
|
||||||
|
|
||||||
return service;
|
return service;
|
||||||
},
|
}
|
||||||
]);
|
);
|
||||||
|
|
|
@ -254,7 +254,7 @@ angular.module('portainer.app').controller('TemplatesController', [
|
||||||
|
|
||||||
var endpointMode = $scope.applicationState.endpoint.mode;
|
var endpointMode = $scope.applicationState.endpoint.mode;
|
||||||
var apiVersion = $scope.applicationState.endpoint.apiVersion;
|
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({
|
$q.all({
|
||||||
templates: TemplateService.templates(),
|
templates: TemplateService.templates(),
|
||||||
|
|
Loading…
Reference in New Issue