1
0
Fork 0
mirror of https://github.com/portainer/portainer.git synced 2025-08-08 23:35:31 +02:00

refactor(settings/backup): migrate backup setting module [EE-5508] (#9076)

This commit is contained in:
Oscar Zhou 2023-06-19 09:57:33 +12:00 committed by GitHub
parent caf87bb0b5
commit 9f9cdf7d43
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 689 additions and 289 deletions

View file

@ -10,6 +10,7 @@ import { EdgeComputeSettingsView } from '@/react/portainer/settings/EdgeComputeV
import { withI18nSuspense } from '@/react-tools/withI18nSuspense';
import { EdgeAutoCreateScriptView } from '@/react/portainer/environments/EdgeAutoCreateScriptView';
import { ListView as EnvironmentsListView } from '@/react/portainer/environments/ListView';
import { BackupSettingsPanel } from '@/react/portainer/settings/SettingsView/BackupSettingsView/BackupSettingsPanel';
import { wizardModule } from './wizard';
import { teamsModule } from './teams';
@ -49,4 +50,8 @@ export const viewsModule = angular
.component(
'environmentsListView',
r2a(withUIRouter(withReactQuery(withCurrentUser(EnvironmentsListView))), [])
)
.component(
'backupSettingsPanel',
r2a(withUIRouter(withReactQuery(withCurrentUser(BackupSettingsPanel))), [])
).name;

View file

@ -152,241 +152,5 @@
</div>
</div>
<div class="row">
<div class="col-sm-12">
<rd-widget>
<rd-widget-header icon="download" title-text="Back up Portainer"></rd-widget-header>
<rd-widget-body>
<form class="form-horizontal" ng-submit="backupPortainer()" name="backupPortainerForm">
<div class="col-sm-12 form-section-title"> Backup configuration </div>
<div class="text-muted small mb-3">This will back up your Portainer server configuration and does not include containers.</div>
<box-selector slim="true" options="backupOptions" value="formValues.backupFormType" on-change="(onBackupOptionsChange)" radio-name="'backupOptions'"></box-selector>
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.S3">
<!-- Schedule automatic backups -->
<div class="form-group mt-3">
<por-switch-field
label="'Schedule automatic backups'"
name="'s3-backup-setting'"
feature-id="s3BackupFeatureId"
checked="formValues.scheduleAutomaticBackups"
field-class="'col-sm-10'"
label-class="'col-sm-2'"
on-change="(onToggleAutoBackups)"
></por-switch-field>
</div>
<!-- !Schedule automatic backups -->
<!-- Cron rule -->
<div class="form-group" ng-if="formValues.scheduleAutomaticBackups">
<label for="cron_rule" class="col-sm-2 control-label text-left">Cron rule</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
placeholder="0 2 * * *"
id="cron_rule"
name="cron_rule"
ng-model="formValues.cronRule"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
required
cronRule
/>
</div>
</div>
<!-- !Cron rule -->
<!-- Access key id -->
<div class="form-group">
<label for="access_key_id" class="col-sm-2 control-label text-left">Access Key ID</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
id="access_key_id"
name="access_key_id"
ng-model="formValues.accessKeyId"
ng-required="formValues.scheduleAutomaticBackups"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
/>
</div>
</div>
<!-- !Access key id -->
<!-- Secret access key -->
<div class="form-group">
<label for="secret_access_key" class="col-sm-2 control-label text-left">Secret Access Key</label>
<div class="col-sm-10">
<input
type="password"
class="form-control"
id="secret_access_key"
name="secret_access_key"
ng-model="formValues.secretAccessKey"
ng-required="formValues.scheduleAutomaticBackups"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
/>
</div>
</div>
<!-- !Secret access key -->
<!-- Region -->
<div class="form-group">
<label for="region" class="col-sm-2 control-label text-left">Region</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
placeholder="default region is us-east-1 if left empty"
id="region"
name="region"
ng-model="formValues.region"
ng-required="formValues.scheduleAutomaticBackups"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
/>
</div>
</div>
<!-- !Region -->
<!-- Bucket name -->
<div class="form-group">
<label for="bucket_name" class="col-sm-2 control-label text-left">Bucket name</label>
<div class="col-sm-10">
<input
type="text"
class="form-control"
id="bucket_name"
name="bucket_name"
ng-model="formValues.bucketName"
ng-required="formValues.scheduleAutomaticBackups"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
/>
</div>
</div>
<!-- !Bucket name -->
<div class="col-sm-12 form-section-title"> Security settings </div>
<!-- Password protect S3 -->
<div class="form-group">
<label for="password_protect" class="col-sm-2 control-label text-left">Password protect</label>
<div class="col-sm-10">
<label class="switch">
<input
type="checkbox"
id="password_protect_s3"
name="password_protect_s3"
ng-model="formValues.passwordProtectS3"
data-cy="settings-passwordProtectToggleS3"
disabled
/><span class="slider round"></span>
</label>
</div>
</div>
<!-- !Password protect S3 -->
<!-- Password S3 -->
<div class="form-group" ng-if="formValues.passwordProtectS3">
<label for="password" class="col-sm-2 control-label text-left">Password</label>
<div class="col-sm-3">
<input type="password" class="form-control" ng-model="formValues.passwordS3" id="password_S3" name="password_S3" required data-cy="settings-backups3pw" />
</div>
</div>
<div class="form-group col-md-12" ng-show="backupPortainerForm.password_S3.$invalid">
<div class="small text-warning">
<div ng-messages="backupPortainerForm.password_S3.$error">
<p ng-message="required"> <pr-icon icon="'alert-triangle'"></pr-icon> This field is required.</p>
</div>
</div>
</div>
<!-- !Password S3 -->
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-disabled="backupPortainerForm.$invalid"
ng-click="exportBackup()"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
>
<span>
<pr-icon icon="'upload'" class-name="'mr-1'"></pr-icon>
Export backup
</span>
</button>
</div>
</div>
<div class="form-group">
<hr />
<div class="col-sm-12">
<button
type="submit"
class="btn btn-primary btn-sm"
ng-disabled="backupPortainerForm.$invalid ||state.backupInProgress"
ng-click="saveS3BackupSettings()"
limited-feature-dir="{{::s3BackupFeatureId}}"
limited-feature-disabled
limited-feature-class="limited-be"
>
<span>Save backup settings</span>
</button>
</div>
</div>
</div>
<div ng-if="formValues.backupFormType === BACKUP_FORM_TYPES.FILE">
<div class="col-sm-12 form-section-title"> Security settings </div>
<!-- Password protect -->
<div class="form-group">
<label for="password_protect" class="col-sm-2 control-label text-left">Password protect</label>
<div class="col-sm-2">
<label class="switch" data-cy="settings-passwordProtectLocal">
<input type="checkbox" id="password_protect" name="password_protect" ng-model="formValues.passwordProtect" /><span class="slider round"></span>
</label>
</div>
</div>
<!-- !Password protect -->
<!-- Password -->
<div class="form-group" ng-if="formValues.passwordProtect">
<label for="password" class="col-sm-2 control-label text-left">Password</label>
<div class="col-sm-3">
<input type="password" class="form-control" ng-model="formValues.password" id="password" name="password" required data-cy="settings-backupLocalPassword" />
</div>
</div>
<div class="form-group col-md-12" ng-show="backupPortainerForm.password.$invalid">
<div class="small text-warning">
<div ng-messages="backupPortainerForm.password.$error">
<p ng-message="required"> <pr-icon icon="'alert-triangle'"></pr-icon> This field is required.</p>
</div>
</div>
</div>
<!-- !Password -->
<!-- actions -->
<div class="form-group">
<div class="col-sm-12">
<button
type="button"
class="btn btn-primary btn-sm"
ng-click="downloadBackup()"
ng-disabled="backupPortainerForm.$invalid || state.backupInProgress || state.featureLimited"
button-spinner="state.backupInProgress"
data-cy="settings-downloadLocalBackup"
>
<span ng-hide="state.backupInProgress">Download backup</span>
<span ng-show="state.backupInProgress">Downloading backup</span>
</button>
</div>
</div>
</div>
<!-- !actions -->
</form>
</rd-widget-body>
</rd-widget>
</div>
</div>
<!-- backup -->
<backup-settings-panel></backup-settings-panel>

View file

@ -1,24 +1,17 @@
import angular from 'angular';
import { FeatureId } from '@/react/portainer/feature-flags/enums';
import { options } from '@/react/portainer/settings/SettingsView/backup-options';
angular.module('portainer.app').controller('SettingsController', [
'$scope',
'Notifications',
'SettingsService',
'StateManager',
'BackupService',
'FileSaver',
function ($scope, Notifications, SettingsService, StateManager, BackupService, FileSaver) {
$scope.s3BackupFeatureId = FeatureId.S3_BACKUP_SETTING;
$scope.enforceDeploymentOptions = FeatureId.ENFORCE_DEPLOYMENT_OPTIONS;
function ($scope, Notifications, SettingsService, StateManager) {
$scope.updateSettings = updateSettings;
$scope.handleSuccess = handleSuccess;
$scope.requireNoteOnApplications = FeatureId.K8S_REQUIRE_NOTE_ON_APPLICATIONS;
$scope.backupOptions = options;
$scope.state = {
actionInProgress: false,
availableKubeconfigExpiryOptions: [
@ -48,28 +41,12 @@ angular.module('portainer.app').controller('SettingsController', [
showHTTPS: !window.ddExtension,
};
$scope.BACKUP_FORM_TYPES = { S3: 's3', FILE: 'file' };
$scope.formValues = {
KubeconfigExpiry: undefined,
HelmRepositoryURL: undefined,
BlackListedLabels: [],
labelName: '',
labelValue: '',
passwordProtect: false,
password: '',
backupFormType: $scope.BACKUP_FORM_TYPES.FILE,
};
$scope.onToggleAutoBackups = function onToggleAutoBackups(checked) {
$scope.$evalAsync(() => {
$scope.formValues.scheduleAutomaticBackups = checked;
});
};
$scope.onBackupOptionsChange = function (type, limited) {
$scope.formValues.backupFormType = type;
$scope.state.featureLimited = limited;
};
$scope.removeFilteredContainerLabel = function (index) {
@ -89,28 +66,6 @@ angular.module('portainer.app').controller('SettingsController', [
updateSettings(filteredSettingsPayload, 'Hidden container settings updated');
};
$scope.downloadBackup = function () {
const payload = {};
if ($scope.formValues.passwordProtect) {
payload.password = $scope.formValues.password;
}
$scope.state.backupInProgress = true;
BackupService.downloadBackup(payload)
.then(function success(data) {
const downloadData = new Blob([data.file], { type: 'application/gzip' });
FileSaver.saveAs(downloadData, data.name);
Notifications.success('Success', 'Backup successfully downloaded');
})
.catch(function error(err) {
Notifications.error('Failure', err, 'Unable to download backup');
})
.finally(function final() {
$scope.state.backupInProgress = false;
});
};
// only update the values from the kube settings widget. In future separate the api endpoints
$scope.saveKubernetesSettings = function () {
const kubeSettingsPayload = {