mirror of
https://github.com/portainer/portainer.git
synced 2025-07-23 07:19:41 +02:00
feat(secrets): allow creating secrets beyond opaque [EE-2625] (#7709)
This commit is contained in:
parent
3b2f0ff9eb
commit
4e20d70a99
23 changed files with 659 additions and 135 deletions
|
@ -1,43 +1,134 @@
|
|||
import angular from 'angular';
|
||||
import _ from 'lodash-es';
|
||||
import { KubernetesConfigurationFormValues, KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues';
|
||||
import { KubernetesConfigurationTypes } from 'Kubernetes/models/configuration/models';
|
||||
import { KubernetesConfigurationKinds, KubernetesSecretTypes } from 'Kubernetes/models/configuration/models';
|
||||
import KubernetesConfigurationHelper from 'Kubernetes/helpers/configurationHelper';
|
||||
import KubernetesNamespaceHelper from 'Kubernetes/helpers/namespaceHelper';
|
||||
import { getServiceAccounts } from 'Kubernetes/rest/serviceAccount';
|
||||
|
||||
import { isConfigurationFormValid } from '../validation';
|
||||
|
||||
class KubernetesCreateConfigurationController {
|
||||
/* @ngInject */
|
||||
constructor($async, $state, $window, ModalService, Notifications, Authentication, KubernetesConfigurationService, KubernetesResourcePoolService) {
|
||||
constructor($async, $state, $window, ModalService, Notifications, Authentication, KubernetesConfigurationService, KubernetesResourcePoolService, EndpointProvider) {
|
||||
this.$async = $async;
|
||||
this.$state = $state;
|
||||
this.$window = $window;
|
||||
this.EndpointProvider = EndpointProvider;
|
||||
this.ModalService = ModalService;
|
||||
this.Notifications = Notifications;
|
||||
this.Authentication = Authentication;
|
||||
this.KubernetesConfigurationService = KubernetesConfigurationService;
|
||||
this.KubernetesResourcePoolService = KubernetesResourcePoolService;
|
||||
this.KubernetesConfigurationTypes = KubernetesConfigurationTypes;
|
||||
this.KubernetesConfigurationKinds = KubernetesConfigurationKinds;
|
||||
this.KubernetesSecretTypes = KubernetesSecretTypes;
|
||||
|
||||
this.onInit = this.onInit.bind(this);
|
||||
this.createConfigurationAsync = this.createConfigurationAsync.bind(this);
|
||||
this.getConfigurationsAsync = this.getConfigurationsAsync.bind(this);
|
||||
this.onResourcePoolSelectionChangeAsync = this.onResourcePoolSelectionChangeAsync.bind(this);
|
||||
this.onSecretTypeChange = this.onSecretTypeChange.bind(this);
|
||||
}
|
||||
|
||||
onChangeName() {
|
||||
const filteredConfigurations = _.filter(this.configurations, (config) => config.Namespace === this.formValues.ResourcePool.Namespace.Name);
|
||||
const filteredConfigurations = _.filter(
|
||||
this.configurations,
|
||||
(config) => config.Namespace === this.formValues.ResourcePool.Namespace.Name && config.Kind === this.formValues.Kind
|
||||
);
|
||||
this.state.alreadyExist = _.find(filteredConfigurations, (config) => config.Name === this.formValues.Name) !== undefined;
|
||||
}
|
||||
|
||||
onResourcePoolSelectionChange() {
|
||||
onChangeKind() {
|
||||
this.onChangeName();
|
||||
// if there is no data field, add one
|
||||
if (this.formValues.Data.length === 0) {
|
||||
this.formValues.Data.push(new KubernetesConfigurationFormValuesEntry());
|
||||
}
|
||||
// if changing back to a secret, that is a service account token, remove the data field
|
||||
if (this.formValues.Kind === this.KubernetesConfigurationKinds.SECRET) {
|
||||
this.onSecretTypeChange();
|
||||
} else {
|
||||
this.isDockerConfig = false;
|
||||
}
|
||||
}
|
||||
|
||||
async onResourcePoolSelectionChangeAsync() {
|
||||
try {
|
||||
this.onChangeName();
|
||||
this.availableServiceAccounts = await getServiceAccounts(this.environmentId, this.formValues.ResourcePool.Namespace.Name);
|
||||
this.formValues.ServiceAccountName = this.availableServiceAccounts.length > 0 ? this.availableServiceAccounts[0].metadata.name : '';
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable load service accounts');
|
||||
}
|
||||
}
|
||||
onResourcePoolSelectionChange() {
|
||||
this.$async(this.onResourcePoolSelectionChangeAsync);
|
||||
}
|
||||
|
||||
onSecretTypeChange() {
|
||||
switch (this.formValues.Type.value) {
|
||||
case KubernetesSecretTypes.OPAQUE.value:
|
||||
case KubernetesSecretTypes.CUSTOM.value:
|
||||
this.formValues.Data = this.formValues.Data.filter((entry) => entry.Value !== '');
|
||||
if (this.formValues.Data.length === 0) {
|
||||
this.addRequiredKeysToForm(['']);
|
||||
}
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
case KubernetesSecretTypes.SERVICEACCOUNTTOKEN.value:
|
||||
// data isn't required for service account tokens, so remove the data fields if they are empty
|
||||
this.addRequiredKeysToForm([]);
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
case KubernetesSecretTypes.DOCKERCONFIGJSON.value:
|
||||
this.addRequiredKeysToForm(['.dockerconfigjson']);
|
||||
this.state.isDockerConfig = true;
|
||||
break;
|
||||
case KubernetesSecretTypes.DOCKERCFG.value:
|
||||
this.addRequiredKeysToForm(['.dockercfg']);
|
||||
this.state.isDockerConfig = true;
|
||||
break;
|
||||
case KubernetesSecretTypes.BASICAUTH.value:
|
||||
this.addRequiredKeysToForm(['username', 'password']);
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
case KubernetesSecretTypes.SSHAUTH.value:
|
||||
this.addRequiredKeysToForm(['ssh-privatekey']);
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
case KubernetesSecretTypes.TLS.value:
|
||||
this.addRequiredKeysToForm(['tls.crt', 'tls.key']);
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
case KubernetesSecretTypes.BOOTSTRAPTOKEN.value:
|
||||
this.addRequiredKeysToForm(['token-id', 'token-secret']);
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
default:
|
||||
this.state.isDockerConfig = false;
|
||||
break;
|
||||
}
|
||||
this.isFormValid();
|
||||
}
|
||||
|
||||
addRequiredKeysToForm(keys) {
|
||||
// remove data entries that have an empty value
|
||||
this.formValues.Data = this.formValues.Data.filter((entry) => entry.Value);
|
||||
|
||||
keys.forEach((key) => {
|
||||
// if the key doesn't exist on the form, add a new formValues.Data entry
|
||||
if (!this.formValues.Data.some((data) => data.Key === key)) {
|
||||
this.formValues.Data.push(new KubernetesConfigurationFormValuesEntry());
|
||||
const index = this.formValues.Data.length - 1;
|
||||
this.formValues.Data[index].Key = key;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
isFormValid() {
|
||||
const uniqueCheck = !this.state.alreadyExist && this.state.isDataValid;
|
||||
if (this.formValues.IsSimple) {
|
||||
return this.formValues.Data.length > 0 && uniqueCheck;
|
||||
}
|
||||
return uniqueCheck;
|
||||
const [isValid, warningMessage] = isConfigurationFormValid(this.state.alreadyExist, this.state.isDataValid, this.formValues);
|
||||
this.state.secretWarningMessage = warningMessage;
|
||||
return isValid;
|
||||
}
|
||||
|
||||
async createConfigurationAsync() {
|
||||
|
@ -47,6 +138,7 @@ class KubernetesCreateConfigurationController {
|
|||
if (!this.formValues.IsSimple) {
|
||||
this.formValues.Data = KubernetesConfigurationHelper.parseYaml(this.formValues);
|
||||
}
|
||||
|
||||
await this.KubernetesConfigurationService.create(this.formValues);
|
||||
this.Notifications.success('Success', 'Configuration succesfully created');
|
||||
this.state.isEditorDirty = false;
|
||||
|
@ -87,10 +179,12 @@ class KubernetesCreateConfigurationController {
|
|||
alreadyExist: false,
|
||||
isDataValid: true,
|
||||
isEditorDirty: false,
|
||||
isDockerConfig: false,
|
||||
secretWarningMessage: '',
|
||||
};
|
||||
|
||||
this.formValues = new KubernetesConfigurationFormValues();
|
||||
this.formValues.Data.push(new KubernetesConfigurationFormValuesEntry());
|
||||
this.formValues.Data = [new KubernetesConfigurationFormValuesEntry()];
|
||||
|
||||
try {
|
||||
const resourcePools = await this.KubernetesResourcePoolService.get();
|
||||
|
@ -98,6 +192,10 @@ class KubernetesCreateConfigurationController {
|
|||
|
||||
this.formValues.ResourcePool = this.resourcePools[0];
|
||||
await this.getConfigurations();
|
||||
|
||||
this.environmentId = this.EndpointProvider.endpointID();
|
||||
this.availableServiceAccounts = await getServiceAccounts(this.environmentId, this.resourcePools[0].Namespace.Name);
|
||||
this.formValues.ServiceAccountName = this.availableServiceAccounts.length > 0 ? this.availableServiceAccounts[0].metadata.name : '';
|
||||
} catch (err) {
|
||||
this.Notifications.error('Failure', err, 'Unable to load view data');
|
||||
} finally {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue