mirror of https://github.com/rancher/ui.git
Merge pull request #1205 from westlywright/concloud
New Host Templates and Host Launch
This commit is contained in:
commit
1b07479e91
|
|
@ -41,7 +41,7 @@
|
|||
{{else}}
|
||||
<section>
|
||||
<div>
|
||||
{{host-settings saved="savedHost"}}
|
||||
{{host-settings saved=(action savedHost)}}
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
|
|
|||
|
|
@ -2,56 +2,24 @@ import Ember from 'ember';
|
|||
import Driver from 'ui/mixins/driver';
|
||||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
errors: null,
|
||||
model: null,
|
||||
config: null,
|
||||
hostTemplates: null,
|
||||
selectedHostTemplate: null,
|
||||
errors: null,
|
||||
host: null,
|
||||
clonedModel: null,
|
||||
primaryResource: Ember.computed.alias('clonedModel'),
|
||||
hostOptions: null,
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.setProperties({
|
||||
hostOptions: this.get(`hostTemplate.publicValues.${this.get('hostTemplate.driver')}Config`),
|
||||
clonedModel: this.get('host').clone(),
|
||||
});
|
||||
|
||||
},
|
||||
|
||||
actions: {
|
||||
saveTemp() {
|
||||
if (this.get('selectedHostTemplate')) {
|
||||
if (this.get('selectedHostTemplate.accountId')) {
|
||||
this.buildModelOut(this.get('model'), this.get('selectedHostTemplate.id')).then((/*result*/) => {
|
||||
this.sendAction('save');
|
||||
});
|
||||
} else {
|
||||
this.get('selectedHostTemplate').save().then((hstTemplate) => {
|
||||
hstTemplate.waitForNotTransitioning().then(() => {
|
||||
this.buildModelOut(this.get('model'), this.get('selectedHostTemplate.id')).then((/*result*/) => {
|
||||
this.sendAction('save');
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
this.buildModelOut(this.get('model')).then((/*result*/) => {
|
||||
this.sendAction('save');
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
buildModelOut: function(modelIn, hostId=null) {
|
||||
var modelOut = modelIn;
|
||||
|
||||
if (hostId) {
|
||||
Ember.$.extend(modelOut, {hostTemplateId: hostId});
|
||||
}
|
||||
|
||||
modelOut.setProperties({
|
||||
rancherConfig: {
|
||||
flavor: this.get('config.uiOptions.id')
|
||||
}
|
||||
});
|
||||
|
||||
let errors = [];
|
||||
return modelOut.save().catch((err) => {
|
||||
errors.pushObject(err);
|
||||
}).finally(() => {
|
||||
if ( errors.length ) {
|
||||
this.set('errors', errors);
|
||||
} else {
|
||||
this.set('errors', null);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,87 +1 @@
|
|||
<div class="hosts-cloud-add">
|
||||
<section class="header clearfix">
|
||||
<div class="row">
|
||||
<div class="mb-0">
|
||||
<h1>
|
||||
{{t 'hostsPage.cloudHostsPage.addPage.header'}}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-20">
|
||||
<form>
|
||||
<section class="horizontal-form">
|
||||
<div class="row addtl-info">
|
||||
<div class="col span-4">
|
||||
<div class="nav-boxes driver">
|
||||
<div class="nav-box-item driver machine-driver active {{config.provider}}"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-8">
|
||||
<div class="price">
|
||||
{{#tooltip-element type="tooltip-basic" model=(concat (format-number config.uiOptions.pricePerHour style='currency' currency='USD') (t 'hostsPage.cloudHostsPage.favoritesPage.pricePerHour')) tooltipTemplate='tooltip-static' aria-describedby="tooltip-base" tooltipFor="cloud-host-launch"}}
|
||||
<div class="inline-block">
|
||||
{{#if config.provider}}
|
||||
{{#if (eq config.provider 'digitalocean') }}
|
||||
{{format-number config.uiOptions.pricePerMonth style='currency' currency='USD'}}<span class="addon">{{t 'hostsPage.cloudHostsPage.favoritesPage.price'}}</span>
|
||||
{{else}}
|
||||
{{format-number config.uiOptions.pricePerMonth style='currency' currency='USD'}}<span class="addon">{{t 'hostsPage.cloudHostsPage.favoritesPage.price'}}</span>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
{{/tooltip-element}}
|
||||
</div>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{config.uiOptions.displayName}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{config.uiOptions.realm}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.memory'}}</label>
|
||||
{{config.uiOptions.memory}}{{t 'hostsPage.cloudHostsPage.addPage.memStUnit'}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.storage'}}</label>
|
||||
{{config.uiOptions.storage}}{{t 'hostsPage.cloudHostsPage.addPage.memStUnit'}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.transfer'}}</label>
|
||||
{{config.uiOptions.transfer}}{{t 'hostsPage.cloudHostsPage.addPage.transferUnit'}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
{{partial "host/add-common"}}
|
||||
<hr />
|
||||
{{#if (or (eq config.uiOptions.apiKeySupport 'byokey') (eq config.uiOptions.apiKeySupport 'both'))}}
|
||||
{{add-host-template
|
||||
templates=hostTemplates
|
||||
provider=config.pretty_provider
|
||||
selectedKey=(mut selectedHostTemplate)
|
||||
}}
|
||||
<hr/>
|
||||
{{/if}}
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
{{#advanced-section}}
|
||||
{{form-user-labels initialLabels=model.labels setLabels=(action 'setLabels')}}
|
||||
{{/advanced-section}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="saveTemp" cancel=cancel createLabel='hostsPage.cloudHostsPage.addPage.launch'}}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
{{partial 'host/host-templates/host-launch'}}
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ export default Ember.Component.extend(ManageLabels, {
|
|||
|
||||
this.$('INPUT.key').last()[0].focus();
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
|
||||
didReceiveAttrs() {
|
||||
|
|
@ -31,6 +31,7 @@ export default Ember.Component.extend(ManageLabels, {
|
|||
}
|
||||
},
|
||||
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
|
|
|
|||
|
|
@ -11,22 +11,39 @@ let isOptimized=[
|
|||
];
|
||||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'aliyunecs',
|
||||
aliyunecsConfig : Ember.computed.alias('model.aliyunecsConfig'),
|
||||
isOptimized : isOptimized,
|
||||
driverName: 'aliyunecs',
|
||||
aliyunecsConfig: Ember.computed.alias('model.publicValues.aliyunecsConfig'),
|
||||
isOptimized: isOptimized,
|
||||
|
||||
|
||||
bootstrap: function() {
|
||||
let config = this.get('store').createRecord({
|
||||
type : 'aliyunecsConfig',
|
||||
type: 'aliyunecsConfig',
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
aliyunecsConfig: config,
|
||||
type: 'hostTemplate',
|
||||
driver: 'aliyunecs',
|
||||
publicValues: {
|
||||
aliyunecsConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
aliyunecsConfig: {
|
||||
accessKeySecret: ''
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
//this.set('editing', false);
|
||||
},
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.accountSection'}}</span>
|
||||
|
|
@ -12,207 +22,207 @@
|
|||
|
||||
<div class="row">
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.accessKey.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.accessKeyId placeholder=(t 'machine.driverAliyunecs.accessKey.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.accessKey.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.accessKeyId placeholder=(t 'machine.driverAliyunecs.accessKey.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.accessKeySecret.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.accessKeySecret placeholder=(t 'machine.driverAliyunecs.accessKeySecret.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.accessKeySecret.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="password" class="form-control" value=model.secretValues.aliyunecsConfig.accessKeySecret placeholder=(t 'machine.driverAliyunecs.accessKeySecret.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.apiEndpoint.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.apiEndpoint placeholder=(t 'machine.driverAliyunecs.apiEndpoint.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceDescription.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.description placeholder=(t 'machine.driverAliyunecs.instanceDescription.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceType.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.instanceType placeholder=(t 'machine.driverAliyunecs.instanceType.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.apiEndpoint.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.apiEndpoint placeholder=(t 'machine.driverAliyunecs.apiEndpoint.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.systemImage.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.imageId placeholder=(t 'machine.driverAliyunecs.systemImage.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceTag.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.tag placeholder=(t 'machine.driverAliyunecs.instanceTag.placeholder')}}
|
||||
</div>
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceDescription.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.description placeholder=(t 'machine.driverAliyunecs.instanceDescription.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.internetMaxBandwidth.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.internetMaxBandwidth placeholder=(t 'machine.driverAliyunecs.internetMaxBandwidth.placeholder')}}
|
||||
<div class="input-group-addon bg-default">Mbps</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.aliyunSLB.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.slbId placeholder=(t 'machine.driverAliyunecs.aliyunSLB.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceType.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.instanceType placeholder=(t 'machine.driverAliyunecs.instanceType.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.systemImage.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.imageId placeholder=(t 'machine.driverAliyunecs.systemImage.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.storageSection'}}</span>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.instanceTag.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.tag placeholder=(t 'machine.driverAliyunecs.instanceTag.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.internetMaxBandwidth.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.internetMaxBandwidth placeholder=(t 'machine.driverAliyunecs.internetMaxBandwidth.placeholder')}}
|
||||
<div class="input-group-addon bg-default">Mbps</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.aliyunSLB.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.slbId placeholder=(t 'machine.driverAliyunecs.aliyunSLB.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.isOptimized.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{!--{{input type="text" class="form-control" value=aliyunecsConfig.isOptimized placeholder=(t 'machine.driverAliyunecs.isOptimized.placeholder')}}--}}
|
||||
{{new-select
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.storageSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.isOptimized.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{!--{{input type="text" class="form-control" value=aliyunecsConfig.isOptimized placeholder=(t 'machine.driverAliyunecs.isOptimized.placeholder')}}--}}
|
||||
{{new-select
|
||||
classNames="form-control"
|
||||
content=isOptimized
|
||||
optionLabelPath='value'
|
||||
value=aliyunecsConfig.isOptimized
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.systemDiskCategory.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.systemDiskCategory placeholder=(t 'machine.driverAliyunecs.systemDiskCategory.placeholder')}}
|
||||
</div>
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.dataDiskCategory.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.diskCategory placeholder=(t 'machine.driverAliyunecs.dataDiskCategory.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.systemDiskCategory.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.systemDiskCategory placeholder=(t 'machine.driverAliyunecs.systemDiskCategory.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.dataDiskSize.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.diskSize placeholder=(t 'machine.driverAliyunecs.dataDiskSize.placeholder')}}
|
||||
<div class="input-group-addon bg-default">GB</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.dataDiskCategory.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.diskCategory placeholder=(t 'machine.driverAliyunecs.dataDiskCategory.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.region.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.region placeholder=(t 'machine.driverAliyunecs.region.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.dataDiskSize.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<div class="input-group">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.diskSize placeholder=(t 'machine.driverAliyunecs.dataDiskSize.placeholder')}}
|
||||
<div class="input-group-addon bg-default">GB</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.zone.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.zone placeholder=(t 'machine.driverAliyunecs.zone.placeholder')}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.region.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.region placeholder=(t 'machine.driverAliyunecs.region.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.networkSection'}}</span>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.zone.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.zone placeholder=(t 'machine.driverAliyunecs.zone.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.networkSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.routeCIDR.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.routeCidr placeholder=(t 'machine.driverAliyunecs.routeCIDR.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.routeCIDR.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.routeCidr placeholder=(t 'machine.driverAliyunecs.routeCIDR.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.vpcId.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.vpcId placeholder=(t 'machine.driverAliyunecs.vpcId.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.vpcId.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.vpcId placeholder=(t 'machine.driverAliyunecs.vpcId.placeholder')}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.vswitchId.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.vswitchId placeholder=(t 'machine.driverAliyunecs.vswitchId.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.vswitchId.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.vswitchId placeholder=(t 'machine.driverAliyunecs.vswitchId.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.privateIp.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.privateIp placeholder=(t 'machine.driverAliyunecs.privateIp.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.privateIp.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.privateIp placeholder=(t 'machine.driverAliyunecs.privateIp.placeholder')}}
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.privateAddressOnly.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="checkbox" class="form-control" checked=aliyunecsConfig.privateAddressOnly}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.securitySection'}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.securityGroup.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.securityGroup placeholder=(t 'machine.driverAliyunecs.securityGroup.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.privateAddressOnly.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="checkbox" class="form-control" checked=aliyunecsConfig.privateAddressOnly}}
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.sshPassword.label'}}</label>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.securitySection'}}</span>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.securityGroup.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.securityGroup placeholder=(t 'machine.driverAliyunecs.securityGroup.placeholder')}}
|
||||
</div>
|
||||
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverAliyunecs.sshPassword.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.sshPassword placeholder=(t 'machine.driverAliyunecs.sshPassword.placeholder')}}
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="text" class="form-control" value=aliyunecsConfig.sshPassword placeholder=(t 'machine.driverAliyunecs.sshPassword.placeholder')}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ export default Ember.Component.extend(Driver, {
|
|||
prefs : Ember.inject.service(),
|
||||
driverName : 'amazonec2',
|
||||
model : null,
|
||||
amazonec2Config : Ember.computed.alias('model.amazonec2Config'),
|
||||
amazonec2Config : Ember.computed.alias('model.publicValues.amazonec2Config'),
|
||||
|
||||
clients : null,
|
||||
allSubnets : null,
|
||||
|
|
@ -139,19 +139,37 @@ export default Ember.Component.extend(Driver, {
|
|||
type : 'amazonec2Config',
|
||||
region : 'us-west-2',
|
||||
instanceType : 't2.micro',
|
||||
securityGroup : 'rancher-machine',
|
||||
securityGroup : ['rancher-machine',],
|
||||
zone : 'a',
|
||||
rootSize : 16,
|
||||
rootSize : '16',
|
||||
accessKey : pref.accessKey||'',
|
||||
secretKey : pref.secretKey||'',
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type : 'host',
|
||||
amazonec2Config : config,
|
||||
type: 'hostTemplate',
|
||||
driver: 'amazonec2',
|
||||
publicValues: {
|
||||
amazonec2Config: config
|
||||
},
|
||||
secretValues: {
|
||||
amazonec2Config: {
|
||||
secretKey: pref.secretKey||'',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
|
||||
init: function() {
|
||||
this._super(...arguments);
|
||||
|
||||
|
|
@ -191,15 +209,6 @@ export default Ember.Component.extend(Driver, {
|
|||
});
|
||||
}.observes('context.step'),
|
||||
|
||||
selectedSecurityGroupChanged: Ember.observer('whichSecurityGroup', 'isStep5', function() {
|
||||
if (this.get('isStep5') && this.get('whichSecurityGroup') === 'custom') {
|
||||
Ember.run.scheduleOnce('afterRender', this, function() {
|
||||
this.initMultiselect();
|
||||
});
|
||||
}
|
||||
}),
|
||||
|
||||
|
||||
actions: {
|
||||
awsLogin: function() {
|
||||
let self = this;
|
||||
|
|
@ -207,13 +216,13 @@ export default Ember.Component.extend(Driver, {
|
|||
this.set('step',2);
|
||||
|
||||
this.set('amazonec2Config.accessKey', (this.get('amazonec2Config.accessKey')||'').trim());
|
||||
this.set('amazonec2Config.secretKey', (this.get('amazonec2Config.secretKey')||'').trim());
|
||||
this.set('model.secretValues.amazonec2Config.secretKey', (this.get('model.secretValues.amazonec2Config.secretKey')||'').trim());
|
||||
|
||||
let subnets = [];
|
||||
let rName = this.get('amazonec2Config.region');
|
||||
let ec2 = new AWS.EC2({
|
||||
accessKeyId : this.get('amazonec2Config.accessKey'),
|
||||
secretAccessKey : this.get('amazonec2Config.secretKey'),
|
||||
secretAccessKey : this.get('model.secretValues.amazonec2Config.secretKey'),
|
||||
region : rName,
|
||||
});
|
||||
|
||||
|
|
@ -400,76 +409,6 @@ export default Ember.Component.extend(Driver, {
|
|||
},
|
||||
},
|
||||
|
||||
initMultiselect: function() {
|
||||
var view = this;
|
||||
|
||||
var opts = {
|
||||
maxHeight: 200,
|
||||
buttonClass: 'btn bg-default',
|
||||
buttonWidth: '100%',
|
||||
|
||||
templates: {
|
||||
li: '<li><a tabindex="0"><label></label></a></li>',
|
||||
},
|
||||
|
||||
buttonText: function(options/*, select*/) {
|
||||
var label = 'Security Groups: ';
|
||||
if ( options.length === 0 )
|
||||
{
|
||||
label += 'None';
|
||||
}
|
||||
else if ( options.length === 1 )
|
||||
{
|
||||
label += $(options[0]).text();
|
||||
}
|
||||
else
|
||||
{
|
||||
label += options.length + ' Selected';
|
||||
}
|
||||
|
||||
return label;
|
||||
},
|
||||
|
||||
onChange: function(/*option, checked*/) {
|
||||
var self = this;
|
||||
var options = $('option', this.$select);
|
||||
var selectedOptions = this.getSelected();
|
||||
var allOption = $('option[value="ALL"]',this.$select)[0];
|
||||
|
||||
var isAll = $.inArray(allOption, selectedOptions) >= 0;
|
||||
|
||||
if ( isAll )
|
||||
{
|
||||
options.each(function(k, option) {
|
||||
var $option = $(option);
|
||||
if ( option !== allOption )
|
||||
{
|
||||
self.deselect($(option).val());
|
||||
$option.prop('disabled',true);
|
||||
$option.parent('li').addClass('disabled');
|
||||
}
|
||||
});
|
||||
|
||||
// @TODO Figure out why deslect()/select() doesn't fix the state in the ember object and remove this hackery...
|
||||
var ary = view.get('instance.' + (this.$select.hasClass('select-cap-add') ? 'capAdd' : 'capDrop'));
|
||||
ary.clear();
|
||||
ary.pushObject('ALL');
|
||||
}
|
||||
else
|
||||
{
|
||||
options.each(function(k, option) {
|
||||
var $option = $(option);
|
||||
$option.prop('disabled',false);
|
||||
$option.parent('li').removeClass('disabled');
|
||||
});
|
||||
}
|
||||
|
||||
this.$select.multiselect('refresh');
|
||||
}
|
||||
};
|
||||
|
||||
this.$('.existing-security-groups').multiselect(opts);
|
||||
},
|
||||
selectedZone: Ember.computed('amazonec2Config.{region,zone}', {
|
||||
get: function() {
|
||||
let config = this.get('amazonec2Config');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,20 @@
|
|||
<section class="horizontal-form">
|
||||
<form>
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAmazon.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mb-20">
|
||||
<span>{{t 'machine.driverAmazon.accessSection'}}</span>
|
||||
</div>
|
||||
|
|
@ -39,7 +53,7 @@
|
|||
</div>
|
||||
<div class="col span-8">
|
||||
{{#if isStep1}}
|
||||
{{input type="password" name="password" classNames="form-control" placeholder=(t 'machine.driverAmazon.secretKey.placeholder') value=amazonec2Config.secretKey}}
|
||||
{{input type="password" name="password" classNames="form-control" placeholder=(t 'machine.driverAmazon.secretKey.placeholder') value=model.secretValues.amazonec2Config.secretKey}}
|
||||
{{else}}
|
||||
<div class="text-muted text-italic">{{t 'machine.driverAmazon.secretKey.provided'}}</div>
|
||||
{{/if}}
|
||||
|
|
@ -151,25 +165,14 @@
|
|||
</div>
|
||||
<div class="col span-8">
|
||||
{{#if isStep5}}
|
||||
<div class="radio">
|
||||
<label>
|
||||
{{radio-button selection=whichSecurityGroup value="default"}}
|
||||
{{#if defaultSecurityGroup}}
|
||||
{{t 'machine.driverAmazon.securityGroup.defaultExisting' groupName=defaultSecurityGroupName htmlSafe=true}}
|
||||
{{else}}
|
||||
{{t 'machine.driverAmazon.securityGroup.defaultCreate' groupName=defaultSecurityGroupName htmlSafe=true}}
|
||||
{{/if}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
{{#if (and settings.isRancher (not isCustomSecurityGroup))}}
|
||||
<p class="text-info ml-20"><a href="{{settings.docsBase}}/hosts/amazon/#required-ports-for-rancher-to-work" target="_blank">{{t 'machine.driverAmazon.portHelp.link'}}</a> {{t 'machine.driverAmazon.portHelp.text'}}</p>
|
||||
{{/if}}
|
||||
|
||||
<div class="radio">
|
||||
<div class="radio pt-10">
|
||||
<label>
|
||||
{{radio-button selection=whichSecurityGroup value="custom"}}
|
||||
{{t 'machine.driverAmazon.securityGroup.custom'}}
|
||||
{{t 'machine.driverAmazon.securityGroup.choose'}}
|
||||
</label>
|
||||
</div>
|
||||
|
||||
|
|
@ -226,14 +229,6 @@
|
|||
|
||||
<section class="horizontal-form {{unless isGteStep7 'hide'}}" style="padding-top: 0;">
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAmazon.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAmazon.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import { regions, sizes, storageTypes, environments } from 'ui/utils/azure-choic
|
|||
import Driver from 'ui/mixins/driver';
|
||||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
azureConfig : Ember.computed.alias('model.azureConfig'),
|
||||
azureConfig : Ember.computed.alias('model.publicValues.azureConfig'),
|
||||
environments : environments.sortBy('value'),
|
||||
sizeChoices : sizes.sortBy('value'),
|
||||
driverName : 'azure',
|
||||
|
|
@ -31,13 +31,20 @@ export default Ember.Component.extend(Driver, {
|
|||
type : 'azureConfig',
|
||||
subscriptionId : '',
|
||||
clientId : '',
|
||||
clientSecret : '',
|
||||
openPort : ['500/udp','4500/udp'],
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
azureConfig: config,
|
||||
type: 'hostTemplate',
|
||||
driver: 'azure',
|
||||
publicValues: {
|
||||
azureConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
azureConfig: {
|
||||
clientSecret : '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
this.set('editing', false);
|
||||
|
|
@ -125,11 +132,10 @@ export default Ember.Component.extend(Driver, {
|
|||
}),
|
||||
|
||||
validate: function() {
|
||||
this._super();
|
||||
let errors = this.get('errors')||[];
|
||||
let errors = [];
|
||||
|
||||
this.set('prefix',(this.get('prefix')||'').toLowerCase());
|
||||
let name = this.get('model.hostname');
|
||||
let name = this.get('model.name');
|
||||
if ( name.length < 4 || name.length > 62 ) {
|
||||
errors.push('Name must be between 4 and 62 characters long');
|
||||
}
|
||||
|
|
@ -146,7 +152,7 @@ export default Ember.Component.extend(Driver, {
|
|||
errors.push('Client ID is requried');
|
||||
}
|
||||
|
||||
if (!this.get('azureConfig.clientSecret') ) {
|
||||
if (!this.get('model.secretValues.azureConfig.clientSecret') ) {
|
||||
errors.push('Client Secret is requried');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,18 @@
|
|||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAzure.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAzure.placementSection'}}</span>
|
||||
|
|
@ -61,9 +71,9 @@
|
|||
|
||||
<div class="col span-6">
|
||||
<label class="pb-5">{{t 'machine.driverAzure.clientSecret.label'}}{{field-required}}</label>
|
||||
{{input type="password" value=azureConfig.clientSecret classNames="form-control"}}
|
||||
{{input type="password" value=model.secretValues.azureConfig.clientSecret classNames="form-control"}}
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
|
@ -113,7 +123,7 @@
|
|||
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAzure.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverAzure.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
|
@ -138,7 +148,7 @@
|
|||
<label class="pb-5">{{t 'machine.driverAzure.dockerPort.label'}}</label>
|
||||
{{input type="text" value=azureConfig.dockerPort classNames="form-control" placeholder=(t 'machine.driverAzure.dockerPort.placeholder')}}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="col span-6">
|
||||
<label class="pb-5">{{t 'machine.driverAzure.openPort.label'}}</label>
|
||||
{{input type="text" value=openPorts classNames="form-control" placeholder=(t 'machine.driverAzure.openPort.placeholder')}}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@
|
|||
<li>
|
||||
{{t 'machine.driverCustom.step3'}}
|
||||
<div class="mt-10">
|
||||
{{form-user-labels setLabels=(action 'setLabels')}}
|
||||
{{form-user-labels setLabels=(action 'setLabels') expandAll=null}}
|
||||
</div>
|
||||
</li>
|
||||
<li>
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@ export default Ember.Component.extend(Driver, {
|
|||
driverName: 'digitalocean',
|
||||
regionChoices: null,
|
||||
model: null,
|
||||
digitaloceanConfig: Ember.computed.alias('model.digitaloceanConfig'),
|
||||
digitaloceanConfig: Ember.computed.alias('model.publicValues.digitaloceanConfig'),
|
||||
step1: true,
|
||||
sizeChoices: null,
|
||||
imageChoices: null,
|
||||
|
|
@ -102,24 +102,31 @@ export default Ember.Component.extend(Driver, {
|
|||
bootstrap: function() {
|
||||
let config = this.get('store').createRecord({
|
||||
type : 'digitaloceanConfig',
|
||||
accessToken : '',
|
||||
size : '1gb',
|
||||
region : 'nyc3',
|
||||
image : 'ubuntu-16-04-x64'
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
digitaloceanConfig: config,
|
||||
type: 'hostTemplate',
|
||||
driver: 'digitalocean',
|
||||
publicValues: {
|
||||
digitaloceanConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
digitaloceanConfig: {
|
||||
accessToken : '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
|
||||
validate: function() {
|
||||
this._super();
|
||||
// this._super();
|
||||
let errors = this.get('errors')||[];
|
||||
let name = this.get('model.hostname')||'';
|
||||
let accessToken = this.get('digitaloceanConfig.accessToken')||'';
|
||||
let name = this.get('model.name')||'';
|
||||
let accessToken = this.get('model.secretValues.digitaloceanConfig.accessToken')||'';
|
||||
|
||||
if ( name.length > 200 ) {
|
||||
errors.push('"name" should be 1-200 characters long');
|
||||
|
|
@ -157,7 +164,7 @@ export default Ember.Component.extend(Driver, {
|
|||
return fetch(url, {
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-Api-Auth-Header': 'Bearer ' + this.get('model.digitaloceanConfig.accessToken'),
|
||||
'X-Api-Auth-Header': 'Bearer ' + this.get('model.secretValues.digitaloceanConfig.accessToken'),
|
||||
},
|
||||
}).then((res) => {
|
||||
let body = res.body;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,21 @@
|
|||
<section class="horizontal-form">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverDigitalocean.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
{{#if step1}}
|
||||
<form>
|
||||
|
||||
<div class="over-hr mb-20">
|
||||
<span>{{t 'machine.driverDigitalocean.accountSection'}}</span>
|
||||
</div>
|
||||
|
|
@ -10,7 +25,7 @@
|
|||
<label>{{t 'machine.driverDigitalocean.accessToken.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{input type="password" value=digitaloceanConfig.accessToken classNames="form-control" placeholder=(t 'machine.driverDigitalocean.accessToken.placeholder')}}
|
||||
{{input type="password" value=model.secretValues.digitaloceanConfig.accessToken classNames="form-control" placeholder=(t 'machine.driverDigitalocean.accessToken.placeholder')}}
|
||||
<p class="text-info">{{t 'machine.driverDigitalocean.accessToken.help' htmlSafe=true}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -20,17 +35,13 @@
|
|||
{{#if gettingData}}
|
||||
<button class="btn bg-primary btn-disabled"><i class="icon icon-spinner icon-spin"></i> {{t 'generic.loading'}}</button>
|
||||
{{else}}
|
||||
<button {{action "getData" 'region'}} class="btn bg-primary" disabled={{not model.digitaloceanConfig.accessToken}}>{{t 'machine.driverDigitalocean.authAccountButton'}}</button>
|
||||
<button {{action "getData" 'region'}} class="btn bg-primary" disabled={{not model.secretValues.digitaloceanConfig.accessToken}}>{{t 'machine.driverDigitalocean.authAccountButton'}}</button>
|
||||
{{/if}}
|
||||
<button {{action "cancel"}} class="btn bg-transparent">{{t 'generic.cancel'}}</button>
|
||||
</div>
|
||||
</form>
|
||||
{{else}}
|
||||
<div class="container-fluid">
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverDigitalocean.regionSection'}}</span>
|
||||
</div>
|
||||
|
|
@ -49,7 +60,7 @@
|
|||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverDigitalocean.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverDigitalocean.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row inline-form">
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@ let RANCHER_INGRESS_RULES = [
|
|||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'exoscale',
|
||||
model : null,
|
||||
exoscaleConfig : Ember.computed.alias('model.exoscaleConfig'),
|
||||
exoscaleConfig : Ember.computed.alias('model.publicValues.exoscaleConfig'),
|
||||
|
||||
allDiskSizes : null,
|
||||
allInstanceProfiles : null,
|
||||
|
|
@ -68,19 +68,38 @@ export default Ember.Component.extend(Driver, {
|
|||
bootstrap: function() {
|
||||
let config = this.get('store').createRecord({
|
||||
type: 'exoscaleConfig',
|
||||
apiKey: '',
|
||||
apiSecretKey: '',
|
||||
exoscaleApiKey: '',
|
||||
diskSize: 50,
|
||||
instanceProfile: 'small',
|
||||
securityGroup: 'rancher-machine'
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
exoscaleConfig: config
|
||||
type: 'hostTemplate',
|
||||
driver: 'exoscale',
|
||||
publicValues: {
|
||||
exoscaleConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
exoscaleConfig: {
|
||||
exoscaleApiSecretKey: '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
|
||||
|
||||
afterInit: function() {
|
||||
this._super();
|
||||
|
||||
|
|
@ -109,8 +128,8 @@ export default Ember.Component.extend(Driver, {
|
|||
this.set('errors', null);
|
||||
this.set('step', 2);
|
||||
|
||||
this.set('exoscaleConfig.apiKey', (this.get('exoscaleConfig.apiKey')||'').trim());
|
||||
this.set('exoscaleConfig.apiSecretKey', (this.get('exoscaleConfig.apiSecretKey')||'').trim());
|
||||
this.set('exoscaleConfig.exoscaleApiKey', (this.get('exoscaleConfig.exoscaleApiKey')||'').trim());
|
||||
this.set('model.secretValues.exoscaleConfig.exoscaleApiSecretKey', (this.get('model.secretValues.exoscaleConfig.exoscaleApiSecretKey')||'').trim());
|
||||
|
||||
this.apiRequest('listSecurityGroups').then((res) => {
|
||||
let groups = [];
|
||||
|
|
@ -271,7 +290,7 @@ export default Ember.Component.extend(Driver, {
|
|||
let url = this.get('app.proxyEndpoint') + '/' + this.exoscaleApi;
|
||||
params = params || {};
|
||||
params.command = command;
|
||||
params.apiKey = this.get('exoscaleConfig.apiKey');
|
||||
params.apiKey = this.get('exoscaleConfig.exoscaleApiKey');
|
||||
params.response = 'json';
|
||||
|
||||
return ajaxPromise({url: url,
|
||||
|
|
@ -293,7 +312,7 @@ export default Ember.Component.extend(Driver, {
|
|||
.sort()
|
||||
.join('&');
|
||||
settings.data += '&signature=' + encodeURIComponent(AWS.util.crypto.hmac(
|
||||
this.get('exoscaleConfig.apiSecretKey'), qs, 'base64', 'sha1'));
|
||||
this.get('model.secretValues.exoscaleConfig.exoscaleApiSecretKey'), qs, 'base64', 'sha1'));
|
||||
return true;
|
||||
},
|
||||
data: params}, true);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,21 @@
|
|||
<section class="horizontal-form">
|
||||
<form>
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverExoscale.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mb-20">
|
||||
<span>{{t 'machine.driverExoscale.accountSection'}}</span>
|
||||
</div>
|
||||
|
|
@ -11,9 +26,9 @@
|
|||
</div>
|
||||
<div class="col span-10">
|
||||
{{#if isStep1}}
|
||||
{{input type="text" name="username" classNames="form-control" placeholder=(t 'machine.driverExoscale.apiKey.placeholder') value=exoscaleConfig.apiKey}}
|
||||
{{input type="text" name="username" classNames="form-control" placeholder=(t 'machine.driverExoscale.apiKey.placeholder') value=exoscaleConfig.exoscaleApiKey}}
|
||||
{{else}}
|
||||
<div>{{exoscaleConfig.apiKey}}</div>
|
||||
<div>{{exoscaleConfig.exoscaleApiKey}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -23,7 +38,7 @@
|
|||
</div>
|
||||
<div class="col span-10">
|
||||
{{#if isStep1}}
|
||||
{{input type="password" name="password" classNames="form-control" placeholder=(t 'machine.driverExoscale.secretKey.placeholder') value=exoscaleConfig.apiSecretKey}}
|
||||
{{input type="password" name="password" classNames="form-control" placeholder=(t 'machine.driverExoscale.secretKey.placeholder') value=model.secretValues.exoscaleConfig.exoscaleApiSecretKey}}
|
||||
{{else}}
|
||||
<div class="text-muted text-italic">{{t 'machine.driverExoscale.secretKey.provided'}}</div>
|
||||
{{/if}}
|
||||
|
|
@ -128,13 +143,9 @@
|
|||
<section class="horizontal-form pt-0 {{unless isGteStep6 'hide'}}">
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverExoscale.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverExoscale.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
|
||||
<div class="row inline-form">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverExoscale.instanceProfile.label'}}</label>
|
||||
|
|
|
|||
|
|
@ -12,16 +12,10 @@ export default Ember.Component.extend(Driver, {
|
|||
schemas : null,
|
||||
driverOpts : null,
|
||||
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
|
||||
this._super();
|
||||
this.driverChanged();
|
||||
},
|
||||
|
||||
bootstrap() {
|
||||
let model = this.get('store').createRecord({
|
||||
type: 'host',
|
||||
type: 'hostTemplate',
|
||||
isOfTypeOther: true,
|
||||
});
|
||||
|
||||
this.setProperties({
|
||||
|
|
@ -29,6 +23,16 @@ export default Ember.Component.extend(Driver, {
|
|||
model: model
|
||||
});
|
||||
},
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this.setProperties({
|
||||
|
|
@ -37,50 +41,76 @@ export default Ember.Component.extend(Driver, {
|
|||
});
|
||||
},
|
||||
|
||||
fieldNames: function() {
|
||||
fieldNames: Ember.computed('otherDriver', 'model', function() {
|
||||
let driver = this.get('otherDriver');
|
||||
|
||||
if ( driver ) {
|
||||
return Object.keys(this.get('userStore').getById('schema', driver.toLowerCase()).get('resourceFields'));
|
||||
}
|
||||
}.property('otherDriver', 'model'),
|
||||
}),
|
||||
|
||||
driverChanged: function() {
|
||||
let driver = this.get('otherDriver');
|
||||
let host = this.get('model');
|
||||
getSecrets(fields) {
|
||||
let keys = Object.keys(fields);
|
||||
let out = [];
|
||||
keys.forEach((key) => {
|
||||
if (key.toLowerCase().indexOf('secret') > -1 || key.toLowerCase().indexOf('password') > -1){
|
||||
out.push(key);
|
||||
}
|
||||
})
|
||||
return out;
|
||||
},
|
||||
|
||||
if ( driver && host) {
|
||||
if ( !host.get(driver) ) {
|
||||
host.set(driver, this.get('store').createRecord({ type: driver }));
|
||||
driverChanged: Ember.on('init', Ember.observer('otherDriver','model', function() {
|
||||
if (this.get('otherDriver')) {
|
||||
let driver = this.get('otherDriver').split('C')[0];
|
||||
let hostTemplate = this.get('model');
|
||||
let config = this.get('store').createRecord({
|
||||
type : this.get('otherDriver'),
|
||||
});
|
||||
let secrets = this.getSecrets(this.get('userStore').getById('schema', this.get('otherDriver').toLowerCase()).get('resourceFields'));
|
||||
let secretConfig = {
|
||||
[this.get('otherDriver')]: {}
|
||||
}
|
||||
|
||||
this.set('driverOpts', host.get(driver));
|
||||
if (secrets) {
|
||||
secrets.forEach((secret) => {
|
||||
secretConfig[secret] = '';
|
||||
});
|
||||
}
|
||||
hostTemplate.setProperties({
|
||||
driver: driver,
|
||||
publicValues: {
|
||||
[this.get('otherDriver')]: config
|
||||
},
|
||||
secretValues: {
|
||||
[this.get('otherDriver')]: secretConfig
|
||||
},
|
||||
});
|
||||
this.set('driverOpts', hostTemplate.get(`publicValues.${this.get('otherDriver')}`));
|
||||
}
|
||||
else {
|
||||
this.set('otherDriver', this.get('otherChoices.firstObject.value'));
|
||||
}
|
||||
}.observes('otherDriver','model'),
|
||||
})),
|
||||
|
||||
otherChoices: function() {
|
||||
otherChoices: Ember.computed('availableDrivers.@each.{hasUi,name}', function() {
|
||||
let out = [];
|
||||
this.get('availableDrivers').filterBy('hasUi',false).forEach((driver) => {
|
||||
out.push({label: driver.name, value: driver.name+'Config'});
|
||||
});
|
||||
|
||||
return out;
|
||||
}.property('availableDrivers.@each.{hasUi,name}'),
|
||||
return out.sortBy('name');
|
||||
}),
|
||||
|
||||
willSave() {
|
||||
// Null out all the drivers that aren't the active one, because the API only accepts one.
|
||||
let activeDriver = this.get('otherDriver');
|
||||
let host = this.get('model');
|
||||
this.get('otherChoices').forEach((choice) => {
|
||||
let cur = choice.value;
|
||||
if ( choice.value !== activeDriver ) {
|
||||
host.set(cur, null);
|
||||
}
|
||||
});
|
||||
// willSave() {
|
||||
// // Null out all the drivers that aren't the active one, because the API only accepts one.
|
||||
// debugger;
|
||||
// let activeDriver = this.get('otherDriver');
|
||||
// let host = this.get('model');
|
||||
// this.get('otherChoices').forEach((choice) => {
|
||||
// let cur = choice.value;
|
||||
// if ( choice.value !== activeDriver ) {
|
||||
// host.set(cur, null);
|
||||
// }
|
||||
// });
|
||||
|
||||
return this._super();
|
||||
},
|
||||
// return this._super();
|
||||
// },
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,18 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{partial "host/add-common"}}
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverOther.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverOther.driverSection'}}</span>
|
||||
|
|
@ -13,9 +24,9 @@
|
|||
</div>
|
||||
<div class="col span-8">
|
||||
{{new-select
|
||||
classNames="form-control"
|
||||
content=otherChoices
|
||||
value=otherDriver
|
||||
classNames="form-control"
|
||||
content=otherChoices
|
||||
value=otherDriver
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -26,12 +37,12 @@
|
|||
|
||||
{{#each fieldNames as |fieldName|}}
|
||||
{{api-field
|
||||
resource=driverOpts
|
||||
resourceType=otherDriver
|
||||
field=fieldName
|
||||
value=(get driverOpts fieldName)
|
||||
schemas=schemas
|
||||
typeDocs=typeDocumentations
|
||||
resource=driverOpts
|
||||
resourceType=otherDriver
|
||||
field=fieldName
|
||||
value=(get driverOpts fieldName)
|
||||
schemas=schemas
|
||||
typeDocs=typeDocumentations
|
||||
}}
|
||||
{{/each}}
|
||||
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ let planChoices = PacketPlans.filter(function(plan) {
|
|||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'packet',
|
||||
packetConfig : Ember.computed.alias('model.packetConfig'),
|
||||
packetConfig : Ember.computed.alias('model.publicValues.packetConfig'),
|
||||
|
||||
facilityChoices : PacketFacilities,
|
||||
planChoices : planChoices,
|
||||
|
|
@ -27,7 +27,6 @@ export default Ember.Component.extend(Driver, {
|
|||
let store = this.get('store');
|
||||
let config = store.createRecord({
|
||||
type : 'packetConfig',
|
||||
apiKey : '',
|
||||
projectId : '',
|
||||
os : 'ubuntu_14_04',
|
||||
facilityCode : 'ewr1',
|
||||
|
|
@ -39,17 +38,29 @@ export default Ember.Component.extend(Driver, {
|
|||
type: 'host',
|
||||
packetConfig: config,
|
||||
}));
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'hostTemplate',
|
||||
driver: 'packet',
|
||||
publicValues: {
|
||||
packetConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
packetConfig: {
|
||||
apiKey : '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
this._super();
|
||||
let errors = this.get('errors')||[];
|
||||
let errors = [];
|
||||
|
||||
if (!this.get('packetConfig.projectId') ) {
|
||||
errors.push('Project ID is required');
|
||||
}
|
||||
|
||||
if (!this.get('packetConfig.apiKey') ) {
|
||||
if (!this.get('model.secretValues.packetConfig.apiKey') ) {
|
||||
errors.push('API Key is requried');
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +1,19 @@
|
|||
<form>
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverPacket.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverPacket.accountSection'}}</span>
|
||||
|
|
@ -16,13 +26,13 @@
|
|||
</div>
|
||||
<div class="col span-6">
|
||||
<label>{{t 'machine.driverPacket.apiKey.label'}}{{field-required}}</label>
|
||||
{{input type="password" name="password" value=packetConfig.apiKey classNames="form-control" placeholder=(t 'machine.driverPacket.apiKey.placeholder')}}
|
||||
{{input type="password" name="password" value=model.secretValues.packetConfig.apiKey classNames="form-control" placeholder=(t 'machine.driverPacket.apiKey.placeholder')}}
|
||||
<p class="text-info">{{t 'machine.driverPacket.apiKeyHelp' htmlSafe=true}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverPacket.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverPacket.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row inline-form">
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ flavorChoices.sort(function(a,b) {
|
|||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'rackspace',
|
||||
rackspaceConfig : Ember.computed.alias('model.rackspaceConfig'),
|
||||
rackspaceConfig : Ember.computed.alias('model.publicValues.rackspaceConfig'),
|
||||
flavorChoices : flavorChoices,
|
||||
regionChoices : [
|
||||
{label: 'Dallas (DFW)', value: 'DFW'},
|
||||
|
|
@ -56,14 +56,33 @@ export default Ember.Component.extend(Driver, {
|
|||
let config = store.createRecord({
|
||||
type: 'rackspaceConfig',
|
||||
username: '',
|
||||
apiKey: '',
|
||||
region: 'DFW',
|
||||
flavorId: 'general1-1',
|
||||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
rackspaceConfig: config,
|
||||
type: 'hostTemplate',
|
||||
driver: 'rackspace',
|
||||
publicValues: {
|
||||
rackspaceConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
rackspaceConfig: {
|
||||
apiKey: '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,9 +2,19 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverRackspace.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverRackspace.accountSection'}}</span>
|
||||
|
|
@ -24,7 +34,7 @@
|
|||
<label>{{t 'machine.driverRackspace.apiKey.label'}}{{field-required}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{input type="password" value=rackspaceConfig.apiKey classNames="form-control" placeholder=(t 'machine.driverRackspace.apiKey.placeholder')}}
|
||||
{{input type="password" value=model.secretValues.rackspaceConfig.apiKey classNames="form-control" placeholder=(t 'machine.driverRackspace.apiKey.placeholder')}}
|
||||
<p class="text-info">{{t 'machine.driverRackspace.accountHelp'}}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -47,7 +57,7 @@
|
|||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverRackspace.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverRackspace.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row inline-form">
|
||||
|
|
|
|||
|
|
@ -1,181 +0,0 @@
|
|||
import Ember from 'ember';
|
||||
import Driver from 'ui/mixins/driver';
|
||||
import { ajaxPromise } from 'ember-api-store/utils/ajax-promise';
|
||||
|
||||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'ubiquity',
|
||||
ubiquityConfig : Ember.computed.alias('model.ubiquityConfig'),
|
||||
ubiquityHostingApi : 'api.ubiquityhosting.com/v25/api.php',
|
||||
|
||||
allZones : null,
|
||||
allImages : null,
|
||||
allFlavors : null,
|
||||
|
||||
step : 1,
|
||||
isStep1 : Ember.computed.equal('step',1),
|
||||
isStep2 : Ember.computed.equal('step',2),
|
||||
isGteStep3 : Ember.computed.gte('step',3),
|
||||
|
||||
bootstrap: function() {
|
||||
let store = this.get('store');
|
||||
|
||||
let config = store.createRecord({
|
||||
type: 'ubiquityConfig',
|
||||
apiToken: '',
|
||||
apiUsername: '',
|
||||
clientId: '',
|
||||
flavorId: '',
|
||||
imageId: '',
|
||||
zoneId: ''
|
||||
});
|
||||
|
||||
this.set('model', store.createRecord({
|
||||
type: 'host',
|
||||
ubiquityConfig: config,
|
||||
}));
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this.set('errors', null);
|
||||
this.set('step', 1);
|
||||
},
|
||||
|
||||
actions: {
|
||||
/* Login step */
|
||||
ubiLogin: function() {
|
||||
this.set('errors', null);
|
||||
this.set('step', 2);
|
||||
this.set('ubiquityConfig.clientId', (this.get('ubiquityConfig.clientId')||'').trim());
|
||||
this.set('ubiquityConfig.apiUsername', (this.get('ubiquityConfig.apiUsername')||'').trim());
|
||||
this.set('ubiquityConfig.apiToken', (this.get('ubiquityConfig.apiToken')||'').trim());
|
||||
|
||||
Ember.RSVP.hash({
|
||||
zones: this.getZones(),
|
||||
flavors: this.getFlavors(),
|
||||
}).then((hash) => {
|
||||
this.set('allZones', hash.zones);
|
||||
this.set('allFlavors', hash.flavors);
|
||||
|
||||
if ( !this.get('ubiquityConfig.zoneId') )
|
||||
{
|
||||
this.set('ubiquityConfig.zoneId', this.get('allZones.firstObject.id'));
|
||||
}
|
||||
|
||||
if ( !this.get('ubiquityConfig.flavorId') )
|
||||
{
|
||||
this.set('ubiquityConfig.flavorId', this.get('allFlavors.firstObject.id'));
|
||||
}
|
||||
|
||||
return this.zoneChange(this.get('ubiquityConfig.zoneId')).then(() => {
|
||||
this.set('step', 3);
|
||||
});
|
||||
}).catch((err) => {
|
||||
this.set('errors', [err]);
|
||||
this.set('step', 1);
|
||||
});
|
||||
},
|
||||
|
||||
setZone(zoneId) {
|
||||
this.zoneChange(zoneId);
|
||||
},
|
||||
},
|
||||
|
||||
zoneChange: function(zoneId) {
|
||||
this.set('ubiquityConfig.zoneId', zoneId);
|
||||
return this.getImages(zoneId).then((images) => {
|
||||
this.set('allImages', images);
|
||||
let existing = this.get('ubiquityConfig.imageId');
|
||||
if ( !existing || images.filterBy('id', existing).length === 0 ) {
|
||||
this.set('ubiquityConfig.imageId', images[0].id);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getZones: function() {
|
||||
return this.apiRequest('list_zones').then((res) => {
|
||||
return (res.Zones || []).map((zone) => {
|
||||
return {
|
||||
id: zone.id,
|
||||
name: zone.name,
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getImages: function(zone_id) {
|
||||
return this.apiRequest('list_images', {zone_id: zone_id, docker_machine: 'true'}).then((res) => {
|
||||
return (res.Images || []).map((image) => {
|
||||
return {
|
||||
id: image.id,
|
||||
name: image.name,
|
||||
description: image.cat_desc,
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getFlavors: function() {
|
||||
return this.apiRequest('list_flavors').then((res) => {
|
||||
return (res.Flavors || []).map((flavor) => {
|
||||
return {
|
||||
id: flavor.id,
|
||||
name: flavor.name,
|
||||
};
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
apiRequest: function(command, params) {
|
||||
let url = this.get('app.proxyEndpoint') + '/' + this.ubiquityHostingApi + "?method=cloud." + encodeURIComponent(command);
|
||||
|
||||
let auth = this.get('ubiquityConfig.clientId') + ':' + this.get('ubiquityConfig.apiUsername') + ':' + this.get('ubiquityConfig.apiToken');
|
||||
params = params || {};
|
||||
|
||||
return ajaxPromise({
|
||||
url: url,
|
||||
method: 'POST',
|
||||
dataType: 'json',
|
||||
|
||||
headers: {
|
||||
'Accept': 'application/json',
|
||||
'X-Api-Headers-Restrict': 'Content-Length',
|
||||
'X-Api-Auth-Header': 'Basic ' + window.btoa(auth),
|
||||
},
|
||||
|
||||
beforeSend: (xhr, settings) => {
|
||||
xhr.setRequestHeader('Content-Type', 'rancher:' + settings.contentType);
|
||||
return true;
|
||||
},
|
||||
|
||||
data: params,
|
||||
params: params
|
||||
}, true).then((res) => {
|
||||
if ((res || '') === '') {
|
||||
return Ember.RSVP.reject('Authentication Failed: Please check the access credentials and that the server is in the list of authorized IP addresses in the Ubiquity console');
|
||||
} else {
|
||||
return res;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
validate: function() {
|
||||
this._super();
|
||||
let errors = this.get('errors')||[];
|
||||
let name = this.get('model.hostname')||'';
|
||||
|
||||
if (name.length < 1 || name.length > 200) {
|
||||
errors.push('"name" should be 1-200 characters long');
|
||||
}
|
||||
|
||||
if (name.match(/[^a-z0-9-]/i)) {
|
||||
errors.push('"name" can only contain letters, numbers, and hyphen');
|
||||
}
|
||||
|
||||
if (errors.get('length')) {
|
||||
this.set('errors',errors);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
});
|
||||
|
|
@ -1,119 +0,0 @@
|
|||
<section class="horizontal-form">
|
||||
<form name="login">
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mb-20">
|
||||
<span>{{t 'machine.driverUbiquity.accountSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row {{if isStep1 'inline-form'}}">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.clientId.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{#if isStep1}}
|
||||
{{input type="text" name="clientId" classNames="form-control" placeholder=(t 'machine.driverUbiquity.clientId.placeholder') value=ubiquityConfig.clientId}}
|
||||
{{else}}
|
||||
<div>{{ubiquityConfig.clientId}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row {{if isStep1 'inline-form'}}">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.apiUsername.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{#if isStep1}}
|
||||
{{input type="text" name="apiUsername" classNames="form-control" placeholder=(t 'machine.driverUbiquity.apiUsername.placeholder') value=ubiquityConfig.apiUsername}}
|
||||
{{else}}
|
||||
<div>{{ubiquityConfig.apiUsername}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="row {{if isStep1 'inline-form'}}">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.apiToken.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{#if isStep1}}
|
||||
{{input type="password" name="apiToken" classNames="form-control" placeholder=(t 'machine.driverUbiquity.apiToken.placeholder') value=ubiquityConfig.apiToken}}
|
||||
{{else}}
|
||||
<div class="text-muted text-italic">{{t 'machine.driverUbiquity.apiToken.provided'}}</div>
|
||||
{{/if}}
|
||||
{{#if isStep1}}
|
||||
<p class="text-info">{{t 'machine.driverUbiquity.accountHelp' htmlSafe=true}}</p>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{#if isStep1}}
|
||||
{{top-errors errors=errors}}
|
||||
<div class="footer-actions">
|
||||
<button {{action "ubiLogin"}} name="submit" class="btn bg-primary">{{t 'machine.driverUbiquity.loginAction'}}</button>
|
||||
<button {{action "cancel"}} class="btn bg-transparent">{{t 'generic.cancel'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</form>
|
||||
</section>
|
||||
|
||||
<section class="horizontal-form pt-0 {{unless isStep2 'hide'}}">
|
||||
<div class="text-center">
|
||||
<i class="icon icon-spinner icon-spin"></i> {{t 'machine.driverUbiquity.loadingInstance'}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="horizontal-form pt-0 {{unless isGteStep3 'hide'}}">
|
||||
<div class="container-fluid">
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverUbiquity.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverUbiquity.regionSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row inline-form">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.region.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
<select class="form-control" onchange={{action "setZone" target.value}}>
|
||||
{{#each allZones as |choice|}}
|
||||
<option value={{choice.id}} selected={{eq ubiquityConfig.zoneId choice.id}}>{{choice.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row inline-form">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.image.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<select class="form-control" onchange={{action (mut ubiquityConfig.imageId) value="target.value"}}>
|
||||
{{#each allImages as |choice|}}
|
||||
<option value={{choice.id}} selected={{eq ubiquityConfig.imageId choice.id}}>{{choice.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'machine.driverUbiquity.flavor.label'}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
<select class="form-control" onchange={{action (mut ubiquityConfig.flavorId) value="target.value"}}>
|
||||
{{#each allFlavors as |choice|}}
|
||||
<option value={{choice.id}} selected={{eq ubiquityConfig.flavorId choice.id}}>{{choice.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{partial "host/add-options"}}
|
||||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
@ -4,7 +4,7 @@ import Driver from 'ui/mixins/driver';
|
|||
export default Ember.Component.extend(Driver, {
|
||||
driverName : 'vmwarevsphere',
|
||||
model : null,
|
||||
config : Ember.computed.alias('model.vmwarevsphereConfig'),
|
||||
config : Ember.computed.alias('model.publicValues.vmwarevsphereConfig'),
|
||||
showEngineUrl : false,
|
||||
|
||||
bootstrap: function() {
|
||||
|
|
@ -17,9 +17,27 @@ export default Ember.Component.extend(Driver, {
|
|||
});
|
||||
|
||||
this.set('model', this.get('store').createRecord({
|
||||
type: 'host',
|
||||
vmwarevsphereConfig: config,
|
||||
engineInstallUrl: '',
|
||||
type: 'hostTemplate',
|
||||
driver: 'vmwarevsphere',
|
||||
publicValues: {
|
||||
vmwarevsphereConfig: config
|
||||
},
|
||||
secretValues: {
|
||||
vmwarevsphereConfig: {
|
||||
password: '',
|
||||
}
|
||||
}
|
||||
}));
|
||||
},
|
||||
|
||||
validate() {
|
||||
let errors = [];
|
||||
|
||||
if ( !this.get('model.name') ) {
|
||||
errors.push('Name is required');
|
||||
}
|
||||
|
||||
this.set('errors', errors);
|
||||
return errors.length === 0;
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -2,9 +2,21 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#if showNameScale}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/if}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverVsphere.instanceSection'}}</span>
|
||||
</div>
|
||||
<div class="row mb-20">
|
||||
{{form-name-description
|
||||
name=model.name
|
||||
description=model.description
|
||||
nameRequired=true
|
||||
namePlaceholder="hostPartial.host.addCommon.new.form.name.placeholder"
|
||||
descriptionShown=true
|
||||
descriptionExpanded=true
|
||||
}}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverVsphere.accountSection'}}</span>
|
||||
|
|
@ -37,12 +49,12 @@
|
|||
<label>{{t 'machine.driverVsphere.password.label'}}{{field-required}}</label>
|
||||
</div>
|
||||
<div class="col span-4">
|
||||
{{input type="password" value=config.password classNames="form-control"}}
|
||||
{{input type="password" value=model.secretValues.vmwarevsphereConfig.password classNames="form-control"}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverVsphere.instanceSection'}}</span>
|
||||
<span>{{t 'machine.driverVsphere.instanceOptionsSection'}}</span>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,8 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
savedHost() {},
|
||||
completed() {},
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
import Ember from 'ember';
|
||||
const { getOwner } = Ember;
|
||||
|
||||
export default Ember.Route.extend({
|
||||
access : Ember.inject.service(),
|
||||
projects : Ember.inject.service(),
|
||||
settings : Ember.inject.service(),
|
||||
host : Ember.inject.service(),
|
||||
backTo : null,
|
||||
|
||||
actions: {
|
||||
cancel() {
|
||||
this.send('goBack');
|
||||
},
|
||||
|
||||
goBack() {
|
||||
if ( this.get('backTo') === 'waiting' ) {
|
||||
this.transitionTo('authenticated.project.waiting');
|
||||
} else {
|
||||
this.transitionTo('hosts.templates');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
activate() {
|
||||
let appRoute = getOwner(this).lookup('route:application');
|
||||
this.set('previousOpts', {name: appRoute.get('previousRoute'), params: appRoute.get('previousParams')});
|
||||
},
|
||||
|
||||
// Loads all the machine drivers and selects the active ones with a corresponding schema into machineDrivers
|
||||
beforeModel(/*transition*/) {
|
||||
this._super(...arguments);
|
||||
|
||||
var hs = this.get('host');
|
||||
|
||||
return hs.loadAllDrivers().then((drivers) => {
|
||||
this.set('machineDrivers', drivers);
|
||||
});
|
||||
},
|
||||
|
||||
model(params) {
|
||||
this.set('backTo', params.backTo);
|
||||
var hs = this.get('host');
|
||||
|
||||
return hs.getModel(params).then((hash) => {
|
||||
return hash;
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<section class="header clearfix">
|
||||
<h1>
|
||||
{{#link-to "infrastructure-tab"}}{{t 'hostsPage.new.header.linkTo'}}{{/link-to}}
|
||||
{{t 'hostsPage.new.header.text'}}
|
||||
</h1>
|
||||
</section>
|
||||
{{component "machine/driver-custom"
|
||||
cancel=(route-action "cancel")
|
||||
driver='custom'
|
||||
completed=(action "completed")
|
||||
goBack=(route-action "goBack")
|
||||
}}
|
||||
<!-- {{add-host model=model driver="custom" completed=(action "completed") goBack=(route-action "goBack") savedHost=(action "savedHost") showPicker=false}} -->
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export function hostPublicValues(params/*, hash*/) {
|
||||
var [host] = params;
|
||||
var pv = host.publicValues[`${host.driver}Config`];
|
||||
return pv;
|
||||
}
|
||||
|
||||
export default Ember.Helper.helper(hostPublicValues);
|
||||
|
|
@ -1,20 +1,7 @@
|
|||
import Ember from 'ember';
|
||||
const PROVIDERS = [
|
||||
{
|
||||
id: 'amazonec2',
|
||||
class: 'amazonec2'
|
||||
},
|
||||
{
|
||||
id: 'digitalocean',
|
||||
class: 'rancherdo'
|
||||
},
|
||||
{
|
||||
id: 'packet',
|
||||
class: 'packet '
|
||||
},
|
||||
]
|
||||
import C from 'ui/utils/constants';
|
||||
export function parseHostIcon(params/*, hash*/) {
|
||||
return PROVIDERS.findBy('id', params[0]).class || 'other';
|
||||
return C.MACHINE_DRIVER_IMAGES[params[0].toUpperCase()] || 'other';
|
||||
}
|
||||
|
||||
export default Ember.Helper.helper(parseHostIcon);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
{{/tooltip-element}}
|
||||
</div>
|
||||
|
||||
{{#link-to "hosts.new" classNames="btn btn-sm bg-primary"}}{{t 'hostsPage.index.addHost'}}{{/link-to}}
|
||||
{{#link-to "hosts.templates" classNames="btn btn-sm bg-primary"}}{{t 'hostsPage.index.hostTemplate'}}{{/link-to}}
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ export default Ember.Route.extend({
|
|||
if ( this.get('backTo') === 'waiting' ) {
|
||||
this.transitionTo('authenticated.project.waiting');
|
||||
} else {
|
||||
this.transitionTo('hosts.index');
|
||||
this.transitionTo('hosts.templates');
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
</h1>
|
||||
</section>
|
||||
|
||||
{{add-host model=model driver=driver hostId=hostId completed=(action 'completed') goBack=(route-action 'goBack')}}
|
||||
{{add-host allowCustom=false model=model driver=driver hostId=hostId completed=(action 'completed') goBack=(route-action 'goBack') savedHost=(route-action 'savedHost')}}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
actions: {
|
||||
launch(model) {
|
||||
this.transitionToRoute('hosts.templates.launch', model.id);
|
||||
},
|
||||
},
|
||||
filteredContent: Ember.computed('model', function() {
|
||||
return this.get('model.content').sortBy('driver', 'name');
|
||||
}),
|
||||
});
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model(/* params */) {
|
||||
return this.get('store').findAll('hostTemplate', null, {forceReload: true}).then((templates) => {
|
||||
//@@TODO possibly redirect to add when no temps exist
|
||||
return templates;
|
||||
});
|
||||
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
<section class="header clearfix">
|
||||
{{#link-to "custom-host" classNames="ml-10 btn btn-sm bg-primary pull-right"}}{{t 'hostTemplatesPage.custom'}}{{/link-to}}
|
||||
{{#link-to "hosts.new" classNames="btn btn-sm bg-primary pull-right"}}{{t 'hostTemplatesPage.addHost'}}{{/link-to}}
|
||||
<h1>
|
||||
{{#link-to "infrastructure-tab"}}{{t 'hostsPage.new.header.linkTo'}}{{/link-to}}
|
||||
{{t 'hostTemplatesPage.title'}}
|
||||
</h1>
|
||||
</section>
|
||||
|
||||
<section class="pl-15 pr-15 clearfix">
|
||||
{{#if filteredContent}}
|
||||
{{#each filteredContent as |host|}}
|
||||
{{#catalog-box
|
||||
model=model
|
||||
active=(not (eq true 'inactive'))
|
||||
classNames='cloud-host'
|
||||
showIcon=false
|
||||
showDescription=false
|
||||
as |section|
|
||||
}}
|
||||
{{#if (eq section 'header')}}
|
||||
{{action-menu model=host class="pull-right"}}
|
||||
<div class="catalog-icon mt-10 {{parse-host-icon host.driver}}"/>
|
||||
{{else if (eq section 'body')}}
|
||||
<hr class="m-10" />
|
||||
<h2>{{host.name}}</h2>
|
||||
<div>
|
||||
<div class="details">
|
||||
{{#if (get (host-public-values host) 'region')}}
|
||||
<div>
|
||||
<label for="">{{t 'hostTemplatesPage.templateBox.labels.zone'}}: </label>
|
||||
{{get (host-public-values host) 'region'}}{{get (host-public-values host) 'zone'}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{{else if (eq section 'footer')}}
|
||||
<button role="button" class="btn bg-primary" {{action 'launch' host}}>{{t 'hostTemplatesPage.templateBox.button'}}</button>
|
||||
{{/if}}
|
||||
{{/catalog-box}}
|
||||
{{/each}}
|
||||
{{else}}
|
||||
{{empty-table resource="container" newRoute="hosts.new" newTranslationKey="hostTemplatesPage.addHost"}}
|
||||
{{/if}}
|
||||
|
||||
</section>
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
});
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
model(params/* , transistion */) {
|
||||
return this.get('store').find('hosttemplate', params.template_id).then((template) => {
|
||||
return this.get('store').find('machinedriver', null, {forceReload: true}).then((drivers) => {
|
||||
var driver = drivers.findBy('name', template.driver);
|
||||
var configId = `${template.driver}Config`;
|
||||
var config = this.get('store').createRecord(template.publicValues[configId]);
|
||||
var tmp = {
|
||||
type: 'host',
|
||||
hostTemplateId: template.id
|
||||
};
|
||||
return {
|
||||
template: template,
|
||||
config: config,
|
||||
host: this.get('store').createRecord(tmp),
|
||||
driver: driver,
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
actions: {
|
||||
cancel() {
|
||||
this.transitionTo('hosts.templates.index');
|
||||
},
|
||||
goBack() {
|
||||
if ( this.get('backTo') === 'waiting' ) {
|
||||
this.transitionTo('authenticated.project.waiting');
|
||||
} else {
|
||||
this.transitionTo('hosts');
|
||||
}
|
||||
}
|
||||
},
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{{cloud-host-add-or-edit
|
||||
host=model.host
|
||||
hostTemplate=model.template
|
||||
driver=model.driver
|
||||
cancel=(route-action 'cancel')
|
||||
goBack=(route-action 'goBack')
|
||||
}}
|
||||
|
|
@ -3,13 +3,6 @@ import Resource from 'ember-api-store/models/resource';
|
|||
var HostTemplate = Resource.extend({
|
||||
type: 'hosttemplate',
|
||||
actions: {
|
||||
deactivate: function() {
|
||||
return this.doAction('deactivate');
|
||||
},
|
||||
|
||||
activate: function() {
|
||||
return this.doAction('activate');
|
||||
},
|
||||
},
|
||||
|
||||
availableActions: function() {
|
||||
|
|
|
|||
|
|
@ -111,8 +111,13 @@ Router.map(function() {
|
|||
|
||||
this.route('new-stack', {path: '/import-compose', resetNamespace: true});
|
||||
|
||||
this.route('custom-host', {path: '/hosts/custom', resetNamespace: true});
|
||||
this.route('hosts', {path: '/hosts', resetNamespace: true}, function() {
|
||||
this.route('index', {path: '/'});
|
||||
this.route('templates', {path: '/templates'}, function() {
|
||||
this.route('index', {path: '/'});
|
||||
this.route('launch', {path: '/launch/:template_id'});
|
||||
});
|
||||
|
||||
this.route('container-cloud', {path: '/container-cloud'}, function() {
|
||||
this.route('index', {path: '/'});
|
||||
|
|
@ -195,9 +200,6 @@ Router.map(function() {
|
|||
this.route('edit-receiver', {path: '/receiver/:receiver_id'});
|
||||
});
|
||||
|
||||
this.route('host-template', {path: '/host-template'}, function(){
|
||||
this.route('keys', {path: '/keys'});
|
||||
});
|
||||
// End: Authenticated
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ $lines-to-show: 4;
|
|||
}
|
||||
&.cloud-host {
|
||||
@extend .machine;
|
||||
height: 300px;
|
||||
height: 250px;
|
||||
.help-text {
|
||||
color: $accent-two;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,11 +3,8 @@
|
|||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col span-2 col-inline">
|
||||
<label>{{t 'hostPartial.host.addOptions.labels'}}</label>
|
||||
</div>
|
||||
<div class="col span-10">
|
||||
{{form-user-labels initialLabels=model.labels setLabels=(action 'setLabels')}}
|
||||
<div class="col span-12">
|
||||
{{form-user-labels initialLabels=model.labels setLabels=(action 'setLabels') expandAll=null}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.region}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.instanceType}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.size'}}</label>
|
||||
{{hostOptions.systemDiskSize}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.instanceType}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.region}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.storage'}}</label>
|
||||
{{hostOptions.rootSize}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.location}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.env'}}</label>
|
||||
{{hostOptions.environment}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.size'}}</label>
|
||||
{{hostOptions.size}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.size}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.region}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.availabilityZone}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.instanceProfile}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.size'}}</label>
|
||||
{{hostOptions.diskSize}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
<div class="hosts-cloud-add">
|
||||
<section class="header clearfix">
|
||||
<div class="row">
|
||||
<div class="mb-0">
|
||||
<h1>
|
||||
{{t 'hostsPage.cloudHostsPage.addPage.header'}}
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="mt-20">
|
||||
<form>
|
||||
<section class="horizontal-form">
|
||||
<div class="row addtl-info">
|
||||
<div class="col span-4">
|
||||
<div class="nav-boxes driver">
|
||||
{{#if driver.hasUi}}
|
||||
<div class="nav-box-item driver machine-driver active {{parse-host-icon hostTemplate.driver}}"></div>
|
||||
{{else}}
|
||||
<div class="nav-box-item driver machine-driver active other"></div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
<div class="col span-8">
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.template'}}</label>
|
||||
{{hostTemplate.name}}
|
||||
</div>
|
||||
<hr/>
|
||||
{{#if driver.hasUi}}
|
||||
{{partial (concat 'host/host-templates/' hostTemplate.driver)}}
|
||||
{{else}}
|
||||
{{partial 'host/host-templates/other'}}
|
||||
{{/if}}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="container-fluid">
|
||||
{{partial "host/add-common"}}
|
||||
<hr />
|
||||
<div class="row">
|
||||
<div class="col span-12">
|
||||
{{#advanced-section}}
|
||||
{{form-user-labels initialLabels=clonedModel.labels setLabels=(action 'setLabels') expandAll=null}}
|
||||
{{/advanced-section}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel" createLabel='hostsPage.cloudHostsPage.addPage.launch'}}
|
||||
</section>
|
||||
|
||||
</form>
|
||||
</section>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.driver'}}</label>
|
||||
{{hostTemplate.driver}}
|
||||
</div>
|
||||
<hr/>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.facilityCode}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.plan}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.os'}}</label>
|
||||
{{hostOptions.os}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.region}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.flavorId}}
|
||||
</div>
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.zone'}}</label>
|
||||
{{hostOptions.datacenter}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.instance'}}</label>
|
||||
{{hostOptions.vcenter}}
|
||||
</div>
|
||||
<hr/>
|
||||
<div>
|
||||
<label for="">{{t 'hostsPage.cloudHostsPage.addPage.size'}}</label>
|
||||
{{hostOptions.diskSize}}
|
||||
</div>
|
||||
|
|
@ -211,13 +211,6 @@ const navTree = [
|
|||
route: 'authenticated.project.hooks',
|
||||
ctx: [getProjectId],
|
||||
},
|
||||
{
|
||||
id: 'infra-template-keys',
|
||||
localizedLabel: 'nav.infra.templateKeys',
|
||||
icon: 'icon icon-key',
|
||||
route: 'authenticated.project.host-template.keys',
|
||||
ctx: [getProjectId],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
|
|
|
|||
|
|
@ -697,6 +697,11 @@ hostsPage:
|
|||
storage: 'Storage:'
|
||||
transfer: 'Transfer:'
|
||||
zone: 'Zone:'
|
||||
env: 'Environment:'
|
||||
size: 'Size:'
|
||||
os: 'OS:'
|
||||
driver: 'Driver:'
|
||||
template: 'Template Name:'
|
||||
tabs:
|
||||
fav: Favorites
|
||||
browse: Browse
|
||||
|
|
@ -735,6 +740,7 @@ hostsPage:
|
|||
index:
|
||||
header: Hosts
|
||||
addHost: Add Host
|
||||
hostTemplate: Host Templates
|
||||
tooltip:
|
||||
listView: List
|
||||
iconView: State Icons
|
||||
|
|
@ -842,6 +848,14 @@ hostsPage:
|
|||
noData: This host does not have any volumes
|
||||
|
||||
hostTemplatesPage:
|
||||
title: Templates
|
||||
addHost: Add Host Template
|
||||
custom: Add Custom Host
|
||||
templateBox:
|
||||
button: Launch
|
||||
labels:
|
||||
region: Region
|
||||
zone: Zone
|
||||
keys:
|
||||
header: Host Template Keys
|
||||
buttonText: New Key
|
||||
|
|
@ -2767,6 +2781,7 @@ machine:
|
|||
securityGroupSection: Security Group
|
||||
securityGroup:
|
||||
label: Security Group
|
||||
choose: Choose an existing group
|
||||
defaultExisting: "Standard: Use the existing <code>{groupName}</code> group"
|
||||
defaultCreate: "Standard: Automatically create a <code>{groupName}</code> group"
|
||||
custom: "Custom: Choose an existing group"
|
||||
|
|
@ -2814,6 +2829,7 @@ machine:
|
|||
label: Subscription Cert
|
||||
placeholder: Your Azure subscription certificate
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
image:
|
||||
label: Image
|
||||
placeholder: 'canonical:UbuntuServer:16.04.0-LTS:latest'
|
||||
|
|
@ -2908,6 +2924,7 @@ machine:
|
|||
A Personal Access Token from the DigitalOcean
|
||||
<a href="https://cloud.digitalocean.com/settings/applications" target="_blank">Apps & API</a> screen
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
image:
|
||||
label: Image
|
||||
sshUser:
|
||||
|
|
@ -2957,6 +2974,7 @@ machine:
|
|||
selectSecurityGroupAction: "Next: Set Instance options"
|
||||
loadingInstance: Fetching available Instance settings...
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
instanceProfile:
|
||||
label: Instance Profile
|
||||
diskSize:
|
||||
|
|
@ -2971,6 +2989,8 @@ machine:
|
|||
driver:
|
||||
label: Driver
|
||||
optionsSection: "{driverName} Options"
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
|
||||
driverPacket:
|
||||
accountSection: Account Access
|
||||
|
|
@ -2982,6 +3002,7 @@ machine:
|
|||
placeholder: Your Packet API key
|
||||
apiKeyHelp: From the Packet <a href="https://app.packet.net/portal#/api-keys" target="_blank">API Keys</a> screen
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
image:
|
||||
label: Image
|
||||
size:
|
||||
|
|
@ -3003,6 +3024,7 @@ machine:
|
|||
region:
|
||||
label: Region
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
flavor:
|
||||
label: Flavor
|
||||
|
||||
|
|
@ -3022,6 +3044,7 @@ machine:
|
|||
loginAction: "Next: Authenticate & Create a New Cloud Instance"
|
||||
loadingInstance: Loading cloud instance creation details...
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
regionSection: Region
|
||||
region:
|
||||
label: Region
|
||||
|
|
@ -3042,6 +3065,7 @@ machine:
|
|||
password:
|
||||
label: Password
|
||||
instanceSection: Instance
|
||||
instanceOptionsSection: Instance Options
|
||||
cpuCount:
|
||||
label: CPUs
|
||||
memorySize:
|
||||
|
|
@ -3078,6 +3102,7 @@ machine:
|
|||
label: Api Endpoint
|
||||
placeholder: Private Aliyun Api Server Endpoint
|
||||
instanceSection: Instance Section
|
||||
instanceOptionsSection: Instance Options Section
|
||||
instanceDescription:
|
||||
label: Instance Description
|
||||
placeholder: Instance Description
|
||||
|
|
|
|||
Loading…
Reference in New Issue