Merge pull request #1890 from loganhz/aliyun

Update Aliyun ECS node driver UI
This commit is contained in:
Vincent Fiduccia 2018-05-09 11:09:48 -07:00 committed by GitHub
commit 57448c5b9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 25394 additions and 282 deletions

View File

@ -22,6 +22,7 @@ module.exports = {
"Ui": true,
"async": true,
"AWS": true,
"ALY": true,
"Identicon": true,
"md5": true,
"_": true,

View File

@ -105,6 +105,7 @@ module.exports = function(defaults) {
app.import('vendor/prompt/prompt-v1-latin-600.woff', { destDir: 'assets/fonts/'});
app.import('vendor/prompt/prompt-v1-latin-600.woff2',{ destDir: 'assets/fonts/'});
app.import('vendor/aws-sdk-ec2.js');
app.import('vendor/aliyun-sdk.js');
app.import('vendor/file-saver/fileSaver.mini.js');
app.import('vendor/json-sanitizer/json-sanitizer.js');

View File

@ -21,6 +21,7 @@ module.exports = {
"Ui": true,
"async": true,
"AWS": true,
"ALY": true,
"Identicon": true,
"md5": true,
"_": true,

View File

@ -1,41 +1,331 @@
import { alias } from '@ember/object/computed';
import { set, get, observer, setProperties, computed } from '@ember/object';
import Component from '@ember/component';
import NodeDriver from 'shared/mixins/node-driver';
import layout from './template';
import { inject as service } from '@ember/service';
import { Promise as EmberPromise } from 'rsvp';
let ioOptimized=[
{
value : "none",
const ENDPOINT = 'https://ecs.aliyuncs.com';
const PAGE_SIZE = 50;
const NONE_OPT_DISK = [{
value: 'cloud'
}];
const OPT_DISK = [{
value: 'cloud_efficiency'
},
{
value: "optimized",
},
value: 'cloud_ssd'
}
];
export default Component.extend(NodeDriver, {
layout,
intl: service(),
settings: service(),
driverName: 'aliyunecs',
config: alias('model.aliyunecsConfig'),
ioOptimized: ioOptimized,
zones: null,
regions: null,
securityGroups: null,
images: null,
instanceTypes: null,
ecsClient: null,
step: 1,
bootstrap: function () {
let config = this.get('globalStore').createRecord({
const config = get(this, 'globalStore').createRecord({
type: 'aliyunecsConfig',
accessKeySecret: ''
accessKeySecret: '',
ioOptimized: 'optimized',
});
this.set('model.aliyunecsConfig', config);
set(this, 'model.aliyunecsConfig', config);
set(this, 'model.engineRegistryMirror', ['https://s06nkgus.mirror.aliyuncs.com']);
set(this, 'model.engineInstallURL', 'http://dev-tool.oss-cn-shenzhen.aliyuncs.com/docker-install/1.13.1.sh');
},
validate() {
let errors = [];
if ( !this.get('model.name') ) {
actions: {
alyLogin: function (cb) {
setProperties(this, {
'errors': null,
'config.accessKeyId': (get(this, 'config.accessKeyId') || '').trim(),
'config.accessKeySecret': (get(this, 'config.accessKeySecret') || '').trim(),
});
const errors = get(this, 'errors') || [];
const intl = get(this, 'intl');
const accessKey = get(this, 'config.accessKeyId');
const accessSecret = get(this, 'config.accessKeySecret');
if (!accessKey) {
errors.push(intl.t('nodeDriver.aliyunecs.errors.accessKeyRequired'));
}
if (!accessSecret) {
errors.push(intl.t('nodeDriver.aliyunecs.errors.accessSecretRequired'));
}
if (errors.length > 0) {
set(this, 'errors', errors);
cb();
return;
}
let ecs;
try {
const location = window.location;
let endpoint = get(this, 'config.apiEndpoint') ? get(this, 'config.apiEndpoint') : ENDPOINT;
endpoint = get(this,'app.proxyEndpoint') + '/' + endpoint.replace('//', '/');
endpoint = `${location.protocol}//${window.location.host}${endpoint}`;
ecs = new ALY.ECS({
accessKeyId: get(this, 'config.accessKeyId'),
secretAccessKey: get(this, 'config.accessKeySecret'),
apiVersion: '2014-05-26',
endpoint,
});
ecs.describeRegions({}, (err, res) => {
if (err) {
let errors = get(this, 'errors') || [];
errors.pushObject(err.message || err);
set(this, 'errors', errors);
cb();
return;
}
set(this, 'ecsClient', ecs);
set(this, 'regions', res.Regions.Region.map((region) => {
return {
value: region.RegionId,
label: region.LocalName,
};
}));
this.regionDidChange();
set(this, 'step', 2);
cb();
});
} catch (err) {
const errors = get(this, 'errors') || [];
errors.pushObject(err.message || err);
set(this, 'errors', errors);
cb();
return;
}
},
loadStorageTypes: function (cb) {
if (!get(this, 'config.securityGroup')) {
set(this, 'config.securityGroup', 'docker-machine')
}
set(this, 'step', 3);
this.diskCategoryChoicesDidChange();
cb();
},
loadInstanceTypes: function (cb) {
this.fetch('Image', 'Images')
.then((images) => {
set(this, 'images', images.filter((image) => image.raw.OSType === 'linux'));
set(this, 'config.imageId', get(this, 'images.firstObject.value'));
this.fetch('InstanceType', 'InstanceTypes')
.then((instanceTypes) => {
set(this, 'instanceTypes', instanceTypes.map((instanceType) => {
return {
group: instanceType.raw.InstanceTypeFamily,
value: instanceType.value,
label: `${instanceType.raw.InstanceTypeId} ( ${instanceType.raw.CpuCoreCount} ${instanceType.raw.CpuCoreCount > 1 ? 'Cores': 'Core'} ${instanceType.raw.MemorySize}GB RAM )`,
}
}));
set(this, 'config.instanceType', get(this, 'instanceTypes.firstObject.value'))
set(this, 'step', 4);
cb();
})
.catch((err) => {
const errors = get(this, 'errors') || [];
errors.pushObject(err.message || err);
set(this, 'errors', errors);
cb();
return;
});
})
.catch((err) => {
const errors = get(this, 'errors') || [];
errors.pushObject(err.message || err);
set(this, 'errors', errors);
cb();
return;
});
},
},
vpcDidChange: observer('config.vpcId', function () {
const vpcId = get(this, 'config.vpcId');
if (vpcId) {
this.fetch('VSwitch', 'VSwitches').then((vswitches) => {
set(this, 'vswitches', vswitches);
const selectedVSwitch = get(this, 'config.vswitchId');
if (selectedVSwitch) {
const found = vswitches.findBy('VSwitchId', selectedVSwitch);
if (!found) {
set(this, 'config.vswitchId', null);
}
}
});
this.fetch('SecurityGroup', 'SecurityGroups').then((securityGroups) => {
set(this, 'securityGroups', securityGroups);
const selectedSecurityGroup = get(this, 'config.securityGroup');
if (selectedSecurityGroup) {
const found = securityGroups.findBy('SecurityGroupId', selectedSecurityGroup);
if (!found) {
set(this, 'config.securityGroup', 'docker-machine');
}
}
});
} else {
set(this, 'config.vswitchId', null);
set(this, 'config.securityGroup', 'docker-machine');
}
}),
regionDidChange: observer('config.region', function () {
const region = get(this, 'config.region');
if (region) {
this.fetch('Vpc', 'Vpcs').then((vpcs) => {
set(this, 'vpcs', vpcs);
const selectedVPC = get(this, 'config.vpcId');
if (selectedVPC) {
const found = vpcs.findBy('VpcId', selectedVPC);
if (!found) {
set(this, 'config.vpcId', null);
}
}
});
this.fetch('Zone', 'Zones').then((zones) => {
set(this, 'zones', zones);
const selectedZone = get(this, 'config.zone');
if (selectedZone) {
const found = zones.findBy('ZoneId', selectedZone);
if (!found) {
set(this, 'config.zone', null);
}
}
});
}
}),
diskCategoryChoices: computed('config.ioOptimized', function () {
return get(this, 'config.ioOptimized') === 'none' ? NONE_OPT_DISK : OPT_DISK;
}),
diskCategoryChoicesDidChange: observer('diskCategoryChoices.@each.value', function () {
set(this, 'config.systemDiskCategory', get(this, 'diskCategoryChoices.firstObject.value'));
set(this, 'config.diskCategory', get(this, 'diskCategoryChoices.firstObject.value'));
}),
validate: function () {
this._super();
const errors = get(this, 'model').validationErrors();
const intl = get(this, 'intl');
const name = get(this, 'model.name');
const sshPassword = get(this, 'config.sshPassword');
const lower = /[a-z]/.test(sshPassword) ? 1 : 0;
const upper = /[A-Z]/.test(sshPassword) ? 1 : 0;
const number = /[0-9]/.test(sshPassword) ? 1 : 0;
const special = /[?+*$^().|<>';:\-=\[\]\{\},&%#@!~`\\]/.test(sshPassword) ? 1 : 0;
if (!name) {
errors.push('Name is required');
}
this.set('errors', errors);
if (sshPassword && (sshPassword.length < 8) || sshPassword.length > 30) {
errors.push(intl.t('nodeDriver.aliyunecs.errors.sshPasswordLengthNotValid'));
}
if (sshPassword && !/[?+*$^().|<>';:\-=\[\]\{\},&%#@!~`\\a-zA-Z0-9]+/.test(sshPassword)) {
errors.push(intl.t('nodeDriver.aliyunecs.errors.sshPasswordInvalidCharacter'));
}
if (sshPassword && (lower + upper + number + special < 3)) {
errors.push(get(this, 'intl').t('nodeDriver.aliyunecs.errors.sshPasswordFormatError'));
}
set(this, 'errors', errors);
return errors.length === 0;
},
fetch: function (resource, plural, page = 1) {
const ecs = get(this, 'ecsClient');
const region = get(this, 'config.region');
const results = [];
let params = {
PageSize: PAGE_SIZE,
PageNumber: page,
};
switch (resource) {
case 'InstanceType':
params = {};
break;
case 'VSwitch':
params.VpcId = get(this, 'config.vpcId');
break;
case 'SecurityGroup':
params.VpcId = get(this, 'config.vpcId');
params.RegionId = region;
break;
case 'Zone':
params = {
RegionId: region,
};
break;
default:
params.RegionId = region;
}
return new EmberPromise((resolve, reject) => {
ecs[`describe${plural}`](params, (err, res) => {
if (err) {
reject(err);
return;
}
const current = res[`${plural}`][resource];
results.pushObjects(current.map((item) => {
return {
label: item[`${resource}Id`],
value: item[`${resource}Id`],
raw: item,
};
}));
if (res.TotalCount > ((PAGE_SIZE * (page - 1)) + current.length)) {
return this.fetch(resource, plural, page + 1)
.then((array) => {
results.pushObjects(array);
resolve(results);
})
.catch((err) => {
reject(err);
});
} else {
resolve(results);
}
});
});
},
});

View File

@ -1,260 +1,270 @@
<section class="horizontal-form">
<div class="container-fluid">
{{#if showNameScale}}
<div class="box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.instanceSection'}}</h4>
<div class="row mb-20">
{{#accordion-list showExpandAll=false as | al expandFn |}}
<div class="over-hr"><span>{{driverOptionsTitle}}</span></div>
{{#accordion-list-item
title=(t 'nodeDriver.aliyunecs.accountSection.label')
detail=(t 'nodeDriver.aliyunecs.accountSection.detail')
expandAll=expandAll
expand=(action expandFn)
expandOnInit=true
}}
<div class="row">
<div class="col span-11-of-23 mt-0 mb-0">
{{form-name-description
name=prefix
nameRequired=true
namePlaceholder="hostsPage.new.name.placeholder"
nameHelpText=nameCountLabel
descriptionShown=true
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.accessKey.label'}}{{field-required}}</label>
{{#input-or-display editable=(eq step 1) value=config.accessKeyId}}
{{input type="text" class="form-control" value=config.accessKeyId placeholder=(t 'nodeDriver.aliyunecs.accessKey.placeholder')}}
{{/input-or-display}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.accessKeySecret.label'}}{{field-required}}</label>
{{#if (eq step 1)}}
{{input type="password" class="form-control" value=config.accessKeySecret placeholder=(t 'nodeDriver.aliyunecs.accessKeySecret.placeholder')}}
{{else}}
<div class="text-muted text-italic">{{t 'nodeDriver.aliyunecs.accessKeySecret.provided'}}</div>
{{/if}}
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.apiEndpoint.label'}}</label>
{{#input-or-display editable=(eq step 1) value=config.apiEndpoint}}
{{input type="text" class="form-control" value=config.apiEndpoint placeholder=(t 'nodeDriver.aliyunecs.apiEndpoint.placeholder')}}
{{/input-or-display}}
</div>
</div>
{{/accordion-list-item}}
{{#if (eq step 1)}}
{{top-errors errors=errors}}
{{save-cancel
save="alyLogin"
cancel="cancel"
createLabel="nodeDriver.aliyunecs.accountSection.next"
savingLabel="nodeDriver.aliyunecs.accountSection.loading"
}}
</div>
<div class="col span-11-of-23 mt-0 mb-0 offset-1-of-23">
{{form-count
min=0
initialScale=1
setScale=(action (mut count))
}}
</div>
</div>
</div>
</div>
{{/if}}
<div class="row box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.accountSection'}}</h4>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.accessKey.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.accessKeyId placeholder=(t 'nodeDriver.aliyunecs.accessKey.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.accessKeySecret.label'}}</label>
</div>
<div class="col span-4">
{{input type="password" class="form-control" value=config.accessKeySecret placeholder=(t 'nodeDriver.aliyunecs.accessKeySecret.placeholder')}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.apiEndpoint.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.apiEndpoint placeholder=(t 'nodeDriver.aliyunecs.apiEndpoint.placeholder')}}
</div>
</div>
</div>
<div class="row box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.instanceOptionsSection'}}</h4>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.instanceDescription.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.description placeholder=(t 'nodeDriver.aliyunecs.instanceDescription.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.instanceType.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.instanceType placeholder=(t 'nodeDriver.aliyunecs.instanceType.placeholder')}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.systemImage.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.imageId placeholder=(t 'nodeDriver.aliyunecs.systemImage.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.instanceTag.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.tag placeholder=(t 'nodeDriver.aliyunecs.instanceTag.placeholder')}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.internetMaxBandwidth.label'}}</label>
</div>
<div class="col span-4">
<div class="input-group">
{{input type="text" class="form-control" value=config.internetMaxBandwidth placeholder=(t 'nodeDriver.aliyunecs.internetMaxBandwidth.placeholder')}}
<div class="input-group-addon bg-default">Mbps</div>
</div>
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.aliyunSLB.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.slbId placeholder=(t 'nodeDriver.aliyunecs.aliyunSLB.placeholder')}}
</div>
</div>
</div>
<div class="row box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.storageSection'}}</h4>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.ioOptimized.label'}}</label>
</div>
<div class="col span-4">
{{!--{{input type="text" class="form-control" value=config.ioOptimized placeholder=(t 'nodeDriver.aliyunecs.ioOptimized.placeholder')}}--}}
{{new-select
classNames="form-control"
content=ioOptimized
optionLabelPath='value'
value=config.ioOptimized
<div class="{{unless (gte step 2) 'hide'}}">
{{#accordion-list-item
title=(t 'nodeDriver.aliyunecs.networkSection.label')
detail=(t 'nodeDriver.aliyunecs.networkSection.detail')
expandAll=expandAll
expand=(action expandFn)
expandOnInit=true
}}
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.region.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.region}}
{{new-select classNames="form-control" content=regions value=config.region}}
{{/input-or-display}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.systemDiskCategory.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.systemDiskCategory placeholder=(t 'nodeDriver.aliyunecs.systemDiskCategory.placeholder')}}
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.vpcId.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.vpcId}}
{{new-select classNames="form-control" content=vpcs value=config.vpcId prompt="nodeDriver.aliyunecs.vpcId.prompt" localizedPrompt=true}}
{{/input-or-display}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.dataDiskCategory.label'}}</label>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.securityGroup.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.securityGroup}}
{{new-select classNames="form-control" content=securityGroups value=config.securityGroup prompt="nodeDriver.aliyunecs.securityGroup.prompt" localizedPrompt=true}}
{{/input-or-display}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.vswitchId.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.vswitchId}}
{{new-select classNames="form-control" content=vswitches value=config.vswitchId prompt="nodeDriver.aliyunecs.vswitchId.prompt" localizedPrompt=true}}
{{/input-or-display}}
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.diskCategory placeholder=(t 'nodeDriver.aliyunecs.dataDiskCategory.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.dataDiskSize.label'}}</label>
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.zone.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.zone}}
{{new-select classNames="form-control" content=zones value=config.zone prompt="nodeDriver.aliyunecs.zone.prompt" localizedPrompt=true}}
{{/input-or-display}}
</div>
<div class="col span-4">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.routeCIDR.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.routeCidr}}
{{input type="text" class="form-control" value=config.routeCidr placeholder=(t 'nodeDriver.aliyunecs.routeCIDR.placeholder')}}
{{/input-or-display}}
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.privateIp.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.privateIp}}
{{input type="text" class="form-control" value=config.privateIp placeholder=(t 'nodeDriver.aliyunecs.privateIp.placeholder')}}
{{/input-or-display}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.privateAddressOnly.label'}}</label>
{{#input-or-display editable=(eq step 2) value=config.privateAddressOnly}}
<div>
{{input type="checkbox" class="form-control" checked=config.privateAddressOnly}}
</div>
{{/input-or-display}}
</div>
</div>
{{/accordion-list-item}}
{{#if (eq step 2)}}
{{top-errors errors=errors}}
{{save-cancel
save="loadStorageTypes"
cancel="cancel"
createLabel="nodeDriver.aliyunecs.networkSection.next"
savingLabel="nodeDriver.aliyunecs.networkSection.loading"
}}
{{/if}}
</div>
<div class="{{unless (gte step 3) 'hide'}}">
{{#accordion-list-item
title=(t 'nodeDriver.aliyunecs.storageSection.label')
detail=(t 'nodeDriver.aliyunecs.storageSection.detail')
expandAll=expandAll
expand=(action expandFn)
expandOnInit=true
}}
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.ioOptimized.label'}}</label>
{{#input-or-display editable=(eq step 3) value=config.ioOptimized}}
<div>
<label class="mr-20 hand">
{{radio-button selection=config.ioOptimized value='optimized'}} {{t 'nodeDriver.aliyunecs.ioOptimized.optimized'}}
</label>
<label class="hand">
{{radio-button selection=config.ioOptimized value='none'}} {{t 'nodeDriver.aliyunecs.ioOptimized.none'}}
</label>
</div>
{{/input-or-display}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.systemDiskCategory.label'}}</label>
{{#input-or-display editable=(eq step 3) value=config.systemDiskCategory}}
{{new-select classNames="form-control" content=diskCategoryChoices optionLabelPath='value' value=config.systemDiskCategory}}
{{/input-or-display}}
</div>
</div>
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.dataDiskCategory.label'}}</label>
{{#input-or-display editable=(eq step 3) value=config.diskCategory}}
{{new-select classNames="form-control" content=diskCategoryChoices optionLabelPath='value' value=config.diskCategory}}
{{/input-or-display}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.dataDiskSize.label'}}</label>
{{#input-or-display editable=(eq step 3) value=config.diskSize}}
<div class="input-group">
{{input type="text" class="form-control" value=config.diskSize placeholder=(t 'nodeDriver.aliyunecs.dataDiskSize.placeholder')}}
<div class="input-group-addon bg-default">GB</div>
</div>
{{/input-or-display}}
</div>
</div>
{{/accordion-list-item}}
{{#if (eq step 3)}}
{{top-errors errors=errors}}
{{save-cancel
save="loadInstanceTypes"
cancel="cancel"
createLabel="nodeDriver.aliyunecs.storageSection.next"
savingLabel="nodeDriver.aliyunecs.storageSection.loading"
}}
{{/if}}
</div>
<div class="{{unless (gte step 4) 'hide'}}">
{{#accordion-list-item
title=(t 'nodeDriver.aliyunecs.instanceOptionsSection.label')
detail=(t 'nodeDriver.aliyunecs.instanceOptionsSection.detail')
expandAll=expandAll
expand=(action expandFn)
expandOnInit=true
}}
<div class="row">
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.instanceDescription.label'}}</label>
{{input type="text" class="form-control" value=config.description placeholder=(t 'nodeDriver.aliyunecs.instanceDescription.placeholder')}}
</div>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.instanceType.label'}}</label>
{{new-select classNames="form-control" content=instanceTypes value=config.instanceType}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.region.label'}}</label>
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.systemImage.label'}}</label>
{{new-select classNames="form-control" content=images optionLabelPath='raw.OSName' optionValuePath='value' value=config.imageId}}
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.region placeholder=(t 'nodeDriver.aliyunecs.region.placeholder')}}
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.internetMaxBandwidth.label'}}</label>
<div class="input-group">
{{input-integer min=1 max=100 class="form-control" value=config.internetMaxBandwidth placeholder=(t 'nodeDriver.aliyunecs.internetMaxBandwidth.placeholder')}}
<div class="input-group-addon bg-default">Mbps</div>
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.zone.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.zone placeholder=(t 'nodeDriver.aliyunecs.zone.placeholder')}}
</div>
</div>
</div>
<div class="row box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.networkSection'}}</h4>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.routeCIDR.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.routeCidr placeholder=(t 'nodeDriver.aliyunecs.routeCIDR.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.vpcId.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.vpcId placeholder=(t 'nodeDriver.aliyunecs.vpcId.placeholder')}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.vswitchId.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.vswitchId placeholder=(t 'nodeDriver.aliyunecs.vswitchId.placeholder')}}
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.aliyunSLB.label'}}</label>
{{input type="text" class="form-control" value=config.slbId placeholder=(t 'nodeDriver.aliyunecs.aliyunSLB.placeholder')}}
</div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.privateIp.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.privateIp placeholder=(t 'nodeDriver.aliyunecs.privateIp.placeholder')}}
<div class="col span-6">
<label class="acc-label">{{t 'nodeDriver.aliyunecs.sshPassword.label'}}</label>
{{input type="password" class="form-control" value=config.sshPassword placeholder=(t 'nodeDriver.aliyunecs.sshPassword.placeholder')}}
</div>
</div>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.privateAddressOnly.label'}}</label>
</div>
<div class="col span-4">
{{input type="checkbox" class="form-control" checked=config.privateAddressOnly}}
</div>
<div class="col span-6">
{{form-value-array
initialValues=config.tag
addActionLabel='nodeDriver.aliyunecs.tags.addActionLabel'
valueLabel='nodeDriver.aliyunecs.tags.valueLabel'
valuePlaceholder='nodeDriver.aliyunecs.tags.placeholder'
changed=(action (mut config.tag))
}}
</div>
</div>
{{/accordion-list-item}}
<div class="row box mt-20">
<h4>{{t 'nodeDriver.aliyunecs.securitySection'}}</h4>
<div class="row">
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.securityGroup.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.securityGroup placeholder=(t 'nodeDriver.aliyunecs.securityGroup.placeholder')}}
</div>
<div class="over-hr"><span>{{templateOptionsTitle}}</span></div>
<div class="col span-2 col-inline">
<label>{{t 'nodeDriver.aliyunecs.sshPassword.label'}}</label>
</div>
<div class="col span-4">
{{input type="text" class="form-control" value=config.sshPassword placeholder=(t 'nodeDriver.aliyunecs.sshPassword.placeholder')}}
</div>
</div>
</div>
{{form-name-description
model=model
nameRequired=true
}}
<div class="over-hr mt-40 mb-30">
<span>{{settings.appName}}</span>
</div>
<div class="row">
<div class="col span-12">
{{form-user-labels initialLabels=labelResource.labels setLabels=(action 'setLabels') expandAll=null}}
</div>
</div>
{{#advanced-section}}
{{form-engine-opts machine=model showEngineUrl=showEngineUrl}}
{{/advanced-section}}
</div>
{{form-user-labels
initialLabels=labelResource.labels
setLabels=(action 'setLabels')
expandAll=expandAll
expand=(action expandFn)
}}
{{form-engine-opts
machine=model
showEngineUrl=showEngineUrl
}}
{{top-errors errors=errors}}
{{save-cancel save="save" cancel="cancel" editing=editing}}
</section>
</div>
{{/accordion-list}}

View File

@ -4725,18 +4725,24 @@ nodeDriver:
region:
label: Region
aliyunecs:
accountSection: Account Access Section
accountSection:
label: 1. Account Access
detail: API Keys will be used to launch Aliyun ECS Instances.
next: "Next: Authenticate & Config network options"
loading: Loading Regions from Aliyun ECS...
accessKey:
label: Access Key*
label: Access Key
placeholder: Your Aliyun Account Access Key
accessKeySecret:
label: Access Key Secret*
placeholder: Your Key's secret
label: Access Key Secret
placeholder: Your Aliyun Account Access Key Secret
provided: Provided
apiEndpoint:
label: Api Endpoint
placeholder: Private Aliyun Api Server Endpoint
instanceSection: Instance Section
instanceOptionsSection: Instance Options Section
label: API Endpoint
placeholder: Private Aliyun API Server Endpoint
instanceOptionsSection:
label: Instance
detail: Customize the Aliyun ECS Instance that will be created.
instanceDescription:
label: Instance Description
placeholder: Instance Description
@ -4746,25 +4752,25 @@ nodeDriver:
systemImage:
label: System image
placeholder: System image
instanceTag:
label: Instance Tag
placeholder: Your Instance Tag in Aliyun
internetMaxBandwidth:
label: Internet Max Bandwidth
placeholder: 1 to 100
aliyunSLB:
label: Aliyun SLB ID
placeholder: Aliyun SLB ID
storageSection: Storage Info
storageSection:
label: Storage
detail: Configure the storage for the instances that will be created by this template.
next: "Next: Config Aliyun ECS Instance options"
loading: Loading Instance Types and Images from Aliyun ECS...
ioOptimized:
label: Instance Storage I/O Optimized
placeholder: none or optimized
optimized: Optimized
none: None
systemDiskCategory:
label: System Disk Category
placeholder: When Storage is optimized, you can input cloud_efficiency, cloud_ssd or ephemeral_ssd.
dataDiskCategory:
label: Data Disk Category
placeholder: When Storage is optimized, you can input cloud_efficiency, cloud_ssd or ephemeral_ssd.
dataDiskSize:
label: Data Disk Size
placeholder: Disk Size
@ -4773,29 +4779,48 @@ nodeDriver:
placeholder: Region
zone:
label: Available Zone
placeholder: Blank for auto select
networkSection: Network Section
prompt: Choose a Available Zone...
networkSection:
label: Network
detail: Configure the network for the instances that will be created by this template.
next: "Next: Config Storage Options"
loading: Loading Storage Types from Aliyun ECS...
routeCIDR:
label: Route CIDR
placeholder: e.g. 192.168.1.0/24
vpcId:
label: Aliyun VPC ID
placeholder: Aliyun VPC ID
label: VPC
prompt: Choose a VPC...
vswitchId:
label: Aliyun Vswitch ID
placeholder: Aliyun Vswitch ID
label: VSwitch
prompt: Choose a VSwitch...
privateIp:
label: Private IP
placeholder: Private IP in Private Network
privateAddressOnly:
label: Private Address Only
securitySection: Security Section
securitySection:
label: Security
detail: Choose the security groups that will be applied to Instances
securityGroup:
label: Security Group
placeholder: Security Group
prompt: Choose a Security Group...
sshPassword:
label: SSH Password
placeholder: Set Instance SSH Password, Blank for Auto set
provided: Provided
tags:
addActionLabel: Add Instance Tag
valueLabel: Tags
placeholder: e.g. dev
errors:
accessKeyRequired: Access Key is required.
accessSecretRequired: Access Secret Key is required.
sshPasswordLengthNotValid: The length of SSH password must between eight and thirty.
sshPasswordInvalidCharacter: SSH password contains invalid characters.
sshPasswordFormatError: "SSH password must contain at least three out of four kinds of following characters: uppercase letter, lowercase letters, numbers, and special characters."
nameNotValidForApp: The name is invalid according to the {appName} hostname rule.
zstack:
access:
title: 1. Account Access

24784
vendor/aliyun-sdk.js vendored Normal file

File diff suppressed because it is too large Load Diff