mirror of https://github.com/rancher/ui.git
397 lines
12 KiB
JavaScript
397 lines
12 KiB
JavaScript
import ClusterDriver from 'shared/mixins/cluster-driver';
|
|
import Component from '@ember/component'
|
|
import {
|
|
computed, get, set, setProperties, observer
|
|
} from '@ember/object';
|
|
import { alias } from '@ember/object/computed';
|
|
import layout from './template';
|
|
import { inject as service } from '@ember/service';
|
|
import { hash } from 'rsvp';
|
|
import { on } from '@ember/object/evented';
|
|
import ipaddr from 'ipaddr.js';
|
|
import { equal } from '@ember/object/computed'
|
|
import C from 'shared/utils/constants';
|
|
import Semver from 'semver';
|
|
|
|
import {
|
|
sizes,
|
|
aksRegions,
|
|
} from 'ui/utils/azure-choices';
|
|
|
|
const NETWORK_POLICY = ['calico']
|
|
const CHINA_REGION_API_URL = 'https://management.chinacloudapi.cn/';
|
|
const CHINA_REGION_AUTH_URL = 'https://login.chinacloudapi.cn/';
|
|
const NETWORK_PLUGINS = [
|
|
{
|
|
label: 'Kubenet',
|
|
value: 'kubenet'
|
|
},
|
|
{
|
|
label: 'Azure',
|
|
value: 'azure'
|
|
}
|
|
];
|
|
const LB_SKUS = [
|
|
{
|
|
label: 'Standard',
|
|
value: 'standard'
|
|
},
|
|
{
|
|
label: 'Basic',
|
|
value: 'basic'
|
|
}
|
|
];
|
|
|
|
export default Component.extend(ClusterDriver, {
|
|
globalStore: service(),
|
|
intl: service(),
|
|
settings: service(),
|
|
versionChoiceService: service('version-choices'),
|
|
layout,
|
|
|
|
configField: 'azureKubernetesServiceConfig',
|
|
|
|
zones: aksRegions,
|
|
versions: null,
|
|
machineSizes: sizes,
|
|
step: 1,
|
|
netMode: 'default',
|
|
monitoringRegionConent: [],
|
|
networkPlugins: NETWORK_PLUGINS,
|
|
lbSkus: LB_SKUS,
|
|
|
|
defaultK8sVersionRange: alias(`settings.${ C.SETTING.VERSION_SYSTEM_K8S_DEFAULT_RANGE }`),
|
|
editing: equal('mode', 'edit'),
|
|
isNew: equal('mode', 'new'),
|
|
|
|
init() {
|
|
this._super(...arguments);
|
|
|
|
let config = get(this, 'cluster.azureKubernetesServiceConfig');
|
|
|
|
if ( !config ) {
|
|
config = this.get('globalStore').createRecord({
|
|
adminUsername: 'azureuser',
|
|
agentOsdiskSize: 100,
|
|
agentPoolName: 'rancher',
|
|
agentVmSize: 'Standard_D2_v2',
|
|
count: 3,
|
|
enableHttpApplicationRouting: false,
|
|
enableMonitoring: true,
|
|
location: 'eastus',
|
|
type: 'azureKubernetesServiceConfig',
|
|
});
|
|
|
|
set(this, 'cluster.azureKubernetesServiceConfig', config);
|
|
set(this, 'loadBalancerSku', 'basic');
|
|
} else {
|
|
const tags = get(config, 'tags') || []
|
|
const map = {}
|
|
|
|
tags.map((t = '') => {
|
|
const split = t.split('=')
|
|
|
|
set(map, split[0], split[1])
|
|
})
|
|
set(this, 'tags', map)
|
|
|
|
if (get(config, 'networkPolicy') || get(config, 'subnet')) {
|
|
set(this, 'netMode', 'advanced')
|
|
}
|
|
}
|
|
},
|
|
|
|
actions: {
|
|
authenticate(cb) {
|
|
const store = get(this, 'globalStore')
|
|
const data = {
|
|
clientId: get(this, 'config.clientId'),
|
|
clientSecret: get(this, 'config.clientSecret'),
|
|
subscriptionId: get(this, 'config.subscriptionId'),
|
|
tenantId: get(this, 'config.tenantId'),
|
|
region: get(this, 'config.location')
|
|
};
|
|
|
|
if ( get(this, 'isChinaRegion') ) {
|
|
setProperties(data, {
|
|
baseUrl: CHINA_REGION_API_URL,
|
|
authBaseUrl: CHINA_REGION_AUTH_URL
|
|
})
|
|
}
|
|
|
|
const aksRequest = {
|
|
versions: store.rawRequest({
|
|
url: '/meta/aksVersions',
|
|
method: 'POST',
|
|
data
|
|
}),
|
|
virtualNetworks: store.rawRequest({
|
|
url: '/meta/aksVirtualNetworks',
|
|
method: 'POST',
|
|
data
|
|
})
|
|
}
|
|
|
|
return hash(aksRequest).then((resp) => {
|
|
const { mode } = this;
|
|
const { versions, virtualNetworks } = resp;
|
|
const isEdit = mode === 'edit';
|
|
const versionz = (get(versions, 'body') || []);
|
|
const initialVersion = isEdit ? this.config.kubernetesVersion : Semver.maxSatisfying(versionz, this.defaultK8sVersionRange);
|
|
|
|
if (!isEdit && initialVersion) {
|
|
set(this, 'cluster.azureKubernetesServiceConfig.kubernetesVersion', initialVersion);
|
|
}
|
|
|
|
setProperties(this, {
|
|
step: 2,
|
|
versions: (get(versions, 'body') || []),
|
|
virtualNetworks: (get(virtualNetworks, 'body') || []),
|
|
});
|
|
|
|
cb(true);
|
|
}).catch((xhr) => {
|
|
const err = xhr.body.message || xhr.body.code || xhr.body.error;
|
|
|
|
setProperties(this, { errors: [err], });
|
|
|
|
cb(false, [err]);
|
|
});
|
|
},
|
|
|
|
setTags(section) {
|
|
const out = []
|
|
|
|
for (let key in section) {
|
|
out.pushObject(`${ key }=${ section[key] }`)
|
|
}
|
|
set(this, 'config.tags', out);
|
|
},
|
|
},
|
|
|
|
resetAdvancedOptions: on('init', observer('netMode', function() {
|
|
if (get(this, 'isNew') && get(this, 'netMode') === 'default') {
|
|
const config = get(this, 'config');
|
|
let {
|
|
subnet,
|
|
virtualNetwork,
|
|
virtualNetworkResourceGroup,
|
|
serviceCidr,
|
|
dnsServiceIp,
|
|
dockerBridgeCidr
|
|
} = this.globalStore.getById('schema', 'azurekubernetesserviceconfig').getCreateDefaults();
|
|
|
|
setProperties(config, {
|
|
subnet,
|
|
virtualNetwork,
|
|
virtualNetworkResourceGroup,
|
|
serviceCidr,
|
|
dnsServiceIp,
|
|
dockerBridgeCidr
|
|
});
|
|
}
|
|
})),
|
|
|
|
loadBalancerSku: computed('config.loadBalancerSku', {
|
|
get() {
|
|
const lbSku = get(this, 'config.loadBalancerSku');
|
|
|
|
if (lbSku === 'standard') {
|
|
return 'Standard';
|
|
}
|
|
|
|
return 'Basic';
|
|
},
|
|
set(key, value) {
|
|
set(this, 'config.loadBalancerSku', value);
|
|
|
|
return value;
|
|
}
|
|
}),
|
|
|
|
versionChoices: computed('versions', function() {
|
|
const {
|
|
versions = [],
|
|
mode,
|
|
config : { kubernetesVersion: initialVersion }
|
|
} = this;
|
|
|
|
// azure versions come in oldest to newest
|
|
return this.versionChoiceService.parseCloudProviderVersionChoices(( versions || [] ).reverse(), initialVersion, mode);
|
|
}),
|
|
|
|
networkChoice: computed({
|
|
set( key, value = '' ) {
|
|
const [subnet, virtualNetwork, virtualNetworkResourceGroup] = value.split(':');
|
|
const config = get(this, 'config');
|
|
|
|
if (subnet && virtualNetwork && virtualNetworkResourceGroup) {
|
|
setProperties(config, {
|
|
subnet,
|
|
virtualNetwork,
|
|
virtualNetworkResourceGroup
|
|
});
|
|
}
|
|
|
|
return value;
|
|
}
|
|
}),
|
|
|
|
filteredVirtualNetworks: computed('config.virtualNetwork', 'virtualNetworks', function() {
|
|
const vnets = get(this, 'virtualNetworks') || [];
|
|
const subNets = [];
|
|
|
|
vnets.forEach( (vnet) => {
|
|
(get(vnet, 'subnets') || []).forEach( (subnet) => {
|
|
subNets.pushObject({
|
|
name: `${ get(subnet, 'name') } (${ get(subnet, 'addressRange') })`,
|
|
group: get(vnet, 'name'),
|
|
value: `${ get(subnet, 'name') }:${ get(vnet, 'name') }:${ get(vnet, 'resourceGroup') }`
|
|
})
|
|
});
|
|
});
|
|
|
|
return subNets;
|
|
}),
|
|
|
|
networkChoiceDisplay: computed('virtualNetworks', 'config.virtualNetwork', 'config.subnet', function() {
|
|
const selected = (get(this, 'virtualNetworks') || []).findBy('name', get(this, 'config.virtualNetwork')) || {}
|
|
const subnet = (get(selected, 'subnets') || []).findBy('name', get(this, 'config.subnet')) || {}
|
|
|
|
return `${ get(subnet, 'name') } (${ get(subnet, 'addressRange') })`
|
|
}),
|
|
|
|
isEditable: computed('mode', function() {
|
|
return ( get(this, 'mode') === 'edit' || get(this, 'mode') === 'new' ) ? true : false;
|
|
}),
|
|
|
|
isChinaRegion: computed('config.location', function() {
|
|
return get(this, 'config.location').startsWith('china');
|
|
}),
|
|
|
|
saveDisabled: computed('config.subscriptionId', 'config.tenantId', 'config.clientId', 'config.clientSecret', 'config.location', function() {
|
|
return get(this, 'config.tenantId') && get(this, 'config.clientId') && get(this, 'config.clientSecret') && get(this, 'config.subscriptionId') && get(this, 'config.location') ? false : true;
|
|
}),
|
|
|
|
networkPolicyContent: computed(() => {
|
|
return NETWORK_POLICY.map((n) => {
|
|
return {
|
|
label: n,
|
|
value: n,
|
|
}
|
|
})
|
|
}),
|
|
|
|
validate() {
|
|
const intl = get(this, 'intl');
|
|
let model = get(this, 'cluster');
|
|
let errors = model.validationErrors() || [];
|
|
|
|
const vnetSet = !!get(this, 'config.virtualNetwork');
|
|
|
|
if (vnetSet) {
|
|
errors = errors.concat(this.validateVnetInputs());
|
|
}
|
|
|
|
if ( !get(this, 'config.resourceGroup') ) {
|
|
errors.push(intl.t('validation.required', { key: intl.t('clusterNew.azureaks.resourceGroup.label') }));
|
|
}
|
|
|
|
if ( !get(this, 'config.sshPublicKeyContents') ) {
|
|
errors.push(intl.t('validation.required', { key: intl.t('clusterNew.azureaks.ssh.label') }));
|
|
}
|
|
|
|
set(this, 'errors', errors);
|
|
|
|
return errors.length === 0;
|
|
},
|
|
|
|
validateVnetInputs() {
|
|
const intl = get(this, 'intl');
|
|
const errors = [];
|
|
const config = get(this, 'config');
|
|
const vnet = get(this, 'virtualNetworks').findBy('name', get(config, 'virtualNetwork'));
|
|
|
|
if (vnet) {
|
|
let subnet = get(vnet, `subnets`).findBy('name', get(config, 'subnet'));
|
|
let vnetRange = ipaddr.parseCIDR(get(subnet, 'addressRange'));
|
|
|
|
let {
|
|
serviceCidr, dnsServiceIp, dockerBridgeCidr
|
|
} = config;
|
|
|
|
let parsedServiceCidr = null;
|
|
let parsedDnsServiceIp = null;
|
|
let parsedDockerBridgeCidr = null;
|
|
|
|
if (!serviceCidr && !dnsServiceIp && !dockerBridgeCidr) {
|
|
errors.pushObject('You must include all required fields when using a Virtual Network');
|
|
}
|
|
|
|
try {
|
|
parsedServiceCidr = ipaddr.parseCIDR(serviceCidr);
|
|
|
|
// check if serviceCidr falls within the VNet/Subnet range
|
|
if (parsedServiceCidr && vnetRange[0].match(parsedServiceCidr)) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.parsedServiceCidr'));
|
|
}
|
|
} catch ( err ) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.serviceCidr'));
|
|
}
|
|
|
|
try {
|
|
parsedDnsServiceIp = ipaddr.parse(dnsServiceIp);
|
|
|
|
// check if dnsService exists in range
|
|
if (parsedDnsServiceIp && vnetRange[0].match(parsedDnsServiceIp, vnetRange[1])) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.parsedDnsServiceIp'));
|
|
}
|
|
} catch ( err ) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.dnsServiceIp'));
|
|
}
|
|
|
|
try {
|
|
parsedDockerBridgeCidr = ipaddr.parseCIDR(dockerBridgeCidr);
|
|
|
|
// check that dockerBridge doesn't overlap
|
|
if (parsedDockerBridgeCidr && ( vnetRange[0].match(parsedDockerBridgeCidr) || parsedServiceCidr[0].match(parsedDockerBridgeCidr) )) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.parsedDockerBridgeCidr'));
|
|
}
|
|
} catch ( err ) {
|
|
errors.pushObject(intl.t('clusterNew.azureaks.errors.included.dockerBridgeCidr'));
|
|
}
|
|
}
|
|
|
|
return errors;
|
|
},
|
|
|
|
willSave() {
|
|
const enableMonitoring = get(this, 'config.enableMonitoring')
|
|
const config = get(this, 'config')
|
|
|
|
if (enableMonitoring) {
|
|
setProperties(config, {
|
|
logAnalyticsWorkspaceResourceGroup: '',
|
|
logAnalyticsWorkspace: '',
|
|
})
|
|
} else {
|
|
setProperties(config, {
|
|
logAnalyticsWorkspaceResourceGroup: null,
|
|
logAnalyticsWorkspace: null,
|
|
})
|
|
}
|
|
|
|
if ( get(this, 'isChinaRegion') ) {
|
|
setProperties(config, {
|
|
baseUrl: CHINA_REGION_API_URL,
|
|
authBaseUrl: CHINA_REGION_AUTH_URL
|
|
})
|
|
} else {
|
|
delete config['baseUrl'];
|
|
delete config['authBaseUrl'];
|
|
}
|
|
|
|
return this._super(...arguments);
|
|
},
|
|
});
|