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}}
|
{{else}}
|
||||||
<section>
|
<section>
|
||||||
<div>
|
<div>
|
||||||
{{host-settings saved="savedHost"}}
|
{{host-settings saved=(action savedHost)}}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
|
||||||
|
|
@ -3,55 +3,23 @@ import Driver from 'ui/mixins/driver';
|
||||||
|
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
errors: null,
|
errors: null,
|
||||||
model: null,
|
host: null,
|
||||||
config: null,
|
clonedModel: null,
|
||||||
hostTemplates: null,
|
primaryResource: Ember.computed.alias('clonedModel'),
|
||||||
selectedHostTemplate: null,
|
hostOptions: null,
|
||||||
|
|
||||||
|
didReceiveAttrs() {
|
||||||
|
this._super(...arguments);
|
||||||
|
|
||||||
|
this.setProperties({
|
||||||
|
hostOptions: this.get(`hostTemplate.publicValues.${this.get('hostTemplate.driver')}Config`),
|
||||||
|
clonedModel: this.get('host').clone(),
|
||||||
|
});
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
actions: {
|
actions: {
|
||||||
saveTemp() {
|
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">
|
{{partial 'host/host-templates/host-launch'}}
|
||||||
<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>
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ export default Ember.Component.extend(ManageLabels, {
|
||||||
|
|
||||||
this.$('INPUT.key').last()[0].focus();
|
this.$('INPUT.key').last()[0].focus();
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
didReceiveAttrs() {
|
didReceiveAttrs() {
|
||||||
|
|
@ -31,6 +31,7 @@ export default Ember.Component.extend(ManageLabels, {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ let isOptimized=[
|
||||||
|
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
driverName: 'aliyunecs',
|
driverName: 'aliyunecs',
|
||||||
aliyunecsConfig : Ember.computed.alias('model.aliyunecsConfig'),
|
aliyunecsConfig: Ember.computed.alias('model.publicValues.aliyunecsConfig'),
|
||||||
isOptimized: isOptimized,
|
isOptimized: isOptimized,
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -22,11 +22,28 @@ export default Ember.Component.extend(Driver, {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
aliyunecsConfig: config,
|
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">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
|
|
||||||
{{#if showNameScale}}
|
<div class="over-hr mt-20 mb-20">
|
||||||
{{partial "host/add-common"}}
|
<span>{{t 'machine.driverAliyunecs.instanceSection'}}</span>
|
||||||
{{/if}}
|
</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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverAliyunecs.accountSection'}}</span>
|
<span>{{t 'machine.driverAliyunecs.accountSection'}}</span>
|
||||||
|
|
@ -23,7 +33,7 @@
|
||||||
<label>{{t 'machine.driverAliyunecs.accessKeySecret.label'}}</label>
|
<label>{{t 'machine.driverAliyunecs.accessKeySecret.label'}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-4">
|
<div class="col span-4">
|
||||||
{{input type="text" class="form-control" value=aliyunecsConfig.accessKeySecret placeholder=(t 'machine.driverAliyunecs.accessKeySecret.placeholder')}}
|
{{input type="password" class="form-control" value=model.secretValues.aliyunecsConfig.accessKeySecret placeholder=(t 'machine.driverAliyunecs.accessKeySecret.placeholder')}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
@ -36,7 +46,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverAliyunecs.instanceSection'}}</span>
|
<span>{{t 'machine.driverAliyunecs.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-2 col-inline">
|
<div class="col span-2 col-inline">
|
||||||
|
|
|
||||||
|
|
@ -106,7 +106,7 @@ export default Ember.Component.extend(Driver, {
|
||||||
prefs : Ember.inject.service(),
|
prefs : Ember.inject.service(),
|
||||||
driverName : 'amazonec2',
|
driverName : 'amazonec2',
|
||||||
model : null,
|
model : null,
|
||||||
amazonec2Config : Ember.computed.alias('model.amazonec2Config'),
|
amazonec2Config : Ember.computed.alias('model.publicValues.amazonec2Config'),
|
||||||
|
|
||||||
clients : null,
|
clients : null,
|
||||||
allSubnets : null,
|
allSubnets : null,
|
||||||
|
|
@ -139,19 +139,37 @@ export default Ember.Component.extend(Driver, {
|
||||||
type : 'amazonec2Config',
|
type : 'amazonec2Config',
|
||||||
region : 'us-west-2',
|
region : 'us-west-2',
|
||||||
instanceType : 't2.micro',
|
instanceType : 't2.micro',
|
||||||
securityGroup : 'rancher-machine',
|
securityGroup : ['rancher-machine',],
|
||||||
zone : 'a',
|
zone : 'a',
|
||||||
rootSize : 16,
|
rootSize : '16',
|
||||||
accessKey : pref.accessKey||'',
|
accessKey : pref.accessKey||'',
|
||||||
secretKey : pref.secretKey||'',
|
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type : 'host',
|
type: 'hostTemplate',
|
||||||
amazonec2Config : config,
|
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() {
|
init: function() {
|
||||||
this._super(...arguments);
|
this._super(...arguments);
|
||||||
|
|
||||||
|
|
@ -191,15 +209,6 @@ export default Ember.Component.extend(Driver, {
|
||||||
});
|
});
|
||||||
}.observes('context.step'),
|
}.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: {
|
actions: {
|
||||||
awsLogin: function() {
|
awsLogin: function() {
|
||||||
let self = this;
|
let self = this;
|
||||||
|
|
@ -207,13 +216,13 @@ export default Ember.Component.extend(Driver, {
|
||||||
this.set('step',2);
|
this.set('step',2);
|
||||||
|
|
||||||
this.set('amazonec2Config.accessKey', (this.get('amazonec2Config.accessKey')||'').trim());
|
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 subnets = [];
|
||||||
let rName = this.get('amazonec2Config.region');
|
let rName = this.get('amazonec2Config.region');
|
||||||
let ec2 = new AWS.EC2({
|
let ec2 = new AWS.EC2({
|
||||||
accessKeyId : this.get('amazonec2Config.accessKey'),
|
accessKeyId : this.get('amazonec2Config.accessKey'),
|
||||||
secretAccessKey : this.get('amazonec2Config.secretKey'),
|
secretAccessKey : this.get('model.secretValues.amazonec2Config.secretKey'),
|
||||||
region : rName,
|
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}', {
|
selectedZone: Ember.computed('amazonec2Config.{region,zone}', {
|
||||||
get: function() {
|
get: function() {
|
||||||
let config = this.get('amazonec2Config');
|
let config = this.get('amazonec2Config');
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,20 @@
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
<form>
|
<form>
|
||||||
<div class="container-fluid">
|
<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">
|
<div class="over-hr mb-20">
|
||||||
<span>{{t 'machine.driverAmazon.accessSection'}}</span>
|
<span>{{t 'machine.driverAmazon.accessSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -39,7 +53,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-8">
|
<div class="col span-8">
|
||||||
{{#if isStep1}}
|
{{#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}}
|
{{else}}
|
||||||
<div class="text-muted text-italic">{{t 'machine.driverAmazon.secretKey.provided'}}</div>
|
<div class="text-muted text-italic">{{t 'machine.driverAmazon.secretKey.provided'}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
@ -151,25 +165,14 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-8">
|
<div class="col span-8">
|
||||||
{{#if isStep5}}
|
{{#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))}}
|
{{#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>
|
<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}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="radio">
|
<div class="radio pt-10">
|
||||||
<label>
|
<label>
|
||||||
{{radio-button selection=whichSecurityGroup value="custom"}}
|
{{t 'machine.driverAmazon.securityGroup.choose'}}
|
||||||
{{t 'machine.driverAmazon.securityGroup.custom'}}
|
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -226,14 +229,6 @@
|
||||||
|
|
||||||
<section class="horizontal-form {{unless isGteStep7 'hide'}}" style="padding-top: 0;">
|
<section class="horizontal-form {{unless isGteStep7 'hide'}}" style="padding-top: 0;">
|
||||||
<div class="container-fluid">
|
<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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverAmazon.instanceOptionsSection'}}</span>
|
<span>{{t 'machine.driverAmazon.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ import { regions, sizes, storageTypes, environments } from 'ui/utils/azure-choic
|
||||||
import Driver from 'ui/mixins/driver';
|
import Driver from 'ui/mixins/driver';
|
||||||
|
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
azureConfig : Ember.computed.alias('model.azureConfig'),
|
azureConfig : Ember.computed.alias('model.publicValues.azureConfig'),
|
||||||
environments : environments.sortBy('value'),
|
environments : environments.sortBy('value'),
|
||||||
sizeChoices : sizes.sortBy('value'),
|
sizeChoices : sizes.sortBy('value'),
|
||||||
driverName : 'azure',
|
driverName : 'azure',
|
||||||
|
|
@ -31,13 +31,20 @@ export default Ember.Component.extend(Driver, {
|
||||||
type : 'azureConfig',
|
type : 'azureConfig',
|
||||||
subscriptionId : '',
|
subscriptionId : '',
|
||||||
clientId : '',
|
clientId : '',
|
||||||
clientSecret : '',
|
|
||||||
openPort : ['500/udp','4500/udp'],
|
openPort : ['500/udp','4500/udp'],
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
azureConfig: config,
|
driver: 'azure',
|
||||||
|
publicValues: {
|
||||||
|
azureConfig: config
|
||||||
|
},
|
||||||
|
secretValues: {
|
||||||
|
azureConfig: {
|
||||||
|
clientSecret : '',
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
this.set('editing', false);
|
this.set('editing', false);
|
||||||
|
|
@ -125,11 +132,10 @@ export default Ember.Component.extend(Driver, {
|
||||||
}),
|
}),
|
||||||
|
|
||||||
validate: function() {
|
validate: function() {
|
||||||
this._super();
|
let errors = [];
|
||||||
let errors = this.get('errors')||[];
|
|
||||||
|
|
||||||
this.set('prefix',(this.get('prefix')||'').toLowerCase());
|
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 ) {
|
if ( name.length < 4 || name.length > 62 ) {
|
||||||
errors.push('Name must be between 4 and 62 characters long');
|
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');
|
errors.push('Client ID is requried');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.get('azureConfig.clientSecret') ) {
|
if (!this.get('model.secretValues.azureConfig.clientSecret') ) {
|
||||||
errors.push('Client Secret is requried');
|
errors.push('Client Secret is requried');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,18 @@
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if showNameScale}}
|
<div class="over-hr mt-20 mb-20">
|
||||||
{{partial "host/add-common"}}
|
<span>{{t 'machine.driverAzure.instanceSection'}}</span>
|
||||||
{{/if}}
|
</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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverAzure.placementSection'}}</span>
|
<span>{{t 'machine.driverAzure.placementSection'}}</span>
|
||||||
|
|
@ -61,7 +71,7 @@
|
||||||
|
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label class="pb-5">{{t 'machine.driverAzure.clientSecret.label'}}{{field-required}}</label>
|
<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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverAzure.instanceSection'}}</span>
|
<span>{{t 'machine.driverAzure.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@
|
||||||
<li>
|
<li>
|
||||||
{{t 'machine.driverCustom.step3'}}
|
{{t 'machine.driverCustom.step3'}}
|
||||||
<div class="mt-10">
|
<div class="mt-10">
|
||||||
{{form-user-labels setLabels=(action 'setLabels')}}
|
{{form-user-labels setLabels=(action 'setLabels') expandAll=null}}
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ export default Ember.Component.extend(Driver, {
|
||||||
driverName: 'digitalocean',
|
driverName: 'digitalocean',
|
||||||
regionChoices: null,
|
regionChoices: null,
|
||||||
model: null,
|
model: null,
|
||||||
digitaloceanConfig: Ember.computed.alias('model.digitaloceanConfig'),
|
digitaloceanConfig: Ember.computed.alias('model.publicValues.digitaloceanConfig'),
|
||||||
step1: true,
|
step1: true,
|
||||||
sizeChoices: null,
|
sizeChoices: null,
|
||||||
imageChoices: null,
|
imageChoices: null,
|
||||||
|
|
@ -102,24 +102,31 @@ export default Ember.Component.extend(Driver, {
|
||||||
bootstrap: function() {
|
bootstrap: function() {
|
||||||
let config = this.get('store').createRecord({
|
let config = this.get('store').createRecord({
|
||||||
type : 'digitaloceanConfig',
|
type : 'digitaloceanConfig',
|
||||||
accessToken : '',
|
|
||||||
size : '1gb',
|
size : '1gb',
|
||||||
region : 'nyc3',
|
region : 'nyc3',
|
||||||
image : 'ubuntu-16-04-x64'
|
image : 'ubuntu-16-04-x64'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
digitaloceanConfig: config,
|
driver: 'digitalocean',
|
||||||
|
publicValues: {
|
||||||
|
digitaloceanConfig: config
|
||||||
|
},
|
||||||
|
secretValues: {
|
||||||
|
digitaloceanConfig: {
|
||||||
|
accessToken : '',
|
||||||
|
}
|
||||||
|
}
|
||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
validate: function() {
|
validate: function() {
|
||||||
this._super();
|
// this._super();
|
||||||
let errors = this.get('errors')||[];
|
let errors = this.get('errors')||[];
|
||||||
let name = this.get('model.hostname')||'';
|
let name = this.get('model.name')||'';
|
||||||
let accessToken = this.get('digitaloceanConfig.accessToken')||'';
|
let accessToken = this.get('model.secretValues.digitaloceanConfig.accessToken')||'';
|
||||||
|
|
||||||
if ( name.length > 200 ) {
|
if ( name.length > 200 ) {
|
||||||
errors.push('"name" should be 1-200 characters long');
|
errors.push('"name" should be 1-200 characters long');
|
||||||
|
|
@ -157,7 +164,7 @@ export default Ember.Component.extend(Driver, {
|
||||||
return fetch(url, {
|
return fetch(url, {
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'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) => {
|
}).then((res) => {
|
||||||
let body = res.body;
|
let body = res.body;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,21 @@
|
||||||
<section class="horizontal-form">
|
<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}}
|
{{#if step1}}
|
||||||
<form>
|
<form>
|
||||||
|
|
||||||
<div class="over-hr mb-20">
|
<div class="over-hr mb-20">
|
||||||
<span>{{t 'machine.driverDigitalocean.accountSection'}}</span>
|
<span>{{t 'machine.driverDigitalocean.accountSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -10,7 +25,7 @@
|
||||||
<label>{{t 'machine.driverDigitalocean.accessToken.label'}}</label>
|
<label>{{t 'machine.driverDigitalocean.accessToken.label'}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-10">
|
<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>
|
<p class="text-info">{{t 'machine.driverDigitalocean.accessToken.help' htmlSafe=true}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -20,17 +35,13 @@
|
||||||
{{#if gettingData}}
|
{{#if gettingData}}
|
||||||
<button class="btn bg-primary btn-disabled"><i class="icon icon-spinner icon-spin"></i> {{t 'generic.loading'}}</button>
|
<button class="btn bg-primary btn-disabled"><i class="icon icon-spinner icon-spin"></i> {{t 'generic.loading'}}</button>
|
||||||
{{else}}
|
{{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}}
|
{{/if}}
|
||||||
<button {{action "cancel"}} class="btn bg-transparent">{{t 'generic.cancel'}}</button>
|
<button {{action "cancel"}} class="btn bg-transparent">{{t 'generic.cancel'}}</button>
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if showNameScale}}
|
|
||||||
{{partial "host/add-common"}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverDigitalocean.regionSection'}}</span>
|
<span>{{t 'machine.driverDigitalocean.regionSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -49,7 +60,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverDigitalocean.instanceSection'}}</span>
|
<span>{{t 'machine.driverDigitalocean.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row inline-form">
|
<div class="row inline-form">
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ let RANCHER_INGRESS_RULES = [
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
driverName : 'exoscale',
|
driverName : 'exoscale',
|
||||||
model : null,
|
model : null,
|
||||||
exoscaleConfig : Ember.computed.alias('model.exoscaleConfig'),
|
exoscaleConfig : Ember.computed.alias('model.publicValues.exoscaleConfig'),
|
||||||
|
|
||||||
allDiskSizes : null,
|
allDiskSizes : null,
|
||||||
allInstanceProfiles : null,
|
allInstanceProfiles : null,
|
||||||
|
|
@ -68,19 +68,38 @@ export default Ember.Component.extend(Driver, {
|
||||||
bootstrap: function() {
|
bootstrap: function() {
|
||||||
let config = this.get('store').createRecord({
|
let config = this.get('store').createRecord({
|
||||||
type: 'exoscaleConfig',
|
type: 'exoscaleConfig',
|
||||||
apiKey: '',
|
exoscaleApiKey: '',
|
||||||
apiSecretKey: '',
|
|
||||||
diskSize: 50,
|
diskSize: 50,
|
||||||
instanceProfile: 'small',
|
instanceProfile: 'small',
|
||||||
securityGroup: 'rancher-machine'
|
securityGroup: 'rancher-machine'
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
|
driver: 'exoscale',
|
||||||
|
publicValues: {
|
||||||
exoscaleConfig: config
|
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() {
|
afterInit: function() {
|
||||||
this._super();
|
this._super();
|
||||||
|
|
||||||
|
|
@ -109,8 +128,8 @@ export default Ember.Component.extend(Driver, {
|
||||||
this.set('errors', null);
|
this.set('errors', null);
|
||||||
this.set('step', 2);
|
this.set('step', 2);
|
||||||
|
|
||||||
this.set('exoscaleConfig.apiKey', (this.get('exoscaleConfig.apiKey')||'').trim());
|
this.set('exoscaleConfig.exoscaleApiKey', (this.get('exoscaleConfig.exoscaleApiKey')||'').trim());
|
||||||
this.set('exoscaleConfig.apiSecretKey', (this.get('exoscaleConfig.apiSecretKey')||'').trim());
|
this.set('model.secretValues.exoscaleConfig.exoscaleApiSecretKey', (this.get('model.secretValues.exoscaleConfig.exoscaleApiSecretKey')||'').trim());
|
||||||
|
|
||||||
this.apiRequest('listSecurityGroups').then((res) => {
|
this.apiRequest('listSecurityGroups').then((res) => {
|
||||||
let groups = [];
|
let groups = [];
|
||||||
|
|
@ -271,7 +290,7 @@ export default Ember.Component.extend(Driver, {
|
||||||
let url = this.get('app.proxyEndpoint') + '/' + this.exoscaleApi;
|
let url = this.get('app.proxyEndpoint') + '/' + this.exoscaleApi;
|
||||||
params = params || {};
|
params = params || {};
|
||||||
params.command = command;
|
params.command = command;
|
||||||
params.apiKey = this.get('exoscaleConfig.apiKey');
|
params.apiKey = this.get('exoscaleConfig.exoscaleApiKey');
|
||||||
params.response = 'json';
|
params.response = 'json';
|
||||||
|
|
||||||
return ajaxPromise({url: url,
|
return ajaxPromise({url: url,
|
||||||
|
|
@ -293,7 +312,7 @@ export default Ember.Component.extend(Driver, {
|
||||||
.sort()
|
.sort()
|
||||||
.join('&');
|
.join('&');
|
||||||
settings.data += '&signature=' + encodeURIComponent(AWS.util.crypto.hmac(
|
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;
|
return true;
|
||||||
},
|
},
|
||||||
data: params}, true);
|
data: params}, true);
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,21 @@
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
<form>
|
<form>
|
||||||
<div class="container-fluid">
|
<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">
|
<div class="over-hr mb-20">
|
||||||
<span>{{t 'machine.driverExoscale.accountSection'}}</span>
|
<span>{{t 'machine.driverExoscale.accountSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -11,9 +26,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-10">
|
<div class="col span-10">
|
||||||
{{#if isStep1}}
|
{{#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}}
|
{{else}}
|
||||||
<div>{{exoscaleConfig.apiKey}}</div>
|
<div>{{exoscaleConfig.exoscaleApiKey}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -23,7 +38,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-10">
|
<div class="col span-10">
|
||||||
{{#if isStep1}}
|
{{#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}}
|
{{else}}
|
||||||
<div class="text-muted text-italic">{{t 'machine.driverExoscale.secretKey.provided'}}</div>
|
<div class="text-muted text-italic">{{t 'machine.driverExoscale.secretKey.provided'}}</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
@ -128,13 +143,9 @@
|
||||||
<section class="horizontal-form pt-0 {{unless isGteStep6 'hide'}}">
|
<section class="horizontal-form pt-0 {{unless isGteStep6 'hide'}}">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverExoscale.instanceSection'}}</span>
|
<span>{{t 'machine.driverExoscale.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{#if showNameScale}}
|
|
||||||
{{partial "host/add-common"}}
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<div class="row inline-form">
|
<div class="row inline-form">
|
||||||
<div class="col span-2 col-inline">
|
<div class="col span-2 col-inline">
|
||||||
<label>{{t 'machine.driverExoscale.instanceProfile.label'}}</label>
|
<label>{{t 'machine.driverExoscale.instanceProfile.label'}}</label>
|
||||||
|
|
|
||||||
|
|
@ -12,16 +12,10 @@ export default Ember.Component.extend(Driver, {
|
||||||
schemas : null,
|
schemas : null,
|
||||||
driverOpts : null,
|
driverOpts : null,
|
||||||
|
|
||||||
init() {
|
|
||||||
this._super(...arguments);
|
|
||||||
|
|
||||||
this._super();
|
|
||||||
this.driverChanged();
|
|
||||||
},
|
|
||||||
|
|
||||||
bootstrap() {
|
bootstrap() {
|
||||||
let model = this.get('store').createRecord({
|
let model = this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
|
isOfTypeOther: true,
|
||||||
});
|
});
|
||||||
|
|
||||||
this.setProperties({
|
this.setProperties({
|
||||||
|
|
@ -29,6 +23,16 @@ export default Ember.Component.extend(Driver, {
|
||||||
model: model
|
model: model
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
validate() {
|
||||||
|
let errors = [];
|
||||||
|
|
||||||
|
if ( !this.get('model.name') ) {
|
||||||
|
errors.push('Name is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
this.set('errors', errors);
|
||||||
|
return errors.length === 0;
|
||||||
|
},
|
||||||
|
|
||||||
willDestroyElement() {
|
willDestroyElement() {
|
||||||
this.setProperties({
|
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');
|
let driver = this.get('otherDriver');
|
||||||
|
|
||||||
if ( driver ) {
|
if ( driver ) {
|
||||||
return Object.keys(this.get('userStore').getById('schema', driver.toLowerCase()).get('resourceFields'));
|
return Object.keys(this.get('userStore').getById('schema', driver.toLowerCase()).get('resourceFields'));
|
||||||
}
|
}
|
||||||
}.property('otherDriver', 'model'),
|
}),
|
||||||
|
|
||||||
driverChanged: function() {
|
getSecrets(fields) {
|
||||||
let driver = this.get('otherDriver');
|
let keys = Object.keys(fields);
|
||||||
let host = this.get('model');
|
let out = [];
|
||||||
|
keys.forEach((key) => {
|
||||||
|
if (key.toLowerCase().indexOf('secret') > -1 || key.toLowerCase().indexOf('password') > -1){
|
||||||
|
out.push(key);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
return out;
|
||||||
|
},
|
||||||
|
|
||||||
if ( driver && host) {
|
driverChanged: Ember.on('init', Ember.observer('otherDriver','model', function() {
|
||||||
if ( !host.get(driver) ) {
|
if (this.get('otherDriver')) {
|
||||||
host.set(driver, this.get('store').createRecord({ type: driver }));
|
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] = '';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
hostTemplate.setProperties({
|
||||||
this.set('otherDriver', this.get('otherChoices.firstObject.value'));
|
driver: driver,
|
||||||
|
publicValues: {
|
||||||
|
[this.get('otherDriver')]: config
|
||||||
|
},
|
||||||
|
secretValues: {
|
||||||
|
[this.get('otherDriver')]: secretConfig
|
||||||
|
},
|
||||||
|
});
|
||||||
|
this.set('driverOpts', hostTemplate.get(`publicValues.${this.get('otherDriver')}`));
|
||||||
}
|
}
|
||||||
}.observes('otherDriver','model'),
|
})),
|
||||||
|
|
||||||
otherChoices: function() {
|
otherChoices: Ember.computed('availableDrivers.@each.{hasUi,name}', function() {
|
||||||
let out = [];
|
let out = [];
|
||||||
this.get('availableDrivers').filterBy('hasUi',false).forEach((driver) => {
|
this.get('availableDrivers').filterBy('hasUi',false).forEach((driver) => {
|
||||||
out.push({label: driver.name, value: driver.name+'Config'});
|
out.push({label: driver.name, value: driver.name+'Config'});
|
||||||
});
|
});
|
||||||
|
|
||||||
return out;
|
return out.sortBy('name');
|
||||||
}.property('availableDrivers.@each.{hasUi,name}'),
|
}),
|
||||||
|
|
||||||
willSave() {
|
// willSave() {
|
||||||
// Null out all the drivers that aren't the active one, because the API only accepts one.
|
// // Null out all the drivers that aren't the active one, because the API only accepts one.
|
||||||
let activeDriver = this.get('otherDriver');
|
// debugger;
|
||||||
let host = this.get('model');
|
// let activeDriver = this.get('otherDriver');
|
||||||
this.get('otherChoices').forEach((choice) => {
|
// let host = this.get('model');
|
||||||
let cur = choice.value;
|
// this.get('otherChoices').forEach((choice) => {
|
||||||
if ( choice.value !== activeDriver ) {
|
// let cur = choice.value;
|
||||||
host.set(cur, null);
|
// if ( choice.value !== activeDriver ) {
|
||||||
}
|
// host.set(cur, null);
|
||||||
});
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
return this._super();
|
// return this._super();
|
||||||
},
|
// },
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,18 @@
|
||||||
|
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverOther.driverSection'}}</span>
|
<span>{{t 'machine.driverOther.driverSection'}}</span>
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ let planChoices = PacketPlans.filter(function(plan) {
|
||||||
|
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
driverName : 'packet',
|
driverName : 'packet',
|
||||||
packetConfig : Ember.computed.alias('model.packetConfig'),
|
packetConfig : Ember.computed.alias('model.publicValues.packetConfig'),
|
||||||
|
|
||||||
facilityChoices : PacketFacilities,
|
facilityChoices : PacketFacilities,
|
||||||
planChoices : planChoices,
|
planChoices : planChoices,
|
||||||
|
|
@ -27,7 +27,6 @@ export default Ember.Component.extend(Driver, {
|
||||||
let store = this.get('store');
|
let store = this.get('store');
|
||||||
let config = store.createRecord({
|
let config = store.createRecord({
|
||||||
type : 'packetConfig',
|
type : 'packetConfig',
|
||||||
apiKey : '',
|
|
||||||
projectId : '',
|
projectId : '',
|
||||||
os : 'ubuntu_14_04',
|
os : 'ubuntu_14_04',
|
||||||
facilityCode : 'ewr1',
|
facilityCode : 'ewr1',
|
||||||
|
|
@ -39,17 +38,29 @@ export default Ember.Component.extend(Driver, {
|
||||||
type: 'host',
|
type: 'host',
|
||||||
packetConfig: config,
|
packetConfig: config,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
this.set('model', this.get('store').createRecord({
|
||||||
|
type: 'hostTemplate',
|
||||||
|
driver: 'packet',
|
||||||
|
publicValues: {
|
||||||
|
packetConfig: config
|
||||||
|
},
|
||||||
|
secretValues: {
|
||||||
|
packetConfig: {
|
||||||
|
apiKey : '',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
validate: function() {
|
validate: function() {
|
||||||
this._super();
|
let errors = [];
|
||||||
let errors = this.get('errors')||[];
|
|
||||||
|
|
||||||
if (!this.get('packetConfig.projectId') ) {
|
if (!this.get('packetConfig.projectId') ) {
|
||||||
errors.push('Project ID is required');
|
errors.push('Project ID is required');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.get('packetConfig.apiKey') ) {
|
if (!this.get('model.secretValues.packetConfig.apiKey') ) {
|
||||||
errors.push('API Key is requried');
|
errors.push('API Key is requried');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,19 @@
|
||||||
<form>
|
<form>
|
||||||
<section class="horizontal-form">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if showNameScale}}
|
<div class="over-hr mt-20 mb-20">
|
||||||
{{partial "host/add-common"}}
|
<span>{{t 'machine.driverPacket.instanceSection'}}</span>
|
||||||
{{/if}}
|
</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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverPacket.accountSection'}}</span>
|
<span>{{t 'machine.driverPacket.accountSection'}}</span>
|
||||||
|
|
@ -16,13 +26,13 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-6">
|
<div class="col span-6">
|
||||||
<label>{{t 'machine.driverPacket.apiKey.label'}}{{field-required}}</label>
|
<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>
|
<p class="text-info">{{t 'machine.driverPacket.apiKeyHelp' htmlSafe=true}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverPacket.instanceSection'}}</span>
|
<span>{{t 'machine.driverPacket.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row inline-form">
|
<div class="row inline-form">
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ flavorChoices.sort(function(a,b) {
|
||||||
|
|
||||||
export default Ember.Component.extend(Driver, {
|
export default Ember.Component.extend(Driver, {
|
||||||
driverName : 'rackspace',
|
driverName : 'rackspace',
|
||||||
rackspaceConfig : Ember.computed.alias('model.rackspaceConfig'),
|
rackspaceConfig : Ember.computed.alias('model.publicValues.rackspaceConfig'),
|
||||||
flavorChoices : flavorChoices,
|
flavorChoices : flavorChoices,
|
||||||
regionChoices : [
|
regionChoices : [
|
||||||
{label: 'Dallas (DFW)', value: 'DFW'},
|
{label: 'Dallas (DFW)', value: 'DFW'},
|
||||||
|
|
@ -56,14 +56,33 @@ export default Ember.Component.extend(Driver, {
|
||||||
let config = store.createRecord({
|
let config = store.createRecord({
|
||||||
type: 'rackspaceConfig',
|
type: 'rackspaceConfig',
|
||||||
username: '',
|
username: '',
|
||||||
apiKey: '',
|
|
||||||
region: 'DFW',
|
region: 'DFW',
|
||||||
flavorId: 'general1-1',
|
flavorId: 'general1-1',
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
rackspaceConfig: config,
|
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">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if showNameScale}}
|
<div class="over-hr mt-20 mb-20">
|
||||||
{{partial "host/add-common"}}
|
<span>{{t 'machine.driverRackspace.instanceSection'}}</span>
|
||||||
{{/if}}
|
</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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverRackspace.accountSection'}}</span>
|
<span>{{t 'machine.driverRackspace.accountSection'}}</span>
|
||||||
|
|
@ -24,7 +34,7 @@
|
||||||
<label>{{t 'machine.driverRackspace.apiKey.label'}}{{field-required}}</label>
|
<label>{{t 'machine.driverRackspace.apiKey.label'}}{{field-required}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-10">
|
<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>
|
<p class="text-info">{{t 'machine.driverRackspace.accountHelp'}}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -47,7 +57,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverRackspace.instanceSection'}}</span>
|
<span>{{t 'machine.driverRackspace.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row inline-form">
|
<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, {
|
export default Ember.Component.extend(Driver, {
|
||||||
driverName : 'vmwarevsphere',
|
driverName : 'vmwarevsphere',
|
||||||
model : null,
|
model : null,
|
||||||
config : Ember.computed.alias('model.vmwarevsphereConfig'),
|
config : Ember.computed.alias('model.publicValues.vmwarevsphereConfig'),
|
||||||
showEngineUrl : false,
|
showEngineUrl : false,
|
||||||
|
|
||||||
bootstrap: function() {
|
bootstrap: function() {
|
||||||
|
|
@ -17,9 +17,27 @@ export default Ember.Component.extend(Driver, {
|
||||||
});
|
});
|
||||||
|
|
||||||
this.set('model', this.get('store').createRecord({
|
this.set('model', this.get('store').createRecord({
|
||||||
type: 'host',
|
type: 'hostTemplate',
|
||||||
vmwarevsphereConfig: config,
|
driver: 'vmwarevsphere',
|
||||||
engineInstallUrl: '',
|
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">
|
<section class="horizontal-form">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
{{#if showNameScale}}
|
|
||||||
{{partial "host/add-common"}}
|
<div class="over-hr mt-20 mb-20">
|
||||||
{{/if}}
|
<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">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverVsphere.accountSection'}}</span>
|
<span>{{t 'machine.driverVsphere.accountSection'}}</span>
|
||||||
|
|
@ -37,12 +49,12 @@
|
||||||
<label>{{t 'machine.driverVsphere.password.label'}}{{field-required}}</label>
|
<label>{{t 'machine.driverVsphere.password.label'}}{{field-required}}</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col span-4">
|
<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>
|
</div>
|
||||||
|
|
||||||
<div class="over-hr mt-20 mb-20">
|
<div class="over-hr mt-20 mb-20">
|
||||||
<span>{{t 'machine.driverVsphere.instanceSection'}}</span>
|
<span>{{t 'machine.driverVsphere.instanceOptionsSection'}}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<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';
|
import Ember from 'ember';
|
||||||
const PROVIDERS = [
|
import C from 'ui/utils/constants';
|
||||||
{
|
|
||||||
id: 'amazonec2',
|
|
||||||
class: 'amazonec2'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'digitalocean',
|
|
||||||
class: 'rancherdo'
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 'packet',
|
|
||||||
class: 'packet '
|
|
||||||
},
|
|
||||||
]
|
|
||||||
export function parseHostIcon(params/*, hash*/) {
|
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);
|
export default Ember.Helper.helper(parseHostIcon);
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
{{/tooltip-element}}
|
{{/tooltip-element}}
|
||||||
</div>
|
</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>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,7 @@ export default Ember.Route.extend({
|
||||||
if ( this.get('backTo') === 'waiting' ) {
|
if ( this.get('backTo') === 'waiting' ) {
|
||||||
this.transitionTo('authenticated.project.waiting');
|
this.transitionTo('authenticated.project.waiting');
|
||||||
} else {
|
} else {
|
||||||
this.transitionTo('hosts.index');
|
this.transitionTo('hosts.templates');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -5,4 +5,4 @@
|
||||||
</h1>
|
</h1>
|
||||||
</section>
|
</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({
|
var HostTemplate = Resource.extend({
|
||||||
type: 'hosttemplate',
|
type: 'hosttemplate',
|
||||||
actions: {
|
actions: {
|
||||||
deactivate: function() {
|
|
||||||
return this.doAction('deactivate');
|
|
||||||
},
|
|
||||||
|
|
||||||
activate: function() {
|
|
||||||
return this.doAction('activate');
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
|
|
||||||
availableActions: function() {
|
availableActions: function() {
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,13 @@ Router.map(function() {
|
||||||
|
|
||||||
this.route('new-stack', {path: '/import-compose', resetNamespace: true});
|
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('hosts', {path: '/hosts', resetNamespace: true}, function() {
|
||||||
this.route('index', {path: '/'});
|
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('container-cloud', {path: '/container-cloud'}, function() {
|
||||||
this.route('index', {path: '/'});
|
this.route('index', {path: '/'});
|
||||||
|
|
@ -195,9 +200,6 @@ Router.map(function() {
|
||||||
this.route('edit-receiver', {path: '/receiver/:receiver_id'});
|
this.route('edit-receiver', {path: '/receiver/:receiver_id'});
|
||||||
});
|
});
|
||||||
|
|
||||||
this.route('host-template', {path: '/host-template'}, function(){
|
|
||||||
this.route('keys', {path: '/keys'});
|
|
||||||
});
|
|
||||||
// End: Authenticated
|
// End: Authenticated
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -59,7 +59,7 @@ $lines-to-show: 4;
|
||||||
}
|
}
|
||||||
&.cloud-host {
|
&.cloud-host {
|
||||||
@extend .machine;
|
@extend .machine;
|
||||||
height: 300px;
|
height: 250px;
|
||||||
.help-text {
|
.help-text {
|
||||||
color: $accent-two;
|
color: $accent-two;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,8 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col span-2 col-inline">
|
<div class="col span-12">
|
||||||
<label>{{t 'hostPartial.host.addOptions.labels'}}</label>
|
{{form-user-labels initialLabels=model.labels setLabels=(action 'setLabels') expandAll=null}}
|
||||||
</div>
|
|
||||||
<div class="col span-10">
|
|
||||||
{{form-user-labels initialLabels=model.labels setLabels=(action 'setLabels')}}
|
|
||||||
</div>
|
</div>
|
||||||
</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',
|
route: 'authenticated.project.hooks',
|
||||||
ctx: [getProjectId],
|
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:'
|
storage: 'Storage:'
|
||||||
transfer: 'Transfer:'
|
transfer: 'Transfer:'
|
||||||
zone: 'Zone:'
|
zone: 'Zone:'
|
||||||
|
env: 'Environment:'
|
||||||
|
size: 'Size:'
|
||||||
|
os: 'OS:'
|
||||||
|
driver: 'Driver:'
|
||||||
|
template: 'Template Name:'
|
||||||
tabs:
|
tabs:
|
||||||
fav: Favorites
|
fav: Favorites
|
||||||
browse: Browse
|
browse: Browse
|
||||||
|
|
@ -735,6 +740,7 @@ hostsPage:
|
||||||
index:
|
index:
|
||||||
header: Hosts
|
header: Hosts
|
||||||
addHost: Add Host
|
addHost: Add Host
|
||||||
|
hostTemplate: Host Templates
|
||||||
tooltip:
|
tooltip:
|
||||||
listView: List
|
listView: List
|
||||||
iconView: State Icons
|
iconView: State Icons
|
||||||
|
|
@ -842,6 +848,14 @@ hostsPage:
|
||||||
noData: This host does not have any volumes
|
noData: This host does not have any volumes
|
||||||
|
|
||||||
hostTemplatesPage:
|
hostTemplatesPage:
|
||||||
|
title: Templates
|
||||||
|
addHost: Add Host Template
|
||||||
|
custom: Add Custom Host
|
||||||
|
templateBox:
|
||||||
|
button: Launch
|
||||||
|
labels:
|
||||||
|
region: Region
|
||||||
|
zone: Zone
|
||||||
keys:
|
keys:
|
||||||
header: Host Template Keys
|
header: Host Template Keys
|
||||||
buttonText: New Key
|
buttonText: New Key
|
||||||
|
|
@ -2767,6 +2781,7 @@ machine:
|
||||||
securityGroupSection: Security Group
|
securityGroupSection: Security Group
|
||||||
securityGroup:
|
securityGroup:
|
||||||
label: Security Group
|
label: Security Group
|
||||||
|
choose: Choose an existing group
|
||||||
defaultExisting: "Standard: Use the existing <code>{groupName}</code> group"
|
defaultExisting: "Standard: Use the existing <code>{groupName}</code> group"
|
||||||
defaultCreate: "Standard: Automatically create a <code>{groupName}</code> group"
|
defaultCreate: "Standard: Automatically create a <code>{groupName}</code> group"
|
||||||
custom: "Custom: Choose an existing group"
|
custom: "Custom: Choose an existing group"
|
||||||
|
|
@ -2814,6 +2829,7 @@ machine:
|
||||||
label: Subscription Cert
|
label: Subscription Cert
|
||||||
placeholder: Your Azure subscription certificate
|
placeholder: Your Azure subscription certificate
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
image:
|
image:
|
||||||
label: Image
|
label: Image
|
||||||
placeholder: 'canonical:UbuntuServer:16.04.0-LTS:latest'
|
placeholder: 'canonical:UbuntuServer:16.04.0-LTS:latest'
|
||||||
|
|
@ -2908,6 +2924,7 @@ machine:
|
||||||
A Personal Access Token from the DigitalOcean
|
A Personal Access Token from the DigitalOcean
|
||||||
<a href="https://cloud.digitalocean.com/settings/applications" target="_blank">Apps & API</a> screen
|
<a href="https://cloud.digitalocean.com/settings/applications" target="_blank">Apps & API</a> screen
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
image:
|
image:
|
||||||
label: Image
|
label: Image
|
||||||
sshUser:
|
sshUser:
|
||||||
|
|
@ -2957,6 +2974,7 @@ machine:
|
||||||
selectSecurityGroupAction: "Next: Set Instance options"
|
selectSecurityGroupAction: "Next: Set Instance options"
|
||||||
loadingInstance: Fetching available Instance settings...
|
loadingInstance: Fetching available Instance settings...
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
instanceProfile:
|
instanceProfile:
|
||||||
label: Instance Profile
|
label: Instance Profile
|
||||||
diskSize:
|
diskSize:
|
||||||
|
|
@ -2971,6 +2989,8 @@ machine:
|
||||||
driver:
|
driver:
|
||||||
label: Driver
|
label: Driver
|
||||||
optionsSection: "{driverName} Options"
|
optionsSection: "{driverName} Options"
|
||||||
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
|
|
||||||
driverPacket:
|
driverPacket:
|
||||||
accountSection: Account Access
|
accountSection: Account Access
|
||||||
|
|
@ -2982,6 +3002,7 @@ machine:
|
||||||
placeholder: Your Packet API key
|
placeholder: Your Packet API key
|
||||||
apiKeyHelp: From the Packet <a href="https://app.packet.net/portal#/api-keys" target="_blank">API Keys</a> screen
|
apiKeyHelp: From the Packet <a href="https://app.packet.net/portal#/api-keys" target="_blank">API Keys</a> screen
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
image:
|
image:
|
||||||
label: Image
|
label: Image
|
||||||
size:
|
size:
|
||||||
|
|
@ -3003,6 +3024,7 @@ machine:
|
||||||
region:
|
region:
|
||||||
label: Region
|
label: Region
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
flavor:
|
flavor:
|
||||||
label: Flavor
|
label: Flavor
|
||||||
|
|
||||||
|
|
@ -3022,6 +3044,7 @@ machine:
|
||||||
loginAction: "Next: Authenticate & Create a New Cloud Instance"
|
loginAction: "Next: Authenticate & Create a New Cloud Instance"
|
||||||
loadingInstance: Loading cloud instance creation details...
|
loadingInstance: Loading cloud instance creation details...
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
regionSection: Region
|
regionSection: Region
|
||||||
region:
|
region:
|
||||||
label: Region
|
label: Region
|
||||||
|
|
@ -3042,6 +3065,7 @@ machine:
|
||||||
password:
|
password:
|
||||||
label: Password
|
label: Password
|
||||||
instanceSection: Instance
|
instanceSection: Instance
|
||||||
|
instanceOptionsSection: Instance Options
|
||||||
cpuCount:
|
cpuCount:
|
||||||
label: CPUs
|
label: CPUs
|
||||||
memorySize:
|
memorySize:
|
||||||
|
|
@ -3078,6 +3102,7 @@ machine:
|
||||||
label: Api Endpoint
|
label: Api Endpoint
|
||||||
placeholder: Private Aliyun Api Server Endpoint
|
placeholder: Private Aliyun Api Server Endpoint
|
||||||
instanceSection: Instance Section
|
instanceSection: Instance Section
|
||||||
|
instanceOptionsSection: Instance Options Section
|
||||||
instanceDescription:
|
instanceDescription:
|
||||||
label: Instance Description
|
label: Instance Description
|
||||||
placeholder: Instance Description
|
placeholder: Instance Description
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue