mirror of https://github.com/rancher/ui.git
388 lines
11 KiB
JavaScript
388 lines
11 KiB
JavaScript
import { equal } from '@ember/object/computed';
|
|
import { next } from '@ember/runloop';
|
|
import { resolve, reject, all } from 'rsvp';
|
|
import { inject as service } from '@ember/service';
|
|
import Component from '@ember/component';
|
|
import NewOrEdit from 'shared/mixins/new-or-edit';
|
|
import { debouncedObserver } from 'ui/utils/debounce';
|
|
import C from 'ui/utils/constants';
|
|
import { flattenLabelArrays } from 'shared/mixins/manage-labels';
|
|
import Util from 'ui/utils/util';
|
|
import layout from './template';
|
|
|
|
export default Component.extend(NewOrEdit, {
|
|
layout,
|
|
intl: service(),
|
|
prefs: service(),
|
|
settings: service(),
|
|
|
|
tagName: 'form',
|
|
|
|
isService: false,
|
|
isUpgrade: false,
|
|
service: null,
|
|
launchConfig: null,
|
|
launchConfigIndex: null, // null: not valid here, -1: Primary LC, 0-n: Sidekick SLCs
|
|
|
|
stack: null,
|
|
scale: 1,
|
|
mode: null,
|
|
|
|
serviceLinksArray: null,
|
|
isRequestedHost: null,
|
|
upgradeOptions: null,
|
|
volumesToCreate: null,
|
|
|
|
// Errors from components
|
|
commandErrors: null,
|
|
volumeErrors: null,
|
|
networkingErrors: null,
|
|
secretsErrors: null,
|
|
healthCheckErrors: null,
|
|
schedulingErrors: null,
|
|
securityErrors: null,
|
|
scaleErrors: null,
|
|
imageErrors: null,
|
|
portErrors: null,
|
|
stackErrors: null,
|
|
metadataErrors: null,
|
|
|
|
actions: {
|
|
setImage(uuid) {
|
|
this.set('launchConfig.image', uuid);
|
|
},
|
|
|
|
setLabels(section,labels) {
|
|
this.set(section+'Labels', labels);
|
|
},
|
|
|
|
setRequestedHostId(hostId) {
|
|
this.set('launchConfig.requestedHostId', hostId);
|
|
},
|
|
|
|
setUpgrade(upgrade) {
|
|
this.set('upgradeOptions', upgrade);
|
|
},
|
|
|
|
done() {
|
|
this.sendAction('done');
|
|
},
|
|
|
|
cancel() {
|
|
this.sendAction('cancel');
|
|
},
|
|
|
|
addSidekick() {
|
|
var ary = this.get('service.secondaryLaunchConfigs');
|
|
ary.pushObject(this.get('store').createRecord({
|
|
type: 'secondaryLaunchConfig',
|
|
kind: 'container',
|
|
tty: true,
|
|
stdinOpen: true,
|
|
restartPolicy: {name: 'always'},
|
|
labels: { [C.LABEL.PULL_IMAGE]: C.LABEL.PULL_IMAGE_VALUE },
|
|
uiId: Util.randomStr(),
|
|
}));
|
|
},
|
|
|
|
removeSidekick(idx) {
|
|
var ary = this.get('primaryService.secondaryLaunchConfigs');
|
|
ary.removeAt(idx);
|
|
},
|
|
},
|
|
|
|
init() {
|
|
window.nec = this;
|
|
this._super(...arguments);
|
|
|
|
// Tell cattle that we're sending the whole thing, not a diff.
|
|
this.set('service.completeLaunchConfigs', true);
|
|
|
|
if ( !this.get('launchConfig.secrets') ) {
|
|
this.set('launchConfig.secrets', []);
|
|
}
|
|
|
|
if ( !this.get('launchConfig.metadata') ) {
|
|
this.set('launchConfig.metadata', {});
|
|
}
|
|
|
|
if ( this.get('isService') && !this.get('isSidekick') ) {
|
|
this.setProperties({
|
|
name: this.get('service.name'),
|
|
description: this.get('service.description'),
|
|
scale: this.get('service.scale'),
|
|
});
|
|
} else {
|
|
this.setProperties({
|
|
name: this.get('launchConfig.name'),
|
|
description: this.get('launchConfig.description'),
|
|
});
|
|
}
|
|
|
|
let stackId = null;
|
|
if ( this.get('isService') ) {
|
|
stackId = this.get('service.stackId');
|
|
} else {
|
|
stackId = this.get('launchConfig.stackId');
|
|
}
|
|
|
|
if ( stackId ) {
|
|
let stack = this.get('store').getById('stack', stackId);
|
|
if ( stack ) {
|
|
this.set('stack', stack);
|
|
}
|
|
}
|
|
|
|
this.labelsChanged();
|
|
},
|
|
|
|
didInsertElement() {
|
|
this.$("INPUT[type='text']")[0].focus();
|
|
},
|
|
|
|
// ----------------------------------
|
|
// Labels
|
|
// ----------------------------------
|
|
userLabels: null,
|
|
scaleLabels: null,
|
|
securityLabels: null,
|
|
commandLabels: null,
|
|
schedulingLabels: null,
|
|
networkingLabels: null,
|
|
|
|
labelsChanged: debouncedObserver(
|
|
'userLabels.@each.{key,value}',
|
|
'scaleLabels.@each.{key,value}',
|
|
'securityLabels.@each.{key,value}',
|
|
'commandLabels.@each.{key,value}',
|
|
'schedulingLabels.@each.{key,value}',
|
|
'networkingLabels.@each.{key,value}',
|
|
function() {
|
|
let out = flattenLabelArrays(
|
|
this.get('userLabels'),
|
|
this.get('scaleLabels'),
|
|
this.get('securityLabels'),
|
|
this.get('commandLabels'),
|
|
this.get('schedulingLabels'),
|
|
this.get('networkingLabels')
|
|
);
|
|
|
|
var config = this.get('launchConfig');
|
|
if ( config )
|
|
{
|
|
this.set('launchConfig.labels', out);
|
|
}
|
|
}
|
|
),
|
|
|
|
// ----------------------------------
|
|
// Save
|
|
// ----------------------------------
|
|
validate() {
|
|
let pr = this.get('primaryResource');
|
|
let errors = pr.validationErrors() || [];
|
|
|
|
if ( this.get('isService') )
|
|
{
|
|
(this.get('service.secondaryLaunchConfigs')||[]).forEach((slc) => {
|
|
slc.validationErrors().forEach((err) => {
|
|
errors.push(slc.get('displayName') + ': ' + err);
|
|
});
|
|
});
|
|
}
|
|
|
|
// Errors from components
|
|
errors.pushObjects(this.get('commandErrors')||[]);
|
|
errors.pushObjects(this.get('volumeErrors')||[]);
|
|
errors.pushObjects(this.get('networkingErrors')||[]);
|
|
errors.pushObjects(this.get('secretsErrors')||[]);
|
|
errors.pushObjects(this.get('healthCheckErrors')||[]);
|
|
errors.pushObjects(this.get('schedulingErrors')||[]);
|
|
errors.pushObjects(this.get('securityErrors')||[]);
|
|
errors.pushObjects(this.get('scaleErrors')||[]);
|
|
errors.pushObjects(this.get('imageErrors')||[]);
|
|
errors.pushObjects(this.get('portErrors')||[]);
|
|
errors.pushObjects(this.get('stackErrors')||[]);
|
|
errors.pushObjects(this.get('metadataErrors')||[]);
|
|
|
|
errors = errors.uniq();
|
|
|
|
if ( errors.get('length') )
|
|
{
|
|
this.set('errors', errors);
|
|
return false;
|
|
}
|
|
|
|
this.set('errors', null);
|
|
return true;
|
|
},
|
|
|
|
willSave() {
|
|
let intl = this.get('intl');
|
|
let pr;
|
|
let nameResource;
|
|
let lc = this.get('launchConfig').clone();
|
|
let name = (this.get('name')||'').trim().toLowerCase();
|
|
|
|
|
|
if ( this.get('isSidekick') ) {
|
|
let service = this.get('service');
|
|
let errors = [];
|
|
if ( !service ) {
|
|
errors.push(this.get('intl').t('newContainer.errors.noSidekick'));
|
|
this.set('errors', errors);
|
|
return false;
|
|
}
|
|
|
|
if ( !name ) {
|
|
errors.push(intl.t('validation.required', {key: intl.t('formNameDescription.name.label')}));
|
|
this.set('errors', errors);
|
|
return false;
|
|
}
|
|
|
|
pr = service.clone();
|
|
let def = lc.serialize();
|
|
def.type = 'secondaryLaunchConfig';
|
|
let sidekick = this.get('store').createRecord(def);
|
|
nameResource = sidekick;
|
|
|
|
let slc = pr.get('secondaryLaunchConfigs');
|
|
if ( !slc ) {
|
|
slc = [];
|
|
pr.set('secondaryLaunchConfigs', slc);
|
|
}
|
|
|
|
let lci = this.get('launchConfigIndex');
|
|
if ( lci === undefined || lci === null ) {
|
|
// If it's a new sidekick, add it to the end of the list
|
|
lci = slc.length;
|
|
}
|
|
|
|
let duplicate = slc.find((x, idx) => {
|
|
return idx !== lci && x.get('name').toLowerCase() === name;
|
|
});
|
|
if ( duplicate ) {
|
|
errors.push(intl.t('newContainer.errors.duplicateName', {name: name, service: duplicate.get('displayName')}));
|
|
this.set('errors', errors);
|
|
return false;
|
|
}
|
|
|
|
slc[lci] = sidekick;
|
|
} else if ( this.get('isService') ) {
|
|
pr = this.get('service').clone();
|
|
nameResource = pr;
|
|
pr.set('launchConfig', lc);
|
|
pr.set('scale', this.get('scale'));
|
|
} else {
|
|
// Convert the launch config to a container
|
|
let lc = this.get('launchConfig').serialize();
|
|
lc.type = 'container';
|
|
pr = this.get('store').createRecord(lc);
|
|
nameResource = pr;
|
|
}
|
|
|
|
pr.set('completeUpdate', true);
|
|
|
|
nameResource.setProperties({
|
|
name: this.get('name'),
|
|
description: this.get('description'),
|
|
});
|
|
|
|
this.set('primaryResource', pr);
|
|
this.set('originalPrimaryResource', pr);
|
|
|
|
let ok = this.validate();
|
|
return ok;
|
|
},
|
|
|
|
doSave() {
|
|
let pr = this.get('primaryResource');
|
|
|
|
let stackPromise = resolve();
|
|
if ( !this.get('isUpgrade') ) {
|
|
// Set the stack ID
|
|
if ( this.get('stack.id') ) {
|
|
pr.set('stackId', this.get('stack.id'));
|
|
} else if ( this.get('stack') ) {
|
|
stackPromise = this.get('stack').save().then((newStack) => {
|
|
pr.set('stackId', newStack.get('id'));
|
|
});
|
|
} else {
|
|
// This shouldn't happen since willSave checked it...
|
|
return reject('No Stack');
|
|
}
|
|
}
|
|
|
|
let self = this;
|
|
let sup = self._super;
|
|
|
|
return stackPromise.then(() => {
|
|
let volumes = this.get('volumesToCreate');
|
|
let volumesPromise = resolve();
|
|
|
|
if ( volumes && volumes.get('length') ) {
|
|
volumesPromise = all(volumes.map((volume) => {
|
|
volume.set('stackId', this.get('stack.id'));
|
|
return volume.save();
|
|
}));
|
|
}
|
|
|
|
return volumesPromise.then(() => {
|
|
if ( this.get('isUpgrade') && !this.get('isService') ) {
|
|
// Container upgrade
|
|
return this.get('launchConfig').doAction('upgrade', {config: this.get('launchConfig')});
|
|
} else {
|
|
// Container create or Service create/upgrade
|
|
return sup.apply(self,arguments);
|
|
}
|
|
});
|
|
});
|
|
},
|
|
|
|
doneSaving() {
|
|
if ( !this.get('isUpgrade') ) {
|
|
let mode = this.get('mode');
|
|
if ( mode === 'sidekick' ) {
|
|
// Remember sidekick as service since you're not
|
|
// likely to want to add many sidekicks in a row
|
|
mode = 'service';
|
|
}
|
|
this.set(`prefs.${C.PREFS.LAST_SCALE_MODE}`, mode);
|
|
this.set(`prefs.${C.PREFS.LAST_STACK}`, this.get('stack.id'));
|
|
}
|
|
this.sendAction('done');
|
|
},
|
|
|
|
header: '',
|
|
updateHeader: function() {
|
|
let args = {};
|
|
let k = 'newContainer.';
|
|
k += (this.get('isUpgrade') ? 'upgrade' : 'add') + '.';
|
|
if ( this.get('isSidekick') ) {
|
|
let svc = this.get('service');
|
|
if ( svc ) {
|
|
k += 'sidekickName';
|
|
args = {name: this.get('service.displayName')};
|
|
} else {
|
|
k += 'sidekick';
|
|
}
|
|
} else if ( this.get('isGlobal') ) {
|
|
k += 'globalService';
|
|
} else if ( this.get('isService') ) {
|
|
k += 'service';
|
|
} else {
|
|
k += 'container';
|
|
}
|
|
|
|
next(() => {
|
|
this.set('header', this.get('intl').t(k, args));
|
|
});
|
|
}.observes('isUpgrade','isService','isSidekick','isGlobal','service.displayName','intl.locale').on('init'),
|
|
|
|
supportsSecrets: function() {
|
|
return !!this.get('store').getById('schema','secret');
|
|
}.property(),
|
|
|
|
isSidekick: equal('mode','sidekick'),
|
|
});
|