mirror of https://github.com/rancher/ui.git
commit
a3d9fe1b6b
|
|
@ -1,5 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
tags: '',
|
||||
|
|
|
|||
|
|
@ -2,10 +2,16 @@ import Ember from 'ember';
|
|||
import C from 'ui/utils/constants';
|
||||
|
||||
export default Ember.Route.extend({
|
||||
modalService: Ember.inject.service('modal'),
|
||||
catalog: Ember.inject.service(),
|
||||
|
||||
parentRoute: 'catalog-tab',
|
||||
|
||||
actions: {
|
||||
cancel() {
|
||||
this.get('modalService').toggleModal();
|
||||
},
|
||||
},
|
||||
model: function(params/*, transition*/) {
|
||||
var store = this.get('store');
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,57 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
access: Ember.inject.service(),
|
||||
projects: Ember.inject.service(),
|
||||
hostService: Ember.inject.service('host'),
|
||||
driver: null,
|
||||
hostId: null,
|
||||
allowCustom: true,
|
||||
allowOther: true,
|
||||
forCatalog: true,
|
||||
inModal: false,
|
||||
goBack: null,
|
||||
|
||||
sortBy: ['name'],
|
||||
sortedDrivers: Ember.computed.sort('model.availableDrivers','sortBy'),
|
||||
|
||||
didReceiveAttrs() {
|
||||
if (!this.get('driver')) {
|
||||
if (this.get('inModal')) {
|
||||
this.set('driver', this.get('sortedDrivers.firstObject.name'));
|
||||
} else {
|
||||
this.set('driver', this.get('hostService.defaultDriver'));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
actions: {
|
||||
switchDriver(name) {
|
||||
if (this.get('hostId')) {
|
||||
this.set('hostId', null);
|
||||
this.set('model.clonedModel', null);
|
||||
}
|
||||
this.set('driver', name);
|
||||
},
|
||||
},
|
||||
|
||||
driverObj: Ember.computed('driver', function() {
|
||||
return this.get('model.availableDrivers').filterBy('name', this.get('driver'))[0];
|
||||
}),
|
||||
|
||||
hasOther: Ember.computed('model.availableDrivers.@each.hasUi', function() {
|
||||
return this.get('model.availableDrivers').filterBy('hasUi',false).length > 0;
|
||||
}),
|
||||
|
||||
showPicker: Ember.computed('model.availableDrivers.length','allowOther','hasOther','allowCustom', function() {
|
||||
return !this.get('projects.current.isWindows') && (
|
||||
this.get('model.availableDrivers.length') +
|
||||
(this.get('allowOther') && this.get('hasOther') ? 1 : 0) +
|
||||
(this.get('allowCustom') ? 1 : 0)
|
||||
) > 1;
|
||||
}),
|
||||
|
||||
showManage: Ember.computed('access.admin','projects.current.isWindows', function() {
|
||||
return !this.get('projects.current.isWindows') && this.get('access.admin');
|
||||
}),
|
||||
});
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
{{#if model.apiHostSet}}
|
||||
<section class="pt-10">
|
||||
{{#if showPicker}}
|
||||
<div class="row nav nav-boxes checked-active">
|
||||
{{#if (and allowCustom (not inModal))}}
|
||||
<a {{action "switchDriver" "custom"}} alt="custom" class="col nav-box-item driver machine-driver custom {{if (eq driver 'custom') 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
|
||||
{{#each sortedDrivers as |choice|}}
|
||||
{{#if choice.hasUi}}
|
||||
<a {{action "switchDriver" choice.name}} alt={{choice.name}} class="col nav-box-item driver machine-driver {{choice.name}} {{if (eq choice.name driver) 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
{{#if (and allowOther hasOther)}}
|
||||
<a {{action "switchDriver" "other"}} alt="other" class="col nav-box-item driver machine-driver other {{if (eq driver 'other') 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if (and access.admin (not forCatalog))}}
|
||||
<p class="text-center small m-0">
|
||||
{{#link-to "admin-tab.machine"}}{{t 'hostsPage.new.manageLink'}}{{/link-to}}
|
||||
</p>
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
{{#if driver}}
|
||||
{{component (if (or (not driverObj) driverObj.hasUi) (concat "machine/driver-" driver) 'machine/driver-other')
|
||||
cancel=(route-action 'cancel')
|
||||
clonedModel=model.clonedModel
|
||||
driver=(concat driver 'Config')
|
||||
schemas=model.schemas
|
||||
typeDocumentations=model.typeDocumentations
|
||||
availableDrivers=model.availableDrivers
|
||||
inModal=inModal
|
||||
completed=(action completed)
|
||||
goBack=goBack
|
||||
}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<section>
|
||||
<div>
|
||||
{{host-settings saved="savedHost"}}
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
|
|
@ -1,7 +1,9 @@
|
|||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAliyunecs.accountSection'}}</span>
|
||||
|
|
@ -221,5 +223,5 @@
|
|||
{{top-errors errors=errors}}
|
||||
|
||||
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -227,7 +227,9 @@
|
|||
<span>{{t 'machine.driverAmazon.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAmazon.instanceOptionsSection'}}</span>
|
||||
|
|
@ -297,5 +299,5 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverAzure.placementSection'}}</span>
|
||||
|
|
@ -198,5 +200,5 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -27,7 +27,9 @@
|
|||
</form>
|
||||
{{else}}
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverDigitalocean.regionSection'}}</span>
|
||||
|
|
@ -109,6 +111,6 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
{{/if}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -131,7 +131,9 @@
|
|||
<span>{{t 'machine.driverExoscale.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="row inline-form">
|
||||
<div class="col span-2 col-inline">
|
||||
|
|
@ -169,5 +171,5 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverOther.driverSection'}}</span>
|
||||
|
|
@ -39,5 +41,5 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
<form>
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverPacket.accountSection'}}</span>
|
||||
|
|
@ -74,6 +76,6 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverRackspace.accountSection'}}</span>
|
||||
|
|
@ -64,5 +66,5 @@
|
|||
{{partial "host/add-options"}}
|
||||
</div>
|
||||
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -67,7 +67,9 @@
|
|||
<span>{{t 'machine.driverUbiquity.instanceSection'}}</span>
|
||||
</div>
|
||||
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverUbiquity.regionSection'}}</span>
|
||||
|
|
@ -113,5 +115,5 @@
|
|||
</div>
|
||||
|
||||
{{top-errors errors=errors}}
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,9 @@
|
|||
|
||||
<section class="horizontal-form">
|
||||
<div class="container-fluid">
|
||||
{{#unless inModal}}
|
||||
{{partial "host/add-common"}}
|
||||
{{/unless}}
|
||||
|
||||
<div class="over-hr mt-20 mb-20">
|
||||
<span>{{t 'machine.driverVsphere.accountSection'}}</span>
|
||||
|
|
@ -131,5 +133,5 @@
|
|||
{{partial "host/add-options"}}
|
||||
</div>
|
||||
|
||||
{{save-cancel save="save" cancel="cancel"}}
|
||||
{{save-cancel save=driverSaveAction cancel="cancel"}}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
import Ember from 'ember';
|
||||
import ModalBase from 'ui/mixins/modal-base';
|
||||
|
||||
export default Ember.Component.extend(ModalBase, {
|
||||
modalService: Ember.inject.service('modal'),
|
||||
hostService: Ember.inject.service('host'),
|
||||
classNames: ['full-modal'],
|
||||
loading: true,
|
||||
model: null,
|
||||
hostConfig: null,
|
||||
goBack: null,
|
||||
actions: {
|
||||
completed(hostConfig) {
|
||||
this.get('modalService.modalOpts.callee').send('completed', hostConfig);
|
||||
Ember.run.next(() => {
|
||||
this.get('modalService').toggleModal();
|
||||
});
|
||||
}
|
||||
},
|
||||
init() {
|
||||
this._super(...arguments);
|
||||
var hs = this.get('hostService');
|
||||
|
||||
hs.loadAllDrivers().then((drivers) => {
|
||||
this.set('machineDrivers', drivers);
|
||||
hs.getModel().then((hash) => {
|
||||
this.set('model', hash);
|
||||
this.set('loading', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
{{#if loading}}
|
||||
<div class="text-center">
|
||||
<i class="icon icon-spinner icon-spin"></i> {{t 'generic.loading'}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{add-host model=model inModal=true completed=(action 'completed')}}
|
||||
{{/if}}
|
||||
|
|
@ -0,0 +1,33 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
modalService: Ember.inject.service('modal'),
|
||||
hostConfig: null,
|
||||
hostName: null,
|
||||
value: null,
|
||||
actions: {
|
||||
launchHost() {
|
||||
// we should reall not kill the previous driver if they edit, fix this in the future
|
||||
if (this.get('hostConfig')) {
|
||||
this.setProperties({
|
||||
hostConfig: null,
|
||||
hostName: null
|
||||
});
|
||||
}
|
||||
this.get('modalService').toggleModal('modal-catalog-host', {
|
||||
callee: this,
|
||||
});
|
||||
},
|
||||
completed(value){
|
||||
this.setProperties({
|
||||
hostConfig: value, // probably use this when we are sending it back up on edit
|
||||
value: JSON.stringify(value)
|
||||
});
|
||||
Object.keys(value).forEach((key) => {
|
||||
if (key.indexOf('Config') >= 0) {
|
||||
this.set('hostName', key.slice(0, key.indexOf('Config')).capitalize());
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
{{#if hostConfig}}
|
||||
{{hostName}} <a href="#" {{action 'launchHost'}}>{{t 'generic.remove'}}</a>
|
||||
{{else}}
|
||||
<button {{action "launchHost"}} class="btn bg-primary">{{t 'schema.inputHost.label'}}</button>
|
||||
{{/if}}
|
||||
|
|
@ -1,47 +1,11 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Controller.extend({
|
||||
access: Ember.inject.service(),
|
||||
projects: Ember.inject.service(),
|
||||
|
||||
queryParams : ['backTo', 'driver', 'hostId'],
|
||||
backTo : null,
|
||||
driver : null,
|
||||
hostId : null,
|
||||
|
||||
allowCustom : true,
|
||||
allowOther : true,
|
||||
|
||||
actions: {
|
||||
switchDriver(name) {
|
||||
if (this.get('hostId')) {
|
||||
this.set('hostId', null);
|
||||
this.set('model.clonedModel', null);
|
||||
completed() {}
|
||||
}
|
||||
this.set('driver', name);
|
||||
},
|
||||
},
|
||||
|
||||
driverObj: function() {
|
||||
return this.get('model.availableDrivers').filterBy('name', this.get('driver'))[0];
|
||||
}.property('driver'),
|
||||
|
||||
hasOther: function() {
|
||||
return this.get('model.availableDrivers').filterBy('hasUi',false).length > 0;
|
||||
}.property('model.availableDrivers.@each.hasUi'),
|
||||
|
||||
showPicker: function() {
|
||||
return !this.get('projects.current.isWindows') && (
|
||||
this.get('model.availableDrivers.length') +
|
||||
(this.get('allowOther') && this.get('hasOther') ? 1 : 0) +
|
||||
(this.get('allowCustom') ? 1 : 0)
|
||||
) > 1;
|
||||
}.property('model.availableDrivers.length','allowOther','hasOther','allowCustom'),
|
||||
|
||||
showManage: function() {
|
||||
return !this.get('projects.current.isWindows') && this.get('access.admin');
|
||||
}.property('access.admin','projects.current.isWindows'),
|
||||
|
||||
sortedDrivers: Ember.computed.sort('model.availableDrivers','sortBy'),
|
||||
sortBy: ['name'],
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,25 +1,11 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
import Util from 'ui/utils/util';
|
||||
const { getOwner } = Ember;
|
||||
|
||||
function proxifyUrl(url, proxyBase) {
|
||||
let parsed = Util.parseUrl(url);
|
||||
|
||||
if ( parsed.hostname.indexOf('.') === -1 || // No dot, local name like localhost
|
||||
parsed.hostname.toLowerCase().match(/\.local$/) || // your-macbook.local
|
||||
parsed.origin.toLowerCase() === window.location.origin // You are here
|
||||
) {
|
||||
return url;
|
||||
} else {
|
||||
return proxyBase + '/' + url;
|
||||
}
|
||||
}
|
||||
|
||||
export default Ember.Route.extend({
|
||||
access : Ember.inject.service(),
|
||||
projects : Ember.inject.service(),
|
||||
settings : Ember.inject.service(),
|
||||
host : Ember.inject.service(),
|
||||
backTo : null,
|
||||
|
||||
defaultDriver: 'custom',
|
||||
|
|
@ -77,142 +63,24 @@ export default Ember.Route.extend({
|
|||
beforeModel(/*transition*/) {
|
||||
this._super(...arguments);
|
||||
|
||||
let us = this.get('userStore');
|
||||
let drivers = [];
|
||||
var hs = this.get('host');
|
||||
|
||||
return us.find('machinedriver', null, {forceReload: true}).then((possible) => {
|
||||
let promises = [];
|
||||
|
||||
possible.filterBy('state','active').forEach((driver) => {
|
||||
let schemaName = driver.get('name') + 'Config';
|
||||
promises.push(us.find('schema', schemaName).then(() => {
|
||||
drivers.push(driver);
|
||||
}).catch(() => {
|
||||
return Ember.RSVP.resolve();
|
||||
}));
|
||||
});
|
||||
|
||||
return Ember.RSVP.all(promises);
|
||||
}).then(() => {
|
||||
return hs.loadAllDrivers().then((drivers) => {
|
||||
this.set('machineDrivers', drivers);
|
||||
});
|
||||
},
|
||||
|
||||
model(params) {
|
||||
this.set('backTo', params.backTo);
|
||||
var hs = this.get('host');
|
||||
|
||||
let promises = {
|
||||
reloadHost: this.get('userStore').find('schema','host', {forceReload: true}),
|
||||
loadCustomUi: this.loadCustomUi(),
|
||||
schemas: this.get('userStore').find('schema'),
|
||||
typeDocumentations: this.get('userStore').findAll('typedocumentation')
|
||||
};
|
||||
|
||||
if ( params.hostId )
|
||||
{
|
||||
promises.clonedModel = this.getHost(params.hostId);
|
||||
}
|
||||
|
||||
if ( this.get('access.admin') ) {
|
||||
let settings = this.get('settings');
|
||||
promises.apiHostSet = settings.load(C.SETTING.API_HOST).then(() => {
|
||||
return !!settings.get(C.SETTING.API_HOST);
|
||||
});
|
||||
return hs.getModel(params).then((hash) => {
|
||||
if (hash.transition) {
|
||||
this.transitionTo('hosts.new', {queryParams: {driver: hash.driver}});
|
||||
} else {
|
||||
promises.apiHostSet = Ember.RSVP.resolve(true);
|
||||
}
|
||||
|
||||
return Ember.RSVP.hash(promises).then((hash) => {
|
||||
hash.availableDrivers = this.get('machineDrivers');
|
||||
if ( this.get('projects.current.isWindows') ) {
|
||||
hash.availableDrivers = [];
|
||||
}
|
||||
|
||||
let defaultDriver = this.get('defaultDriver');
|
||||
let targetDriver = params.driver || this.get('lastDriver') || defaultDriver;
|
||||
|
||||
if ( ['custom','other'].indexOf(targetDriver) === -1 && hash.availableDrivers.filterBy('name', targetDriver).length === 0 )
|
||||
{
|
||||
targetDriver = defaultDriver;
|
||||
}
|
||||
|
||||
if ( params.driver !== targetDriver )
|
||||
{
|
||||
this.transitionTo('hosts.new', {queryParams: {driver: targetDriver}});
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ember.Object.create(hash);
|
||||
return hash;
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Loads the custom UI CSS/JS for drivers that have a uiUrl,
|
||||
loadCustomUi() {
|
||||
return new Ember.RSVP.Promise((resolve, reject) => {
|
||||
let completed = 0, expected = 0;
|
||||
let timer = null;
|
||||
|
||||
function loaded() {
|
||||
completed++;
|
||||
if ( completed === expected ) {
|
||||
resolve();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
function errored(name) {
|
||||
clearTimeout(timer);
|
||||
reject({type: 'error', message: 'Error loading custom driver UI: ' + name});
|
||||
}
|
||||
|
||||
// machineDrivers already contains only the active ones with a schema
|
||||
this.get('machineDrivers').forEach((driver) => {
|
||||
let id = 'driver-ui-js-' + driver.name;
|
||||
if (driver.uiUrl && $(`#${id}`).length === 0 ) {
|
||||
expected++;
|
||||
let script = document.createElement('script');
|
||||
script.onload = function() { loaded(driver.name); };
|
||||
script.onerror = function() {errored(driver.name); };
|
||||
script.src = proxifyUrl(driver.uiUrl, this.get('app.proxyEndpoint'));
|
||||
script.id = id;
|
||||
document.getElementsByTagName('BODY')[0].appendChild(script);
|
||||
|
||||
expected++;
|
||||
let link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.id = id;
|
||||
link.href = proxifyUrl(driver.uiUrl.replace(/\.js$/,'.css'), this.get('app.proxyEndpoint'));
|
||||
link.onload = function() { loaded(driver.name); };
|
||||
link.onerror = function() { errored(driver.name); };
|
||||
document.getElementsByTagName('HEAD')[0].appendChild(link);
|
||||
}
|
||||
});
|
||||
|
||||
if ( expected === 0 ) {
|
||||
resolve();
|
||||
} else {
|
||||
timer = setTimeout(function() {
|
||||
reject({type: 'error', message: 'Timeout loading custom machine drivers'});
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
getHost(hostId) {
|
||||
let store = this.get('store');
|
||||
return store.find('host', hostId).then((host) => {
|
||||
|
||||
let hostOut = host.cloneForNew();
|
||||
let src = host[`${host.driver}Config`];
|
||||
if ( src ) {
|
||||
src.type = `${host.driver}Config`;
|
||||
let config = store.createRecord(src);
|
||||
hostOut.set(`${host.driver}Config`, config);
|
||||
}
|
||||
return hostOut;
|
||||
}).catch(() => {
|
||||
return Ember.RSVP.reject({type: 'error', message: 'Failed to retrieve cloned model'}) ;
|
||||
});
|
||||
},
|
||||
});
|
||||
|
|
|
|||
|
|
@ -5,47 +5,4 @@
|
|||
</h1>
|
||||
</section>
|
||||
|
||||
{{#if model.apiHostSet}}
|
||||
<section class="pt-10">
|
||||
{{#if showPicker}}
|
||||
<div class="row nav nav-boxes checked-active">
|
||||
{{#if allowCustom}}
|
||||
<a {{action "switchDriver" "custom"}} alt="custom" class="col nav-box-item driver machine-driver custom {{if (eq driver 'custom') 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
|
||||
{{#each sortedDrivers as |choice|}}
|
||||
{{#if choice.hasUi}}
|
||||
<a {{action "switchDriver" choice.name}} alt={{choice.name}} class="col nav-box-item driver machine-driver {{choice.name}} {{if (eq choice.name driver) 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
|
||||
{{#if (and allowOther hasOther)}}
|
||||
<a {{action "switchDriver" "other"}} alt="other" class="col nav-box-item driver machine-driver other {{if (eq driver 'other') 'active'}}" href="#"></a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if access.admin}}
|
||||
<p class="text-center small m-0">
|
||||
{{#link-to "admin-tab.machine"}}{{t 'hostsPage.new.manageLink'}}{{/link-to}}
|
||||
</p>
|
||||
{{/if}}
|
||||
</section>
|
||||
|
||||
{{#if driver}}
|
||||
{{component (if (or (not driverObj) driverObj.hasUi) (concat "machine/driver-" driver) 'machine/driver-other')
|
||||
cancel=(route-action 'cancel')
|
||||
goBack=(route-action 'goBack')
|
||||
clonedModel=model.clonedModel
|
||||
driver=(concat driver 'Config')
|
||||
schemas=model.schemas
|
||||
typeDocumentations=model.typeDocumentations
|
||||
availableDrivers=model.availableDrivers
|
||||
}}
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<section>
|
||||
<div>
|
||||
{{host-settings saved="savedHost"}}
|
||||
</div>
|
||||
</section>
|
||||
{{/if}}
|
||||
{{add-host model=model driver=driver hostId=hostId completed=(action 'completed') goBack=(route-action 'goBack')}}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Service.extend({
|
||||
});
|
||||
|
|
@ -19,6 +19,7 @@ export default Ember.Mixin.create(NewOrEdit, ManageLabels, {
|
|||
multiTemplate : null,
|
||||
clonedModel : null,
|
||||
useHost : true,
|
||||
hostConfig : null,
|
||||
|
||||
actions: {
|
||||
addLabel: addAction('addLabel', '.key'),
|
||||
|
|
@ -26,7 +27,13 @@ export default Ember.Mixin.create(NewOrEdit, ManageLabels, {
|
|||
this.attrs.cancel();
|
||||
},
|
||||
goBack() {
|
||||
if (Ember.typeOf(this.attrs.goBack) === 'function') {
|
||||
this.attrs.goBack();
|
||||
}
|
||||
},
|
||||
passConfigBack(cb) {
|
||||
this.sendAction('completed', this.get('model'));
|
||||
cb(true);
|
||||
},
|
||||
setLabels(labels) {
|
||||
let out = {};
|
||||
|
|
@ -52,6 +59,14 @@ export default Ember.Mixin.create(NewOrEdit, ManageLabels, {
|
|||
}
|
||||
},
|
||||
|
||||
driverSaveAction: Ember.computed('inModal', function() {
|
||||
if (this.get('inModal')) {
|
||||
return 'passConfigBack';
|
||||
} else {
|
||||
return 'save';
|
||||
}
|
||||
}),
|
||||
|
||||
nameParts: function() {
|
||||
let input = this.get('prefix')||'';
|
||||
let count = this.get('count');
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import Ember from 'ember';
|
||||
import NewOrEdit from 'ui/mixins/new-or-edit';
|
||||
import C from 'ui/utils/constants';
|
||||
import {tagChoices, tagsToArray} from 'ui/models/stack';
|
||||
|
||||
export default Ember.Controller.extend(NewOrEdit, {
|
||||
|
|
|
|||
|
|
@ -125,6 +125,9 @@ Router.map(function() {
|
|||
this.route('add', {path: '/add/:cloud_id'});
|
||||
});
|
||||
|
||||
this.route('new', {path: '/add'}, function() {
|
||||
this.route('index', {path: '/'});
|
||||
});
|
||||
|
||||
this.route('host', {path: '/:host_id', resetNamespace: true}, function() {
|
||||
this.route('containers');
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
import { tagsToArray } from 'ui/models/stack';
|
||||
import { headersWithHost as containerHeaders } from 'ui/components/container-table/component';
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,164 @@
|
|||
import Ember from 'ember';
|
||||
import C from 'ui/utils/constants';
|
||||
import Util from 'ui/utils/util';
|
||||
|
||||
function proxifyUrl(url, proxyBase) {
|
||||
let parsed = Util.parseUrl(url);
|
||||
|
||||
if ( parsed.hostname.indexOf('.') === -1 || // No dot, local name like localhost
|
||||
parsed.hostname.toLowerCase().match(/\.local$/) || // your-macbook.local
|
||||
parsed.origin.toLowerCase() === window.location.origin // You are here
|
||||
) {
|
||||
return url;
|
||||
} else {
|
||||
return proxyBase + '/' + url;
|
||||
}
|
||||
}
|
||||
|
||||
export default Ember.Service.extend({
|
||||
userStore: Ember.inject.service('user-store'),
|
||||
access : Ember.inject.service(),
|
||||
projects : Ember.inject.service(),
|
||||
settings : Ember.inject.service(),
|
||||
machineDrivers: null,
|
||||
defaultDriver: 'custom',
|
||||
loadAllDrivers() {
|
||||
let us = this.get('userStore');
|
||||
let drivers = [];
|
||||
|
||||
return new Ember.RSVP.Promise((resolve, reject) => {
|
||||
us.find('machinedriver', null, {forceReload: true}).then((possible) => {
|
||||
let promises = [];
|
||||
|
||||
possible.filterBy('state','active').forEach((driver) => {
|
||||
let schemaName = driver.get('name') + 'Config';
|
||||
promises.push(us.find('schema', schemaName).then(() => {
|
||||
drivers.push(driver);
|
||||
}).catch(() => {
|
||||
reject();
|
||||
}));
|
||||
});
|
||||
|
||||
Ember.RSVP.all(promises);
|
||||
}).then(() => {
|
||||
this.set('machineDrivers', drivers);
|
||||
resolve(drivers);
|
||||
});
|
||||
});
|
||||
},
|
||||
getHost(hostId) {
|
||||
let store = this.get('store');
|
||||
return store.find('host', hostId).then((host) => {
|
||||
|
||||
let hostOut = host.cloneForNew();
|
||||
let src = host[`${host.driver}Config`];
|
||||
if ( src ) {
|
||||
src.type = `${host.driver}Config`;
|
||||
let config = store.createRecord(src);
|
||||
hostOut.set(`${host.driver}Config`, config);
|
||||
}
|
||||
return hostOut;
|
||||
}).catch(() => {
|
||||
return Ember.RSVP.reject({type: 'error', message: 'Failed to retrieve cloned model'}) ;
|
||||
});
|
||||
},
|
||||
getModel(params=null) {
|
||||
let promises = {
|
||||
reloadHost: this.get('userStore').find('schema','host', {forceReload: true}),
|
||||
loadCustomUi: this.loadCustomUi(),
|
||||
schemas: this.get('userStore').find('schema'),
|
||||
typeDocumentations: this.get('userStore').findAll('typedocumentation')
|
||||
};
|
||||
|
||||
if (params && params.hostId )
|
||||
{
|
||||
promises.clonedModel = this.getHost(params.hostId);
|
||||
}
|
||||
|
||||
|
||||
if ( this.get('access.admin') ) {
|
||||
let settings = this.get('settings');
|
||||
promises.apiHostSet = settings.load(C.SETTING.API_HOST).then(() => {
|
||||
return !!settings.get(C.SETTING.API_HOST);
|
||||
});
|
||||
} else {
|
||||
promises.apiHostSet = Ember.RSVP.resolve(true);
|
||||
}
|
||||
|
||||
return Ember.RSVP.hash(promises).then((hash) => {
|
||||
hash.availableDrivers = this.get('machineDrivers');
|
||||
if ( this.get('projects.current.isWindows') ) {
|
||||
hash.availableDrivers = [];
|
||||
}
|
||||
|
||||
let defaultDriver = this.get('defaultDriver');
|
||||
let targetDriver = params && params.driver ? params.driver : defaultDriver;
|
||||
|
||||
if ( ['custom','other'].indexOf(targetDriver) === -1 && hash.availableDrivers.filterBy('name', targetDriver).length === 0 )
|
||||
{
|
||||
targetDriver = defaultDriver;
|
||||
}
|
||||
|
||||
if (params && params.driver !== targetDriver )
|
||||
{
|
||||
return {transition: true, driver: targetDriver};
|
||||
}
|
||||
else
|
||||
{
|
||||
return Ember.Object.create(hash);
|
||||
}
|
||||
});
|
||||
},
|
||||
// Loads the custom UI CSS/JS for drivers that have a uiUrl,
|
||||
loadCustomUi() {
|
||||
return new Ember.RSVP.Promise((resolve, reject) => {
|
||||
let completed = 0, expected = 0;
|
||||
let timer = null;
|
||||
|
||||
function loaded() {
|
||||
completed++;
|
||||
if ( completed === expected ) {
|
||||
resolve();
|
||||
clearTimeout(timer);
|
||||
}
|
||||
}
|
||||
|
||||
function errored(name) {
|
||||
clearTimeout(timer);
|
||||
reject({type: 'error', message: 'Error loading custom driver UI: ' + name});
|
||||
}
|
||||
|
||||
// machineDrivers already contains only the active ones with a schema
|
||||
this.get('machineDrivers').forEach((driver) => {
|
||||
let id = 'driver-ui-js-' + driver.name;
|
||||
if (driver.uiUrl && $(`#${id}`).length === 0 ) {
|
||||
expected++;
|
||||
let script = document.createElement('script');
|
||||
script.onload = function() { loaded(driver.name); };
|
||||
script.onerror = function() {errored(driver.name); };
|
||||
script.src = proxifyUrl(driver.uiUrl, this.get('app.proxyEndpoint'));
|
||||
script.id = id;
|
||||
document.getElementsByTagName('BODY')[0].appendChild(script);
|
||||
|
||||
expected++;
|
||||
let link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.id = id;
|
||||
link.href = proxifyUrl(driver.uiUrl.replace(/\.js$/,'.css'), this.get('app.proxyEndpoint'));
|
||||
link.onload = function() { loaded(driver.name); };
|
||||
link.onerror = function() { errored(driver.name); };
|
||||
document.getElementsByTagName('HEAD')[0].appendChild(link);
|
||||
}
|
||||
});
|
||||
|
||||
if ( expected === 0 ) {
|
||||
resolve();
|
||||
} else {
|
||||
timer = setTimeout(function() {
|
||||
reject({type: 'error', message: 'Timeout loading custom machine drivers'});
|
||||
}, 10000);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
});
|
||||
|
|
@ -405,6 +405,7 @@ C.SUPPORTED_SCHEMA_INPUTS= [
|
|||
'date',
|
||||
'enum',
|
||||
'float',
|
||||
'host',
|
||||
'int',
|
||||
'multiline',
|
||||
'password',
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
"dotenv": "^4.0.0",
|
||||
"ember-api-store": "2.2.0",
|
||||
"ember-browserify": "^1.0.1",
|
||||
"ember-cli": "^2.9.1",
|
||||
"ember-cli": "2.9.1",
|
||||
"ember-cli-app-version": "^2.0.0",
|
||||
"ember-cli-babel": "^5.1.7",
|
||||
"ember-cli-clipboard": "0.4.1",
|
||||
|
|
@ -60,7 +60,7 @@
|
|||
"forever-agent": "^0.6.1",
|
||||
"glob": "^5.0.3",
|
||||
"http-proxy": "^1.11.1",
|
||||
"liquid-fire": "0.26.4",
|
||||
"liquid-fire": "0.27.1",
|
||||
"loader.js": "^4.0.10",
|
||||
"postcss-scss": "^0.4.0",
|
||||
"semver": "^5.3.0",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
import { moduleFor, test } from 'ember-qunit';
|
||||
|
||||
moduleFor('service:ll', 'Unit | Service | ll', {
|
||||
// Specify the other units that are required for this test.
|
||||
// needs: ['service:foo']
|
||||
});
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it exists', function(assert) {
|
||||
let service = this.subject();
|
||||
assert.ok(service);
|
||||
});
|
||||
|
|
@ -3217,6 +3217,8 @@ schema:
|
|||
prompt: Choose a Certificate...
|
||||
inputEnum:
|
||||
option: Choose an option...
|
||||
inputHost:
|
||||
label: Select Host
|
||||
inputService:
|
||||
prompt: Choose a Service...
|
||||
inputSecret:
|
||||
|
|
|
|||
Loading…
Reference in New Issue