import Ember from 'ember'; import NewOrEdit from 'ui/mixins/new-or-edit'; import SelectTab from 'ui/mixins/select-tab'; import { debouncedObserver } from 'ui/utils/debounce'; import C from 'ui/utils/constants'; import { flattenLabelArrays } from 'ui/mixins/manage-labels'; import Util from 'ui/utils/util'; function displayConfigName(name,isSidekick,idx) { if ( name ) { return name; } else if ( isSidekick ) { return '(Sidekick #' + (idx+1) + ')'; } else { return '(Primary)'; } } export default Ember.Component.extend(NewOrEdit, SelectTab, { intl : Ember.inject.service(), settings : Ember.inject.service(), tagName: 'form', isService: false, isUpgrade: false, //primaryResource: Ember.computed.alias('launchConfig'), primaryService: null, launchConfig: null, service: null, allHosts: null, allStoragePools: null, stack: null, count: 1, serviceLinksArray: null, isRequestedHost: null, portsAsStrArray: null, launchConfigIndex: -1, upgradeOptions: null, // Errors from components commandErrors: null, volumeErrors: null, networkingErrors: null, secretsErrors: null, healthCheckErrors: null, schedulingErrors: null, securityErrors: null, scaleErrors: null, imageErrors: null, portErrors: null, diskErrors: null, stackErrors: null, actions: { setScale(scale) { if ( this.get('isService') ) { this.set('service.scale', scale); } else { this.set('launchConfig.count', scale); } }, setImage(uuid) { this.set('launchConfig.imageUuid', uuid); }, setLabels(section,labels) { this.set(section+'Labels', labels); }, setRequestedHostId(hostId) { this.set('launchConfig.requestedHostId', hostId); }, setServiceLinks(links) { this.set('serviceLinksArray', links); }, 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. if ( this.get('service') ) { this.set('service.completeLaunchConfigs', true); } if ( !this.get('launchConfig.secrets') ) { this.set('launchConfig.secrets', []); } this.labelsChanged(); }, didInsertElement() { this.$("INPUT[type='text']")[0].focus(); }, // ---------------------------------- // Sidekicks // ---------------------------------- hasSidekicks: function() { return this.get('service.secondaryLaunchConfigs.length') > 0; }.property('service.secondaryLaunchConfigs.length'), launchConfigChoices: function() { var isUpgrade = this.get('isUpgrade'); let intl = this.get('intl'); // Enabled is only for upgrade, and isn't maintained if the names change, but they can't on upgrade. var out = [ { index: -1, name: this.get('service.name') || intl.t('newContainer.emptyPrimaryService'), enabled: true } ]; (this.get('service.secondaryLaunchConfigs')||[]).forEach((item, index) => { out.push({ index: index, name: item.get('name') || intl.t('newContainer.emptySidekick', {num: index+1}), enabled: !isUpgrade, uiId: item.get('uiId'), }); }); return out; }.property('service.name','service.secondaryLaunchConfigs.@each.name','intl.locale'), noLaunchConfigsEnabled: function() { return this.get('launchConfigChoices').filterBy('enabled',true).get('length') === 0; }.property('launchConfigChoices.@each.enabled'), // ---------------------------------- // 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); } } ), // ---------------------------------- // Disks // ---------------------------------- storageDriverChoices: function() { return (this.get('allStoragePools')||[]) .map((pool) => { return pool.get('driverName'); }) .filter((name) => { return C.VM_CAPABLE_STORAGE_DRIVERS.indexOf(name) >= 0; }) .uniq() .sort(); }.property('allStoragePools.@each.driverName'), // ---------------------------------- // Save // ---------------------------------- validate() { this._super(); var errors = this.get('errors')||[]; 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('diskErrors')||[]); errors.pushObjects(this.get('stackErrors')||[]); errors = errors.uniq(); if ( errors.get('length') ) { this.set('errors', errors); return false; } this.set('errors', null); return true; }, willSave() { let ok = this._super(...arguments); if ( ok && !this.get('isUpgrade') ) { this.set('primaryResource.completeUpdate', true); // Set the stack ID if ( this.get('stack.id') ) { this.set('primaryResource.stackId', this.get('stack.id')); return true; } else if ( this.get('stack') ) { return this.get('stack').save().then((newStack) => { this.set('primaryResource.stackId', newStack.get('id')); return true; }); } } return ok; }, doSave() { if ( this.get('isService') || !this.get('isUpgrade') ) { return this._super(...arguments); } // Container upgrade return this.get('primaryResource').doAction('upgrade', { config: this.get('primaryResource') }); }, didSave() { if ( this.get('isService') ) { // Returns a promise return this.setServiceLinks(); } }, setServiceLinks() { var service = this.get('service'); var ary = []; this.get('serviceLinksArray').forEach((row) => { if ( row.serviceId ) { ary.push({name: row.name, serviceId: row.serviceId}); } }); return service.doAction('setservicelinks', {serviceLinks: ary}); }, doneSaving() { this.sendAction('done'); }, headerToken: function() { let k = 'newContainer.'; k += (this.get('isUpgrade') ? 'upgrade' : 'add') + '.'; if ( this.get('isSidekick') ) { k += 'sidekick'; } else if ( this.get('isService') ) { k += 'scalingGroup'; } else { k += 'container'; } return k; }.property('isUpgrade','isService'), configName: function() { let name = this.get('primaryResource.name'); let isSidekick = this.get('isSidekick'); let idx = this.get('launchConfigIndex'); return displayConfigName(name,isSidekick,idx); }.property('primaryResource.name','launchConfigIndex','isSidekick'), slcWithNames: function() { let out = []; out.pushObjects(this.get('service.secondaryLaunchConfigs').map((x, idx) => { return { displayName: displayConfigName(x.get('name'), true, idx), slc: x }; })); return out; }.property('primaryResource.name','service.secondaryLaunchConfigs.@each.name'), supportsSecrets: function() { return !!this.get('store').getById('schema','secret'); }.property(), });