mirror of https://github.com/rancher/ui.git
818 lines
22 KiB
JavaScript
818 lines
22 KiB
JavaScript
import { isArray } from '@ember/array';
|
|
import Component from '@ember/component';
|
|
import {
|
|
computed, get, observer, set, setProperties
|
|
} from '@ember/object';
|
|
import { alias, equal, not, union } from '@ember/object/computed';
|
|
import { inject as service } from '@ember/service';
|
|
import { classify } from '@ember/string';
|
|
import { isEmpty } from '@ember/utils';
|
|
import $ from 'jquery';
|
|
import { allSettled, Promise } from 'rsvp';
|
|
import { coerce, lt, minor } from 'semver';
|
|
import ClusterDriver from 'shared/mixins/cluster-driver';
|
|
import { EKS_REGIONS, EKS_VERSIONS, nameFromResource } from 'shared/utils/amazon';
|
|
import { randomStr } from 'shared/utils/util';
|
|
import { DEFAULT_EKS_CONFIG, DEFAULT_NODE_GROUP_CONFIG, DEFAULT_USER_DATA } from 'ui/models/cluster';
|
|
import layout from './template';
|
|
|
|
|
|
export default Component.extend(ClusterDriver, {
|
|
intl: service(),
|
|
versionChoiceService: service('version-choices'),
|
|
layout,
|
|
|
|
// config computed prop is setup in the clusterDriver mixin on init
|
|
configField: 'eksConfig',
|
|
step: 1,
|
|
serviceRoles: null,
|
|
nodeInstanceRoles: null,
|
|
securityGroups: null,
|
|
whichSecurityGroup: 'default',
|
|
errors: null,
|
|
otherErrors: null,
|
|
clusterErrors: null,
|
|
credentialError: null,
|
|
serviceRoleMode: 'default',
|
|
vpcSubnetMode: 'default',
|
|
allImages: null,
|
|
allSecurityGroups: null,
|
|
allKeyPairs: null,
|
|
allLaunchTemplates: null,
|
|
selectedServiceRole: null,
|
|
selectedGroupedDetails: null,
|
|
kmsKeys: null,
|
|
instanceTypes: null,
|
|
originalSecret: null,
|
|
|
|
cloudWatchAuditEnabled: false,
|
|
cloudWatchApiEnabled: false,
|
|
cloudWatchSchedulerEnabled: false,
|
|
cloudWatchControllerManagerEnabled: false,
|
|
cloudWatchAuthenticatorEnabled: false,
|
|
loadFailedKmsKeys: false,
|
|
isPostSave: false,
|
|
|
|
regionChoices: EKS_REGIONS,
|
|
kubernetesVersionContent: EKS_VERSIONS,
|
|
|
|
isNew: not('editing'),
|
|
isCustomSecurityGroup: equal('whichSecurityGroup', 'custom'),
|
|
editing: equal('mode', 'edit'),
|
|
clusterState: alias('model.originalCluster.state'),
|
|
allErrors: union('errors', 'otherErrors', 'clusterErrors'),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
const { model: { cloudCredentials } } = this;
|
|
|
|
setProperties(this, {
|
|
allSubnets: [],
|
|
clients: {},
|
|
clusterErrors: [],
|
|
errors: [],
|
|
kmsKeys: [],
|
|
otherErrors: [],
|
|
instanceTypes: [],
|
|
});
|
|
|
|
let config = get(this, 'cluster.eksConfig');
|
|
|
|
if ( !config ) {
|
|
const kubernetesVersion = this.kubernetesVersionContent.firstObject;
|
|
const ngConfig = { ...DEFAULT_NODE_GROUP_CONFIG, };
|
|
|
|
set(ngConfig, 'launchTemplate', this.globalStore.createRecord({
|
|
name: '',
|
|
id: null,
|
|
version: null,
|
|
type: 'launchTemplate'
|
|
}));
|
|
|
|
set(ngConfig, 'version', kubernetesVersion);
|
|
setProperties(DEFAULT_EKS_CONFIG, {
|
|
kubernetesVersion,
|
|
nodeGroups: [this.globalStore.createRecord(ngConfig)],
|
|
})
|
|
|
|
config = this.globalStore.createRecord(DEFAULT_EKS_CONFIG);
|
|
|
|
if (!isEmpty(cloudCredentials)) {
|
|
const singleMatch = cloudCredentials.find((cc) => {
|
|
if (!isEmpty(get(cc, 'amazonec2credentialConfig'))) {
|
|
return true;
|
|
}
|
|
});
|
|
|
|
if (singleMatch) {
|
|
set(config, 'amazonCredentialSecret', singleMatch.id);
|
|
}
|
|
}
|
|
|
|
set(this, 'cluster.eksConfig', config);
|
|
} else {
|
|
this.syncUpstreamConfig();
|
|
|
|
const initalTags = { ...( config.tags || {} ) };
|
|
|
|
set(this, 'initalTags', initalTags);
|
|
|
|
if (this.mode === 'edit') {
|
|
( config.loggingTypes || [] ).forEach((option) => {
|
|
set(this, `cloudWatch${ classify(option) }Enabled`, true);
|
|
});
|
|
}
|
|
|
|
if (!isEmpty(config?.subnets)) {
|
|
set(this, 'vpcSubnetMode', 'custom');
|
|
}
|
|
}
|
|
|
|
let cur = config?.amazonCredentialSecret;
|
|
|
|
if ( cur && !cur.startsWith('cattle-global-data:') ) {
|
|
cur = `cattle-global-data:${ cur }`;
|
|
}
|
|
|
|
set(this, 'originalSecret', cur);
|
|
},
|
|
|
|
willDestroyElement() {
|
|
setProperties(this, {
|
|
step: 1,
|
|
clients: null,
|
|
allSubnets: null,
|
|
instanceTypes: [],
|
|
});
|
|
},
|
|
|
|
actions: {
|
|
getAuthCreds() {
|
|
return this.authCreds()
|
|
},
|
|
addNodeGroup() {
|
|
let { config } = this;
|
|
let { nodeGroups = [], kubernetesVersion } = config;
|
|
const ngConfig = { ...DEFAULT_NODE_GROUP_CONFIG, };
|
|
|
|
set(ngConfig, 'launchTemplate', this.globalStore.createRecord({
|
|
name: '',
|
|
id: null,
|
|
version: null,
|
|
type: 'launchTemplate',
|
|
}));
|
|
|
|
if (!isArray(nodeGroups)) {
|
|
nodeGroups = [];
|
|
}
|
|
|
|
const nodeGroup = this.globalStore.createRecord(ngConfig);
|
|
|
|
set(nodeGroup, 'version', kubernetesVersion);
|
|
|
|
nodeGroups.pushObject(nodeGroup);
|
|
|
|
set(this, 'config.nodeGroups', nodeGroups);
|
|
},
|
|
|
|
removeNodeGroup(nodeGroup) {
|
|
let { config: { nodeGroups = [] } } = this;
|
|
|
|
if (!isEmpty(nodeGroups)) {
|
|
nodeGroups.removeObject(nodeGroup);
|
|
}
|
|
|
|
set(this, 'config.nodeGroups', nodeGroups);
|
|
},
|
|
|
|
setTags(section) {
|
|
set(this, 'config.tags', section);
|
|
},
|
|
|
|
finishAndSelectCloudCredential(cred) {
|
|
if (cred) {
|
|
set(this, 'config.amazonCredentialSecret', get(cred, 'id'));
|
|
set(this, 'credentialError', false);
|
|
|
|
|
|
this.send('startAwsConfiguration');
|
|
}
|
|
},
|
|
|
|
multiSecurityGroupSelect() {
|
|
let options = Array.prototype.slice.call($('.existing-security-groups')[0], 0);
|
|
let selectedOptions = [];
|
|
|
|
options.filterBy('selected', true).forEach((cap) => {
|
|
return selectedOptions.push(cap.value);
|
|
});
|
|
|
|
set(this, 'config.securityGroups', selectedOptions);
|
|
},
|
|
|
|
multiSubnetGroupSelect() {
|
|
let options = Array.prototype.slice.call($('.existing-subnet-groups')[0], 0);
|
|
let selectedOptions = [];
|
|
|
|
options.filterBy('selected', true).forEach((cap) => {
|
|
return selectedOptions.push(cap.value);
|
|
});
|
|
|
|
set(this, 'config.subnets', selectedOptions);
|
|
},
|
|
|
|
async startAwsConfiguration(cb) {
|
|
const errors = [];
|
|
const { mode } = this;
|
|
let step = 2;
|
|
|
|
|
|
try {
|
|
await allSettled([
|
|
this.loadRoles(),
|
|
this.loadKMSKeys(),
|
|
this.loadInstanceTypes(),
|
|
this.loadLaunchTemplates(),
|
|
this.loadKeyPairs(),
|
|
]);
|
|
|
|
if (mode === 'edit') {
|
|
step = 4;
|
|
}
|
|
|
|
if (get(this, 'credentialError')) {
|
|
const errors = this.errors || [];
|
|
|
|
errors.unshift(this.intl.t('nodeDriver.amazoneks.access.credentialError'))
|
|
|
|
set(this, 'errors', errors);
|
|
step = 1;
|
|
}
|
|
|
|
set(this, 'step', step);
|
|
|
|
if (cb) {
|
|
cb();
|
|
}
|
|
|
|
return true;
|
|
} catch (err) {
|
|
errors.pushObject(err.message);
|
|
|
|
set(this, 'errors', errors);
|
|
|
|
return cb ? cb(false, err) : err;
|
|
}
|
|
},
|
|
|
|
async loadSubnets(cb = function() {}) {
|
|
const { selectedServiceRole } = this;
|
|
|
|
if (!isEmpty(selectedServiceRole)) {
|
|
set(this, 'config.serviceRole', selectedServiceRole);
|
|
}
|
|
|
|
try {
|
|
const subnets = await this.describeResource(['EC2', 'describeSubnets', 'Subnets']);
|
|
|
|
setProperties(this, {
|
|
allSubnets: subnets,
|
|
step: 3,
|
|
})
|
|
|
|
cb();
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
|
|
cb(false, err);
|
|
}
|
|
},
|
|
|
|
async setSubnets(cb) {
|
|
try {
|
|
if (get(this, 'vpcSubnetMode') === 'custom') {
|
|
await this.loadSecurityGroups();
|
|
}
|
|
|
|
set(this, 'step', 4);
|
|
|
|
cb();
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
|
|
cb(false, err);
|
|
}
|
|
},
|
|
},
|
|
|
|
clusterChanged: observer('originalCluster.state', function() {
|
|
if ( get(this, 'step') >= 2 ) {
|
|
const state = get(this, 'originalCluster.state')
|
|
|
|
if ( !['active', 'pending', 'initializing', 'waiting'].includes(state) ) {
|
|
if (this.close) {
|
|
this.close();
|
|
}
|
|
}
|
|
}
|
|
}),
|
|
|
|
resetKms: observer('config.secretsEncryption', function() {
|
|
if (!get(this, 'config.secretsEncryption')) {
|
|
set(this, 'config.kmsKey', null);
|
|
}
|
|
}),
|
|
|
|
cloudWatchLoggingChanged: observer(
|
|
'cloudWatchApiEnabled',
|
|
'cloudWatchAuditEnabled',
|
|
'cloudWatchAuthenticatorEnabled',
|
|
'cloudWatchControllerManagerEnabled',
|
|
'cloudWatchSchedulerEnabled',
|
|
function() {
|
|
let { config: { loggingTypes = [] } } = this;
|
|
const logOpts = ['audit', 'api', 'scheduler', 'controllerManager', 'authenticator'];
|
|
|
|
if (!isArray(loggingTypes)) {
|
|
loggingTypes = [];
|
|
}
|
|
|
|
logOpts.forEach((option) => {
|
|
const value = get(this, `cloudWatch${ classify(option) }Enabled`);
|
|
|
|
if (value) {
|
|
loggingTypes.addObject(option);
|
|
} else {
|
|
loggingTypes.removeObject(option);
|
|
}
|
|
});
|
|
|
|
set(this, 'config.loggingTypes', loggingTypes);
|
|
}),
|
|
|
|
serviceRoleModeDidChange: observer('serviceRoleMode', function() {
|
|
const mode = get(this, 'serviceRoleMode');
|
|
|
|
if ( mode === 'custom' ) {
|
|
const role = get(this, 'serviceRoles.firstObject.RoleName');
|
|
|
|
if ( role ) {
|
|
set(this, 'selectedServiceRole', role);
|
|
}
|
|
} else {
|
|
set(this, 'selectedServiceRole', null);
|
|
}
|
|
}),
|
|
|
|
postSaveChanged: observer('isPostSave', function() {
|
|
const {
|
|
isNew,
|
|
isPostSave,
|
|
config: { privateAccess, publicAccess }
|
|
} = this;
|
|
|
|
if (!publicAccess && privateAccess && isPostSave) {
|
|
if (isNew) {
|
|
set(this, 'step', 5);
|
|
} else {
|
|
this.close();
|
|
}
|
|
} else {
|
|
this.close();
|
|
}
|
|
}),
|
|
|
|
importedClusterIsPending: computed('clusterIsPending', 'model.originalCluster', function() {
|
|
const { clusterIsPending } = this;
|
|
const originalCluster = get(this, 'model.originalCluster');
|
|
const ourClusterSpec = get(( originalCluster ?? {} ), 'eksConfig');
|
|
const upstreamSpec = get(( originalCluster ?? {} ), 'eksStatus.upstreamSpec');
|
|
|
|
return clusterIsPending && get(ourClusterSpec, 'imported') && !isEmpty(upstreamSpec);
|
|
}),
|
|
|
|
clusterIsPending: computed('clusterState', function() {
|
|
const { clusterState } = this;
|
|
|
|
return ['pending', 'provisioning', 'waiting'].includes(clusterState);
|
|
}),
|
|
|
|
cloudCredentials: computed('globalStore', 'model.cloudCredentials', 'originalSecret', function() {
|
|
const { model: { cloudCredentials } } = this;
|
|
|
|
const out = cloudCredentials.filter((cc) => !isEmpty(get(cc, 'amazonec2credentialConfig')));
|
|
|
|
if ( this.originalSecret && !out.find((x) => x.id === this.originalSecret ) ) {
|
|
const obj = this.globalStore.createRecord({
|
|
name: `${ this.originalSecret.replace(/^cattle-global-data:/, '') } (current)`,
|
|
id: this.originalSecret,
|
|
type: 'cloudCredential',
|
|
amazonec2credentialConfig: {},
|
|
});
|
|
|
|
out.push(obj);
|
|
}
|
|
|
|
return out;
|
|
}),
|
|
|
|
selectedCloudCredential: computed('cloudCredentials', 'config.amazonCredentialSecret', function() {
|
|
const cur = this.config?.amazonCredentialSecret;
|
|
const cloudCredentials = this.cloudCredentials;
|
|
|
|
if (isEmpty(cloudCredentials) && isEmpty(cur)) {
|
|
return null;
|
|
} else {
|
|
return cloudCredentials.findBy('id', cur.includes('cattle-global-data:') ? cur : `cattle-global-data:${ cur }`);
|
|
}
|
|
}),
|
|
|
|
selectedSubnets: computed('config.subnets.[]', 'primaryResource.eksStatus.subnets.[]', function() {
|
|
const {
|
|
config: { subnets },
|
|
primaryResource: { eksStatus: { subnets: generatedSubnets } = { } },
|
|
} = this;
|
|
|
|
if (isEmpty(subnets)) {
|
|
if (!isEmpty(generatedSubnets)) {
|
|
return generatedSubnets;
|
|
}
|
|
|
|
return [];
|
|
}
|
|
|
|
return subnets;
|
|
}),
|
|
|
|
disableVersionSelect: computed('', 'config.kubernetesVersion', 'nodeGroupsVersionCollection', function() {
|
|
const kubernetesVersion = get(this, 'config.kubernetesVersion');
|
|
|
|
return get(this, 'nodeGroupsVersionCollection').any((version) => lt(coerce(version), coerce(kubernetesVersion)));
|
|
}),
|
|
|
|
nodeGroupsVersionCollection: computed('config.nodeGroups.@.eachversion', function() {
|
|
return (get(this, 'config.nodeGroups') || []).map((ng) => ng.version).uniq();
|
|
}),
|
|
|
|
versionChoices: computed('editing', 'kubernetesVersionContent', 'nodeGroupsVersionCollection.[]', function() {
|
|
const {
|
|
config,
|
|
intl,
|
|
kubernetesVersionContent,
|
|
mode,
|
|
} = this;
|
|
let { kubernetesVersion: initialVersion } = config;
|
|
|
|
if (isEmpty(initialVersion)) {
|
|
initialVersion = kubernetesVersionContent[0];
|
|
}
|
|
|
|
const versionChoices = this.versionChoiceService.parseCloudProviderVersionChoices(kubernetesVersionContent.slice(), initialVersion, mode);
|
|
|
|
// only EKS and edit - user can only upgrade a single minor version at a time
|
|
if (this.editing) {
|
|
if (!versionChoices.findBy('value', initialVersion)) {
|
|
versionChoices.unshift({
|
|
label: initialVersion,
|
|
value: initialVersion,
|
|
});
|
|
}
|
|
|
|
const initalMinorVersion = parseInt(minor(coerce(initialVersion)), 10);
|
|
|
|
versionChoices.forEach((vc) => {
|
|
const vcMinorV = parseInt(minor(coerce(vc.value)), 10);
|
|
const diff = vcMinorV - initalMinorVersion;
|
|
|
|
if (diff > 1) {
|
|
setProperties(vc, {
|
|
disabled: true,
|
|
label: `${ vc.label } ${ intl.t('formVersions.eks.label') }`,
|
|
});
|
|
}
|
|
})
|
|
}
|
|
|
|
return versionChoices;
|
|
}),
|
|
|
|
filteredKeyPairs: computed('allKeyPairs', function() {
|
|
return ( get(this, 'allKeyPairs') ?? [] ).sortBy('KeyName');
|
|
}),
|
|
|
|
groupedSubnets: computed('filteredSubnets.[]', function() {
|
|
const { filteredSubnets } = this;
|
|
const out = [];
|
|
|
|
filteredSubnets.forEach((subnet) => {
|
|
var vpc = get(subnet, 'group');
|
|
|
|
if ( vpc ) {
|
|
var group = out.filterBy('group', vpc)[0];
|
|
|
|
if ( !group ) {
|
|
group = {
|
|
group: vpc,
|
|
subnets: []
|
|
};
|
|
out.push(group);
|
|
}
|
|
|
|
group.subnets.push(subnet);
|
|
}
|
|
});
|
|
|
|
return out.sortBy('group');
|
|
}),
|
|
|
|
filteredSubnets: computed('allSubnets', function() {
|
|
return get(this, 'allSubnets').map( (subnet) => {
|
|
return {
|
|
subnetName: nameFromResource(subnet, 'SubnetId'),
|
|
subnetId: subnet.SubnetId,
|
|
group: subnet.VpcId
|
|
}
|
|
}).sortBy('subnetName');
|
|
}),
|
|
|
|
filteredSecurityGroups: computed('allSecurityGroups', 'config.subnets.[]', function() {
|
|
const {
|
|
config: { subnets: configSubnets = [] },
|
|
filteredSubnets
|
|
} = this;
|
|
const selectedSubnets = filteredSubnets.filter((fs) => configSubnets.includes(fs.subnetId));
|
|
|
|
return get(this, 'allSecurityGroups').filter((sg) => {
|
|
return selectedSubnets.findBy('group', sg.VpcId)
|
|
}).sortBy('GroupName');
|
|
}),
|
|
|
|
readableServiceRole: computed('config.serviceRole', 'serviceRoles', function() {
|
|
const roles = get(this, 'serviceRoles');
|
|
const selectedRole = get(this, 'config.serviceRole');
|
|
const match = roles.findBy('RoleName', selectedRole);
|
|
|
|
return match && match.RoleName ? get(match, 'RoleName') : this.intl.t('nodeDriver.amazoneks.role.noneSelected');
|
|
}),
|
|
|
|
syncUpstreamConfig() {
|
|
const originalCluster = get(this, 'model.originalCluster').clone();
|
|
const ourClusterSpec = get(originalCluster, 'eksConfig');
|
|
const upstreamSpec = get(originalCluster, 'eksStatus.upstreamSpec');
|
|
|
|
if (!isEmpty(upstreamSpec)) {
|
|
Object.keys(ourClusterSpec).forEach((k) => {
|
|
if (isEmpty(get(ourClusterSpec, k)) && !isEmpty(get(upstreamSpec, k))) {
|
|
set(this, `config.${ k }`, get(upstreamSpec, k));
|
|
}
|
|
});
|
|
}
|
|
},
|
|
|
|
authCreds() {
|
|
let {
|
|
config: {
|
|
region,
|
|
amazonCredentialSecret
|
|
}
|
|
} = this;
|
|
const httpOptions = { cloudCredentialId: amazonCredentialSecret.includes('cattle-global-data') ? amazonCredentialSecret : `cattle-global-data:${ amazonCredentialSecret }` };
|
|
|
|
if (this.editing) {
|
|
set(httpOptions, 'clusterID', get(this, 'model.originalCluster.id'));
|
|
}
|
|
|
|
const auth = {
|
|
accessKeyId: randomStr(),
|
|
secretAccessKey: randomStr(),
|
|
region,
|
|
httpOptions,
|
|
};
|
|
|
|
|
|
return auth;
|
|
},
|
|
|
|
async loadRoles() {
|
|
try {
|
|
const auth = { ...this.authCreds() };
|
|
const { region } = auth;
|
|
|
|
if ( region === 'cn-northwest-1' ) {
|
|
auth.region = 'cn-north-1';
|
|
auth.endpoint = `iam.cn-north-1.amazonaws.com.cn`
|
|
}
|
|
|
|
const awsRoles = await this.describeResource(['IAM', 'listRoles', 'Roles'], { MaxItems: 1000 }, auth);
|
|
|
|
const eksRoles = [];
|
|
const ec2Roles = []
|
|
|
|
awsRoles.forEach( (role) => {
|
|
let policy = JSON.parse(decodeURIComponent(get(role, 'AssumeRolePolicyDocument')));
|
|
let statement = get(policy, 'Statement');
|
|
|
|
statement.forEach( (doc) => {
|
|
let principal = get(doc, 'Principal');
|
|
|
|
if (principal) {
|
|
let service = get(principal, 'Service');
|
|
|
|
if (service && service.includes('ec2.amazonaws.com') && !ec2Roles.findBy('RoleId', get(role, 'RoleId')) && !role.RoleName.match(/^rancher-managed/)){
|
|
ec2Roles.push(role)
|
|
}
|
|
if ( service && ( service.includes('eks.amazonaws') || service.includes('EKS') ) && !eksRoles.findBy('RoleId', get(role, 'RoleId'))) {
|
|
eksRoles.push(role)
|
|
} else if (get(principal, 'EKS')) {
|
|
eksRoles.push(role)
|
|
}
|
|
}
|
|
});
|
|
});
|
|
set(this, 'nodeInstanceRoles', ec2Roles)
|
|
set(this, 'serviceRoles', eksRoles);
|
|
} catch (err) {
|
|
if (err.message.includes('Authentication Token')) {
|
|
set(this, 'credentialError', true);
|
|
}
|
|
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadSecurityGroups() {
|
|
try {
|
|
const securityGroups = await this.describeResource(['EC2', 'describeSecurityGroups', 'SecurityGroups']);
|
|
|
|
set(this, 'allSecurityGroups', securityGroups);
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadLaunchTemplates() {
|
|
try {
|
|
const launchTemplates = await this.describeResource(['EC2', 'describeLaunchTemplates', 'LaunchTemplates']);
|
|
|
|
set(this, 'allLaunchTemplates', launchTemplates);
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadInstanceTypes() {
|
|
try {
|
|
const instanceTypes = await this.describeResource(['EC2', 'describeInstanceTypes', 'InstanceTypes']);
|
|
|
|
set(this, 'instanceTypes', instanceTypes);
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadImages() {
|
|
// this is can be VERY expensive if `ExecutableUsers` is excluded
|
|
// I am not sure if that param is even correct nor do I think we should use this
|
|
// I am leaving in for dev purpose remove before pr
|
|
try {
|
|
const images = await this.describeResource(['EC2', 'describeImages', 'Images'], {
|
|
ExecutableUsers: ['self'],
|
|
Filters: [{
|
|
Name: 'state',
|
|
Values: ['available']
|
|
}]
|
|
});
|
|
|
|
set(this, 'allImages', images);
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadKeyPairs() {
|
|
try {
|
|
const allKeyPairs = await this.describeResource(['EC2', 'describeKeyPairs', 'KeyPairs']);
|
|
|
|
set(this, 'allKeyPairs', allKeyPairs);
|
|
} catch (err) {
|
|
get(this, 'errors').pushObject(err);
|
|
}
|
|
},
|
|
|
|
async loadKMSKeys() {
|
|
try {
|
|
const kmsKeys = await this.describeResource(['KMS', 'listKeys', 'Keys']);
|
|
|
|
set(this, 'kmsKeys', kmsKeys)
|
|
} catch (err) {
|
|
// creators MAY not have access to KMS keys via IAM so dont kill everything because they dont
|
|
// its not required
|
|
set(this, 'loadFailedKmsKeys', true);
|
|
}
|
|
},
|
|
|
|
willSave() {
|
|
this.validateNodeGroups();
|
|
|
|
|
|
if (!isEmpty(this.errors)) {
|
|
return false;
|
|
}
|
|
|
|
const { config } = this;
|
|
const {
|
|
displayName, subnets, nodeGroups
|
|
} = config;
|
|
|
|
if (isEmpty(subnets)) {
|
|
set(this, 'config.subnets', []);
|
|
}
|
|
|
|
if (isEmpty(displayName) || displayName === '(null)') {
|
|
set(this.config, 'displayName', this.primaryResource.name);
|
|
}
|
|
|
|
nodeGroups.forEach(( ng ) => {
|
|
const { launchTemplate } = ng;
|
|
|
|
if (!isEmpty(launchTemplate)) {
|
|
const {
|
|
id, version, name
|
|
} = launchTemplate;
|
|
|
|
if (isEmpty(id) && isEmpty(version) && isEmpty(name)) {
|
|
set(ng, 'launchTemplate', null);
|
|
}
|
|
|
|
// we dont want to send the example user data
|
|
if (ng.userData === DEFAULT_USER_DATA) {
|
|
set(ng, 'userData', null);
|
|
}
|
|
}
|
|
});
|
|
|
|
return this._super(...arguments);
|
|
},
|
|
|
|
doSave(opt) {
|
|
return get(this, 'primaryResource').save(opt).then((newData) => {
|
|
return newData;
|
|
}).catch(( err ) => {
|
|
return err;
|
|
});
|
|
},
|
|
|
|
validateNodeGroups() {
|
|
const nodeGroups = get(this, 'primaryResource.eksConfig.nodeGroups');
|
|
const errors = [];
|
|
|
|
if (!isEmpty(nodeGroups)) {
|
|
const nodeGroupErrors = [];
|
|
|
|
nodeGroups.forEach((ng) => {
|
|
const ngErr = ng.validationErrors();
|
|
|
|
nodeGroupErrors.push(ngErr)
|
|
});
|
|
|
|
if (!isEmpty(nodeGroupErrors)) {
|
|
errors.pushObjects(nodeGroupErrors.flat());
|
|
}
|
|
}
|
|
|
|
set(this, 'errors', errors);
|
|
|
|
return errors.length >= 1 ? true : null;
|
|
},
|
|
|
|
describeResource(apiDescription, params = {}, authCreds = this.authCreds()) {
|
|
const [awsClassName, awsSDKMethod, responseKey] = apiDescription;
|
|
const klass = new AWS[awsClassName](authCreds);
|
|
|
|
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const fetchData = (params, allResponseData = []) => {
|
|
klass[awsSDKMethod](params, (err, data) => {
|
|
if (err){
|
|
return reject(err)
|
|
}
|
|
allResponseData.push(...data[responseKey])
|
|
|
|
if (data.IsTruncated && data.Marker){
|
|
fetchData({
|
|
...params,
|
|
Marker: data.Marker
|
|
}, allResponseData)
|
|
} else {
|
|
resolve(allResponseData)
|
|
}
|
|
})
|
|
}
|
|
|
|
fetchData(params, [])
|
|
})
|
|
}
|
|
});
|