mirror of https://github.com/rancher/ui.git
360 lines
11 KiB
JavaScript
360 lines
11 KiB
JavaScript
import Component from '@ember/component';
|
|
import layout from './template';
|
|
import {
|
|
computed, get, set, setProperties, observer
|
|
} from '@ember/object';
|
|
import { inject as service } from '@ember/service';
|
|
import { alias } from '@ember/object/computed';
|
|
import { isEmpty } from '@ember/utils';
|
|
import C from 'ui/utils/constants';
|
|
import { azure as AzureInfo } from './cloud-provider-info';
|
|
import { next } from '@ember/runloop';
|
|
import { debouncedObserver } from 'ui/utils/debounce';
|
|
|
|
const azureDefaults = C.AZURE_DEFAULTS;
|
|
const GENERIC_PATH = 'cluster.rancherKubernetesEngineConfig.cloudProvider.cloudConfig';
|
|
const AWS_PATH = 'cluster.rancherKubernetesEngineConfig.cloudProvider.awsCloudProvider';
|
|
const AZURE_PATH = 'cluster.rancherKubernetesEngineConfig.cloudProvider.azureCloudProvider';
|
|
|
|
export default Component.extend({
|
|
globalStore: service(),
|
|
settings: service(),
|
|
growl: service(),
|
|
layout,
|
|
configType: null,
|
|
cluster: null,
|
|
driver: null,
|
|
selectedCloudProvider: 'none',
|
|
mode: 'new',
|
|
hasBuiltIn: false,
|
|
configAnswers: null,
|
|
clusterTemplateCreate: false,
|
|
configVariable: null,
|
|
questions: null,
|
|
azureDefaults,
|
|
azureDescriptions: AzureInfo,
|
|
|
|
configName: alias('cluster.rancherKubernetesEngineConfig.cloudProvider.name'),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
|
|
const cloudProviderName = get(this, 'cluster.rancherKubernetesEngineConfig.cloudProvider.name');
|
|
|
|
if ( cloudProviderName === 'aws' ) {
|
|
setProperties(this, {
|
|
selectedCloudProvider: 'amazonec2',
|
|
configAnswers: get(this, AWS_PATH)
|
|
});
|
|
} else if ( cloudProviderName === 'azure' ) {
|
|
const reorderedAnswers = this.sortAzureFields(this.globalStore.getById('schema', 'azurecloudprovider'), get(this, AZURE_PATH));
|
|
|
|
this.setCpFields(`azureCloudProvider`, reorderedAnswers);
|
|
|
|
setProperties(this, {
|
|
selectedCloudProvider: 'azure',
|
|
configAnswers: reorderedAnswers,
|
|
});
|
|
} else if ( !cloudProviderName ) {
|
|
set(this, 'selectedCloudProvider', 'none');
|
|
} else {
|
|
setProperties(this, {
|
|
selectedCloudProvider: 'generic',
|
|
configAnswers: get(this, GENERIC_PATH)
|
|
});
|
|
}
|
|
},
|
|
|
|
driverDidChange: observer('driver', function() {
|
|
set(this, 'selectedCloudProvider', 'none');
|
|
}),
|
|
|
|
modeChanged: observer('selectedCloudProvider', function() {
|
|
let selectedCloudProvider = get(this, 'selectedCloudProvider');
|
|
|
|
if ( selectedCloudProvider !== 'none' ) {
|
|
this.constructConfig();
|
|
} else {
|
|
let config = get(this, 'cluster.rancherKubernetesEngineConfig');
|
|
|
|
if (config && get(config, 'cloudProvider')) {
|
|
delete config.cloudProvider;
|
|
}
|
|
}
|
|
}),
|
|
|
|
harvesterCloudProviderDisabledChange: observer('harvesterCloudProviderDisabled', function() {
|
|
if (get(this, 'harvesterCloudProviderDisabled')) {
|
|
set(this, 'selectedCloudProvider', 'none')
|
|
}
|
|
}),
|
|
|
|
configAnswersDidChange: debouncedObserver('mappedConfigAnswers.@each.{key,value}', function() {
|
|
const mappedAnswers = get(this, 'mappedConfigAnswers');
|
|
const selectedCloudProvider = get(this, 'selectedCloudProvider');
|
|
const configAnswersOut = {};
|
|
let pathForSet;
|
|
|
|
switch (selectedCloudProvider) {
|
|
case 'azure':
|
|
pathForSet = AZURE_PATH;
|
|
|
|
break;
|
|
|
|
case 'amazonec2':
|
|
pathForSet = AWS_PATH;
|
|
|
|
break;
|
|
|
|
default:
|
|
pathForSet = GENERIC_PATH;
|
|
|
|
break;
|
|
}
|
|
|
|
mappedAnswers.forEach((answer) => {
|
|
set(configAnswersOut, answer.key, answer.value);
|
|
});
|
|
|
|
set(this, pathForSet, configAnswersOut);
|
|
}),
|
|
|
|
selectedCloudProviderOverrideAvailable: computed(
|
|
'applyClusterTemplate', 'clusterTemplateCreate', 'clusterTemplateRevision.{id,questions}', 'configName', 'selectedCloudProvider', 'isDestroying', 'isDestroyed',
|
|
function() {
|
|
let { clusterTemplateRevision, applyClusterTemplate } = this;
|
|
|
|
if (applyClusterTemplate && clusterTemplateRevision) {
|
|
if (clusterTemplateRevision.questions) {
|
|
let found = clusterTemplateRevision.questions.filter((ctr) => {
|
|
return ctr.variable.includes('rancherKubernetesEngineConfig.cloudProvider');
|
|
});
|
|
|
|
if (found.length === 0 && this.selectedCloudProvider !== 'none') {
|
|
set(this, 'selectedCloudProvider', 'none');
|
|
}
|
|
|
|
return found.length >= 1;
|
|
} else {
|
|
if (this.configName) {
|
|
next(() => {
|
|
if (this.isDestroyed || this.isDestroying) {
|
|
return;
|
|
}
|
|
|
|
set(this, 'selectedCloudProvider', this.configName);
|
|
});
|
|
}
|
|
}
|
|
} else {
|
|
next(() => {
|
|
if (!this.configName) {
|
|
if (this.isDestroyed || this.isDestroying) {
|
|
return;
|
|
}
|
|
|
|
set(this, 'selectedCloudProvider', this.selectedCloudProvider === 'generic' ? 'generic' : 'none');
|
|
}
|
|
});
|
|
}
|
|
|
|
return false;
|
|
}),
|
|
|
|
isCreateClusterOrClusterTemplate: computed('applyClusterTemplate', function() {
|
|
const { applyClusterTemplate } = this;
|
|
|
|
if (applyClusterTemplate) {
|
|
return false;
|
|
} else {
|
|
return true;
|
|
}
|
|
}),
|
|
|
|
mappedConfigAnswers: computed('configAnswers', function() {
|
|
const configAnswers = (get(this, 'configAnswers') || {});
|
|
const out = [];
|
|
|
|
Object.keys(configAnswers).forEach((answerKey) => {
|
|
out.push({
|
|
key: answerKey,
|
|
value: configAnswers[answerKey]
|
|
});
|
|
});
|
|
|
|
return out;
|
|
}),
|
|
|
|
showVsphereHelperText: computed('selectedCloudProvider', 'driver', function() {
|
|
const driver = get(this, 'driver');
|
|
const selectedCloudProvider = get(this, 'selectedCloudProvider');
|
|
|
|
return (driver === 'custom' || driver === 'vmwarevsphere') &&
|
|
(selectedCloudProvider === 'external')
|
|
}),
|
|
|
|
harvesterCloudProviderDisabled: computed('cluster.name', 'model.{harvesterNodeTemplateId,nodeTemplates}', function() {
|
|
const nodeTemplate = (get(this, 'model.nodeTemplates') || []).find((n) => n.id === get(this, 'model.harvesterNodeTemplateId')) || {}
|
|
const cloudCredentialId = get(nodeTemplate, 'cloudCredentialId')
|
|
const cloudCredential = get(this, 'globalStore').getById('cloudCredential', cloudCredentialId) || {}
|
|
const isExternalCredential = get(cloudCredential, 'harvestercredentialConfig.clusterType') === 'external'
|
|
|
|
return !get(this, 'model.harvesterNodeTemplateId') || !get(this, 'cluster.name') || isExternalCredential
|
|
}),
|
|
|
|
checkDefaults(record) {
|
|
get(this, 'azureDefaults').forEach((def) => {
|
|
if (isEmpty(record[def])) {
|
|
set(record, def, null);
|
|
}
|
|
});
|
|
},
|
|
|
|
sortAzureFields(schema, answers) {
|
|
const schemaFields = schema.getFieldNames();
|
|
const resourceFields = get(schema, 'resourceFields');
|
|
const descriptionInfo = AzureInfo;
|
|
const requiredFields = schemaFields.filter((item) => get(descriptionInfo, `${ item }.required`)).sort();
|
|
const keysWithoutFields = schemaFields.filter((item) => !requiredFields.includes(item)).sort();
|
|
const prioritizedKeys = keysWithoutFields.unshiftObjects(requiredFields);
|
|
const reorderedFields = {};
|
|
|
|
// Hack the schema to be required so validation will require them
|
|
requiredFields.forEach((key) => {
|
|
schema.resourceFields[key].required = true;
|
|
});
|
|
|
|
prioritizedKeys.forEach((key) => {
|
|
let resourceField = get(resourceFields, key);
|
|
|
|
if (answers && answers.hasOwnProperty(key)) {
|
|
set(reorderedFields, key, get(answers, key));
|
|
} else {
|
|
if (get(resourceField, 'type') === 'password') {
|
|
set(reorderedFields, key, null);
|
|
}
|
|
}
|
|
});
|
|
|
|
return reorderedFields;
|
|
},
|
|
|
|
constructConfig() {
|
|
let nue = {};
|
|
let selectedCloudProvider = get(this, 'selectedCloudProvider');
|
|
let cluster = get(this, 'cluster');
|
|
let config = get(cluster, 'rancherKubernetesEngineConfig') || set(cluster, 'rancherKubernetesEngineConfig', {});
|
|
let harvesterCluster = {}
|
|
let nodeTemplate
|
|
|
|
switch (selectedCloudProvider) {
|
|
case 'azure':
|
|
|
|
nue = get(this, 'globalStore').createRecord({ type: 'azureCloudProvider' });
|
|
|
|
delete nue.type;
|
|
|
|
this.checkDefaults(nue);
|
|
|
|
nue = this.sortAzureFields(this.globalStore.getById('schema', 'azurecloudprovider'), nue);
|
|
|
|
set(config, 'cloudProvider', get(this, 'globalStore').createRecord({
|
|
type: 'cloudProvider',
|
|
name: 'azure',
|
|
azureCloudProvider: nue
|
|
}));
|
|
|
|
setProperties(this, {
|
|
hasBuiltIn: true,
|
|
'cluster.rancherKubernetesEngineConfig': config,
|
|
configAnswers: nue,
|
|
});
|
|
|
|
break;
|
|
|
|
case 'amazonec2':
|
|
|
|
nue = get(this, 'globalStore').createRecord({ type: 'awsCloudProvider' });
|
|
|
|
set(config, 'cloudProvider', get(this, 'globalStore').createRecord({
|
|
type: 'cloudProvider',
|
|
name: 'aws',
|
|
awsCloudProvider: nue
|
|
}));
|
|
|
|
set(this, 'configAnswers', nue);
|
|
|
|
break;
|
|
|
|
case 'harvester':
|
|
harvesterCluster = this.getHarvesterCluster()
|
|
|
|
set(config, 'cloudProvider', get(this, 'globalStore').createRecord({
|
|
type: 'cloudProvider',
|
|
name: 'harvester',
|
|
harvesterCloudProvider: nue,
|
|
}));
|
|
|
|
set(this, 'configAnswers', nue);
|
|
|
|
nodeTemplate = (get(this, 'model.nodeTemplates') || []).find((n) => n.id === get(this, 'model.harvesterNodeTemplateId'))
|
|
|
|
get(this, 'globalStore').rawRequest({
|
|
url: `/k8s/clusters/${ harvesterCluster.id }/v1/harvester/kubeconfig`,
|
|
method: 'POST',
|
|
data: {
|
|
clusterRoleName: 'harvesterhci.io:cloudprovider',
|
|
namespace: get(nodeTemplate, 'harvesterConfig.vmNamespace'),
|
|
serviceAccountName: get(cluster, 'name'),
|
|
},
|
|
}).then((obj) => {
|
|
set(config, 'cloudProvider.harvesterCloudProvider.cloudConfig', get(obj, 'body'))
|
|
})
|
|
.catch((err) => {
|
|
get(this, 'growl').fromError('Error getting kubeconfig file', err);
|
|
})
|
|
|
|
break;
|
|
|
|
case 'external':
|
|
|
|
set(config, 'cloudProvider', get(this, 'globalStore').createRecord({
|
|
type: 'cloudProvider',
|
|
name: 'external',
|
|
}));
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
set(config, 'cloudProvider', get(this, 'globalStore').createRecord({
|
|
type: 'cloudProvider',
|
|
cloudConfig: nue
|
|
}));
|
|
|
|
set(this, 'configAnswers', nue);
|
|
|
|
break;
|
|
}
|
|
},
|
|
|
|
setCpFields() {
|
|
throw new Error('setCpFields action is required!');
|
|
},
|
|
|
|
addOverride() {
|
|
throw new Error('addOverride action is required!');
|
|
},
|
|
|
|
getHarvesterCluster() {
|
|
const nodeTemplate = (get(this, 'model.nodeTemplates') || []).find((n) => n.id === get(this, 'model.harvesterNodeTemplateId'))
|
|
const cloudCredentialId = get(nodeTemplate, 'cloudCredentialId')
|
|
const cloudCredential = get(this, 'globalStore').getById('cloudCredential', cloudCredentialId)
|
|
const clusterId = get(cloudCredential, 'harvestercredentialConfig.clusterId')
|
|
const harvesterCluster = get(this, 'globalStore').getById('cluster', clusterId)
|
|
|
|
return harvesterCluster
|
|
},
|
|
});
|