import angular from 'angular';
import _ from 'lodash-es';
import { KubernetesConfigurationFormValues, KubernetesConfigurationFormValuesEntry } from 'Kubernetes/models/configuration/formvalues';
import { KubernetesConfigurationKinds, KubernetesSecretTypeOptions } 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, 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.KubernetesConfigurationKinds = KubernetesConfigurationKinds;
this.KubernetesSecretTypeOptions = KubernetesSecretTypeOptions;
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 && config.Kind === this.formValues.Kind
);
this.state.alreadyExist = _.find(filteredConfigurations, (config) => config.Name === this.formValues.Name) !== undefined;
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.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) {
case KubernetesSecretTypeOptions.OPAQUE.value:
case KubernetesSecretTypeOptions.CUSTOM.value:
this.formValues.Data = this.formValues.Data.filter((entry) => entry.Value !== '');
this.addRequiredKeysToForm(['']);
this.state.isDockerConfig = false;
break;
case KubernetesSecretTypeOptions.SERVICEACCOUNTTOKEN.value:
// data isn't required for service account tokens, so remove the data fields if they are empty
this.addRequiredKeysToForm([]);
case KubernetesSecretTypeOptions.DOCKERCONFIGJSON.value:
this.addRequiredKeysToForm(['.dockerconfigjson']);
this.state.isDockerConfig = true;
case KubernetesSecretTypeOptions.DOCKERCFG.value:
this.addRequiredKeysToForm(['.dockercfg']);
case KubernetesSecretTypeOptions.BASICAUTH.value:
this.addRequiredKeysToForm(['username', 'password']);
case KubernetesSecretTypeOptions.SSHAUTH.value:
this.addRequiredKeysToForm(['ssh-privatekey']);
case KubernetesSecretTypeOptions.TLS.value:
this.addRequiredKeysToForm(['tls.crt', 'tls.key']);
case KubernetesSecretTypeOptions.BOOTSTRAPTOKEN.value:
this.addRequiredKeysToForm(['token-id', 'token-secret']);
default:
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)) {
const index = this.formValues.Data.length - 1;
this.formValues.Data[index].Key = key;
});
isFormValid() {
const [isValid, warningMessage] = isConfigurationFormValid(this.state.alreadyExist, this.state.isDataValid, this.formValues);
this.state.secretWarningMessage = warningMessage;
return isValid;
async createConfigurationAsync() {
this.state.actionInProgress = true;
this.formValues.ConfigurationOwner = this.Authentication.getUserDetails().username;
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;
this.$state.go('kubernetes.configurations');
this.Notifications.error('Failure', err, 'Unable to create configuration');
} finally {
this.state.actionInProgress = false;
createConfiguration() {
return this.$async(this.createConfigurationAsync);
async getConfigurationsAsync() {
this.configurations = await this.KubernetesConfigurationService.get();
this.Notifications.error('Failure', err, 'Unable to retrieve configurations');
getConfigurations() {
return this.$async(this.getConfigurationsAsync);
async uiCanExit() {
if (!this.formValues.IsSimple && this.formValues.DataYaml && this.state.isEditorDirty) {
return this.ModalService.confirmWebEditorDiscard();
async onInit() {
this.state = {
actionInProgress: false,
viewReady: false,
alreadyExist: false,
isDataValid: true,
isEditorDirty: false,
isDockerConfig: false,
secretWarningMessage: '',
};
this.formValues = new KubernetesConfigurationFormValues();
this.formValues.Data = [new KubernetesConfigurationFormValuesEntry()];
const resourcePools = await this.KubernetesResourcePoolService.get();
this.resourcePools = _.filter(resourcePools, (resourcePool) => !KubernetesNamespaceHelper.isSystemNamespace(resourcePool.Namespace.Name));
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.Notifications.error('Failure', err, 'Unable to load view data');
this.state.viewReady = true;
this.$window.onbeforeunload = () => {
return '';
$onInit() {
return this.$async(this.onInit);
$onDestroy() {
export default KubernetesCreateConfigurationController;
angular.module('portainer.kubernetes').controller('KubernetesCreateConfigurationController', KubernetesCreateConfigurationController);