feat(deployment): enforce deployment options EE-4416 (#7974)

pull/8071/head
Ali 2022-11-17 22:00:34 +13:00 committed by GitHub
parent e0f3a8c0a2
commit d012a4efc4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 96 additions and 31 deletions

View File

@ -72,7 +72,6 @@
<a href="https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/" target="_blank">privacy policy</a>. <a href="https://www.portainer.io/documentation/in-app-analytics-and-privacy-policy/" target="_blank">privacy policy</a>.
</div> </div>
</div> </div>
<!-- login screen banner --> <!-- login screen banner -->
<div class="form-group"> <div class="form-group">
<por-switch-field <por-switch-field
@ -86,7 +85,6 @@
></por-switch-field> ></por-switch-field>
</div> </div>
<!-- !login screen banner --> <!-- !login screen banner -->
<!-- templates --> <!-- templates -->
<div class="col-sm-12 form-section-title"> App Templates </div> <div class="col-sm-12 form-section-title"> App Templates </div>
<div> <div>
@ -112,6 +110,35 @@
</div> </div>
</div> </div>
<!-- !templates --> <!-- !templates -->
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-click="saveApplicationSettings()"
ng-disabled="state.actionInProgress || !settings.TemplatesURL"
button-spinner="state.actionInProgress"
data-cy="settings-saveSettingsButton"
>
<span ng-hide="state.actionInProgress">Save application settings</span>
<span ng-show="state.actionInProgress">Saving...</span>
</button>
</div>
</div>
<!-- !actions -->
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="svg-kube" feather-icon="true" title-text="Kubernetes settings"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal">
<!-- helm charts --> <!-- helm charts -->
<div class="col-sm-12 form-section-title"> Helm Repository </div> <div class="col-sm-12 form-section-title"> Helm Repository </div>
<div> <div>
@ -129,7 +156,6 @@
</div> </div>
</div> </div>
<!-- !helm charts --> <!-- !helm charts -->
<!-- host-filesystem -->
<!-- kube --> <!-- kube -->
<div class="col-sm-12 form-section-title"> Kubernetes </div> <div class="col-sm-12 form-section-title"> Kubernetes </div>
<div class="form-group"> <div class="form-group">
@ -138,25 +164,40 @@
<select <select
id="kubeconfig_expiry" id="kubeconfig_expiry"
class="form-control" class="form-control"
ng-model="settings.KubeconfigExpiry" ng-model="formValues.KubeconfigExpiry"
ng-options="opt.value as opt.key for opt in state.availableKubeconfigExpiryOptions" ng-options="opt.value as opt.key for opt in state.availableKubeconfigExpiryOptions"
></select> ></select>
</div> </div>
</div> </div>
<!-- ! kube --> <!-- ! kube -->
<!-- deployment options -->
<div class="col-sm-12 form-section-title"> Deployment Options </div>
<div class="form-group">
<por-switch-field
label="'Enforce code-based deployment'"
name="'toggle_hideAddWithForm'"
feature-id="enforceDeploymentOptions"
disabled="true"
checked="false"
field-class="'col-sm-12'"
label-class="'col-sm-2'"
tooltip="'Hides the \'Add with form\' buttons and prevents adding/editing of resources via forms'"
></por-switch-field>
</div>
<!-- !deployment options -->
<!-- actions --> <!-- actions -->
<div class="form-group"> <div class="form-group">
<div class="col-sm-12"> <div class="col-sm-12">
<button <button
type="button" type="button"
class="btn btn-primary btn-sm" class="btn btn-primary btn-sm"
ng-click="saveApplicationSettings()" ng-click="saveKubernetesSettings()"
ng-disabled="state.actionInProgress || !settings.TemplatesURL" ng-disabled="state.kubeSettingsActionInProgress"
button-spinner="state.actionInProgress" button-spinner="state.kubeSettingsActionInProgress"
data-cy="settings-saveSettingsButton" data-cy="settings-saveSettingsButton"
> >
<span ng-hide="state.actionInProgress">Save settings</span> <span ng-hide="state.kubeSettingsActionInProgress">Save Kubernetes settings</span>
<span ng-show="state.actionInProgress">Saving...</span> <span ng-show="state.kubeSettingsActionInProgress">Saving...</span>
</button> </button>
</div> </div>
</div> </div>
@ -202,7 +243,7 @@
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="label in settings.BlackListedLabels"> <tr ng-repeat="label in formValues.BlackListedLabels">
<td>{{ label.name }}</td> <td>{{ label.name }}</td>
<td>{{ label.value }}</td> <td>{{ label.value }}</td>
<td> <td>
@ -211,10 +252,10 @@
> >
</td> </td>
</tr> </tr>
<tr ng-if="settings.BlackListedLabels.length === 0"> <tr ng-if="formValues.BlackListedLabels.length === 0">
<td colspan="3" class="text-center text-muted">No filter available.</td> <td colspan="3" class="text-center text-muted">No filter available.</td>
</tr> </tr>
<tr ng-if="!settings.BlackListedLabels"> <tr ng-if="!formValues.BlackListedLabels">
<td colspan="3" class="text-center text-muted">Loading...</td> <td colspan="3" class="text-center text-muted">Loading...</td>
</tr> </tr>
</tbody> </tbody>

View File

@ -15,6 +15,7 @@ angular.module('portainer.app').controller('SettingsController', [
function ($scope, $state, Notifications, SettingsService, StateManager, BackupService, FileSaver) { function ($scope, $state, Notifications, SettingsService, StateManager, BackupService, FileSaver) {
$scope.customBannerFeatureId = FeatureId.CUSTOM_LOGIN_BANNER; $scope.customBannerFeatureId = FeatureId.CUSTOM_LOGIN_BANNER;
$scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING; $scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING;
$scope.enforceDeploymentOptions = FeatureId.ENFORCE_DEPLOYMENT_OPTIONS;
$scope.backupOptions = options; $scope.backupOptions = options;
@ -52,6 +53,9 @@ angular.module('portainer.app').controller('SettingsController', [
$scope.formValues = { $scope.formValues = {
customLogo: false, customLogo: false,
KubeconfigExpiry: undefined,
HelmRepositoryURL: undefined,
BlackListedLabels: [],
labelName: '', labelName: '',
labelValue: '', labelValue: '',
enableTelemetry: false, enableTelemetry: false,
@ -91,21 +95,20 @@ angular.module('portainer.app').controller('SettingsController', [
}; };
$scope.removeFilteredContainerLabel = function (index) { $scope.removeFilteredContainerLabel = function (index) {
var settings = $scope.settings; const filteredSettings = $scope.formValues.BlackListedLabels.filter((_, i) => i !== index);
settings.BlackListedLabels.splice(index, 1); const filteredSettingsPayload = { BlackListedLabels: filteredSettings };
updateSettings(filteredSettingsPayload, 'Hidden container settings updated');
updateSettings(settings);
}; };
$scope.addFilteredContainerLabel = function () { $scope.addFilteredContainerLabel = function () {
var settings = $scope.settings;
var label = { var label = {
name: $scope.formValues.labelName, name: $scope.formValues.labelName,
value: $scope.formValues.labelValue, value: $scope.formValues.labelValue,
}; };
settings.BlackListedLabels.push(label);
updateSettings(settings); const filteredSettings = [...$scope.formValues.BlackListedLabels, label];
const filteredSettingsPayload = { BlackListedLabels: filteredSettings };
updateSettings(filteredSettingsPayload, 'Hidden container settings updated');
}; };
$scope.downloadBackup = function () { $scope.downloadBackup = function () {
@ -130,32 +133,45 @@ angular.module('portainer.app').controller('SettingsController', [
}); });
}; };
// only update the values from the app settings widget. In future separate the api endpoints
$scope.saveApplicationSettings = function () { $scope.saveApplicationSettings = function () {
var settings = $scope.settings; const appSettingsPayload = {
SnapshotInterval: $scope.settings.SnapshotInterval,
if (!$scope.formValues.customLogo) { LogoURL: $scope.formValues.customLogo ? $scope.settings.LogoURL : '',
settings.LogoURL = ''; EnableTelemetry: $scope.formValues.enableTelemetry,
} TemplatesURL: $scope.settings.TemplatesURL,
};
settings.EnableTelemetry = $scope.formValues.enableTelemetry;
$scope.state.actionInProgress = true; $scope.state.actionInProgress = true;
updateSettings(settings); updateSettings(appSettingsPayload, 'Application settings updated');
}; };
function updateSettings(settings) { // only update the values from the kube settings widget. In future separate the api endpoints
$scope.saveKubernetesSettings = function () {
const kubeSettingsPayload = {
KubeconfigExpiry: $scope.formValues.KubeconfigExpiry,
HelmRepositoryURL: $scope.formValues.HelmRepositoryURL,
GlobalDeploymentOptions: $scope.formValues.GlobalDeploymentOptions,
};
$scope.state.kubeSettingsActionInProgress = true;
updateSettings(kubeSettingsPayload, 'Kubernetes settings updated');
};
function updateSettings(settings, successMessage = 'Settings updated') {
SettingsService.update(settings) SettingsService.update(settings)
.then(function success() { .then(function success(response) {
Notifications.success('Success', 'Settings updated'); Notifications.success('Success', successMessage);
StateManager.updateLogo(settings.LogoURL); StateManager.updateLogo(settings.LogoURL);
StateManager.updateSnapshotInterval(settings.SnapshotInterval); StateManager.updateSnapshotInterval(settings.SnapshotInterval);
StateManager.updateEnableTelemetry(settings.EnableTelemetry); StateManager.updateEnableTelemetry(settings.EnableTelemetry);
$state.reload(); $scope.formValues.BlackListedLabels = response.BlackListedLabels;
}) })
.catch(function error(err) { .catch(function error(err) {
Notifications.error('Failure', err, 'Unable to update settings'); Notifications.error('Failure', err, 'Unable to update settings');
}) })
.finally(function final() { .finally(function final() {
$scope.state.kubeSettingsActionInProgress = false;
$scope.state.actionInProgress = false; $scope.state.actionInProgress = false;
}); });
} }
@ -172,7 +188,11 @@ angular.module('portainer.app').controller('SettingsController', [
if (settings.LogoURL !== '') { if (settings.LogoURL !== '') {
$scope.formValues.customLogo = true; $scope.formValues.customLogo = true;
} }
$scope.formValues.enableTelemetry = settings.EnableTelemetry; $scope.formValues.enableTelemetry = settings.EnableTelemetry;
$scope.formValues.KubeconfigExpiry = settings.KubeconfigExpiry;
$scope.formValues.HelmRepositoryURL = settings.HelmRepositoryURL;
$scope.formValues.BlackListedLabels = settings.BlackListedLabels;
}) })
.catch(function error(err) { .catch(function error(err) {
Notifications.error('Failure', err, 'Unable to retrieve application settings'); Notifications.error('Failure', err, 'Unable to retrieve application settings');

View File

@ -53,6 +53,7 @@ import upload from '@/assets/ico/upload.svg?c';
import url from '@/assets/ico/url.svg?c'; import url from '@/assets/ico/url.svg?c';
import usercircle from '@/assets/ico/user-circle.svg?c'; import usercircle from '@/assets/ico/user-circle.svg?c';
import userlock from '@/assets/ico/user-lock.svg?c'; import userlock from '@/assets/ico/user-lock.svg?c';
import kube from '@/assets/ico/kube.svg?c';
import Placeholder from '@/assets/ico/placeholder.svg?c'; // Placeholder is used when an icon name cant be matched import Placeholder from '@/assets/ico/placeholder.svg?c'; // Placeholder is used when an icon name cant be matched
// vendor icons // vendor icons
import aws from '@/assets/ico/vendor/aws.svg?c'; import aws from '@/assets/ico/vendor/aws.svg?c';
@ -152,6 +153,7 @@ export const SvgIcons = {
proget, proget,
quay, quay,
internal, internal,
kube,
}; };
interface SvgProps { interface SvgProps {

View File

@ -32,5 +32,6 @@ export enum FeatureId {
POD_SECURITY_POLICY_CONSTRAINT = 'pod-security-policy-constraint', POD_SECURITY_POLICY_CONSTRAINT = 'pod-security-policy-constraint',
HIDE_DOCKER_HUB_ANONYMOUS = 'hide-docker-hub-anonymous', HIDE_DOCKER_HUB_ANONYMOUS = 'hide-docker-hub-anonymous',
CUSTOM_LOGIN_BANNER = 'custom-login-banner', CUSTOM_LOGIN_BANNER = 'custom-login-banner',
ENFORCE_DEPLOYMENT_OPTIONS = 'k8s-enforce-deployment-options',
K8S_ADM_ONLY_USR_INGRESS_DEPLY = 'k8s-admin-only-ingress-deploy', K8S_ADM_ONLY_USR_INGRESS_DEPLY = 'k8s-admin-only-ingress-deploy',
} }

View File

@ -37,6 +37,7 @@ export async function init(edition: Edition) {
[FeatureId.POD_SECURITY_POLICY_CONSTRAINT]: Edition.BE, [FeatureId.POD_SECURITY_POLICY_CONSTRAINT]: Edition.BE,
[FeatureId.HIDE_DOCKER_HUB_ANONYMOUS]: Edition.BE, [FeatureId.HIDE_DOCKER_HUB_ANONYMOUS]: Edition.BE,
[FeatureId.CUSTOM_LOGIN_BANNER]: Edition.BE, [FeatureId.CUSTOM_LOGIN_BANNER]: Edition.BE,
[FeatureId.ENFORCE_DEPLOYMENT_OPTIONS]: Edition.BE,
[FeatureId.K8S_ADM_ONLY_USR_INGRESS_DEPLY]: Edition.BE, [FeatureId.K8S_ADM_ONLY_USR_INGRESS_DEPLY]: Edition.BE,
}; };