diff --git a/app/admin-tab/settings/controller.js b/app/admin-tab/settings/controller.js index 908acafae..e6b573c6c 100644 --- a/app/admin-tab/settings/controller.js +++ b/app/admin-tab/settings/controller.js @@ -3,6 +3,7 @@ import C from 'ui/utils/constants'; export default Ember.Controller.extend({ settings: Ember.inject.service(), + projects: Ember.inject.service(), queryParams: ['backToAdd'], backToAdd: false, @@ -30,7 +31,6 @@ export default Ember.Controller.extend({ } if (this.get('backToAdd')) { - propsOut[C.SETTING.API_HOST] = model.host; } else { @@ -59,7 +59,7 @@ export default Ember.Controller.extend({ if (this.get('backToAdd')) { - this.transitionToRoute('hosts.new'); + this.transitionToRoute('hosts.new', this.get('projects.current.id')); } else { this.send('goToPrevious'); diff --git a/app/authenticated/controller.js b/app/authenticated/controller.js index ece0bc29d..f7d10eb87 100644 --- a/app/authenticated/controller.js +++ b/app/authenticated/controller.js @@ -11,4 +11,13 @@ export default Ember.Controller.extend({ hasKubernetes: false, hasSystem: false, hasVm: Ember.computed.alias('settings.hasVm'), + + init() { + this._super(); + this.k8sChanged(); + }, + + k8sChanged: function() { + this.set('hasKubernetes', !!this.get('projects.current.kubernetes')); + }.observes('projects.current.kubernetes'), }); diff --git a/app/authenticated/index/route.js b/app/authenticated/index/route.js index 0bf0efef3..10c8e569b 100644 --- a/app/authenticated/index/route.js +++ b/app/authenticated/index/route.js @@ -4,14 +4,11 @@ export default Ember.Route.extend({ projects: Ember.inject.service(), redirect() { - this.get('projects').selectDefault().then((project) => { - if ( project ) { - this.replaceWith('authenticated.project', project.get('id')); - } else { - this.replaceWith('settings.projects'); - } - }).catch(() => { + var project = this.get('projects.current'); + if ( project ) { + this.replaceWith('authenticated.project', project.get('id')); + } else { this.replaceWith('settings.projects'); - }); + } }, }); diff --git a/app/authenticated/project/route.js b/app/authenticated/project/route.js index b14ae86ba..cad82bf47 100644 --- a/app/authenticated/project/route.js +++ b/app/authenticated/project/route.js @@ -1,50 +1,31 @@ import Ember from 'ember'; -import Socket from 'ui/utils/socket'; -import Util from 'ui/utils/util'; -import C from 'ui/utils/constants'; import { hasThings } from 'ui/authenticated/project/controller'; export default Ember.Route.extend({ - k8s : Ember.inject.service(), - prefs : Ember.inject.service(), - projects : Ember.inject.service(), access : Ember.inject.service(), - userTheme : Ember.inject.service('user-theme'), - - socket : null, - pingTimer : null, - k8sUidBlacklist: null, model(params, transition) { - if ( !params.project_id ) + var project = this.modelFor('authenticated').project; + if ( !project ) { - // If there isn't a project, pick one - return this.get('projects').selectDefault().then((project) => { - if ( project ) - { - this.replaceWith('authenticated.project', project.get('id')); - } - else - { - this.replaceWith('settings.projects'); - } - }).catch(() => { - this.replaceWith('settings.projects'); - }); + this.replaceWith('settings.projects'); + return; } - return this.loadProject(params.project_id).then((project) => { - this.set(`tab-session.${C.TABSESSION.PROJECT}`, project.get('id')); - this.get('projects').setCurrent(project); + // If the project ID in the URL is out of sync somehow, bail + if ( project.get('id') !== params.project_id ) + { + this.replaceWith('authenticated'); + return; + } - return this.loadSchemas().then(() => { - return this.loadStacks().then((stacks) => { - hasThings(stacks, project, window.lc('authenticated')); + return this.loadSchemas().then(() => { + return this.loadStacks().then((stacks) => { + hasThings(stacks, project, window.lc('authenticated')); - return Ember.Object.create({ - project: project, - stacks: stacks, - }); + return Ember.Object.create({ + project: project, + stacks: stacks, }); }); }).catch((err) => { @@ -65,10 +46,6 @@ export default Ember.Route.extend({ return ret; }, - loadProject(id) { - return this.get('store').find('project', id); - }, - loadSchemas() { var store = this.get('store'); store.resetType('schema'); @@ -79,345 +56,4 @@ export default Ember.Route.extend({ return this.get('store').findAllUnremoved('environment'); }, - activate() { - this._super(); - - console.log('Activate socket for', this.get(`tab-session.${C.TABSESSION.PROJECT}`)); - var store = this.get('store'); - var boundTypeify = store._typeify.bind(store); - - if ( !this.get('k8sUidBlacklist') ) - { - this.set('k8sUidBlacklist', []); - } - - var url = "ws://"+window.location.host + this.get('app.wsEndpoint'); - - url = Util.addQueryParam(url, 'projectId', this.get(`tab-session.${C.TABSESSION.PROJECT}`)); - var socket = Socket.create({ - url: url - }); - this.set('socket', socket); - - socket.on('message', (event) => { - var d = JSON.parse(event.data, boundTypeify); - //this._trySend('subscribeMessage',d); - - if ( d.name === 'resource.change' ) - { - this._trySend(d.resourceType+'Changed', d); - } - else if ( d.name === 'service.kubernetes.change' ) - { - var changeType = (Ember.get(d, 'data.type')||'').toLowerCase(); - var obj = Ember.get(d, 'data.object'); - if ( changeType && obj ) - { - this._trySend('k8sResourceChanged', changeType, obj); - } - } - else if ( d.name === 'ping' ) - { - this._trySend('subscribePing', d); - } - }); - - socket.on('connected', (tries, after) => { - this._trySend('subscribeConnected', tries, after); - }); - - socket.on('disconnected', () => { - this._trySend('subscribeDisconnected', this.get('tries')); - }); - - socket.connect(); - }, - - deactivate() { - this._super(); - this.closeSocket(); - }, - - resetController() { - this._super(); - this.closeSocket(); - }, - - closeSocket() { - var socket = this.get('socket'); - if ( socket ) - { - socket.disconnect(); - this.set('socket', null); - } - - Ember.run.cancel(this.get('pingTimer')); - }, - - actions: { - // Raw message from the WebSocket - //subscribeMessage: function(/*data*/) { - //console.log('subscribeMessage',data); - //}, - - // WebSocket connected - subscribeConnected: function(tries,msec) { - var msg = 'Subscribe connected'; - if (tries > 0) - { - msg += ' (after '+ tries + ' ' + (tries === 1 ? 'try' : 'tries'); - if (msec) - { - msg += ', ' + (msec/1000) + ' sec'; - } - - msg += ')'; - } - console.log(msg); - }, - - // WebSocket disconnected - subscribeDisconnected: function() { - console.log('Subscribe disconnected'); - this.closeSocket(); - }, - - subscribePing: function() { - console.log('Subscribe ping'); - if ( this.get('pingTimer') ) - { - Ember.run.cancel(this.get('pingTimer')); - } - - this.set('pingTimer', Ember.run.later(this, function() { - console.log('Subscribe missed 2 pings...'); - if ( this.get('socket') ) - { - this.get('socket').connect(); - } - }, 11000)); - }, - - hostChanged: function(change) { - // If the host has a physicalHostId, ensure it is in the machine's hosts array. - var host = change.data.resource; - var machine = this.get('store').getById('machine', host.get('physicalHostId')); - if ( machine ) - { - machine.get('hosts').addObject(host); - } - }, - - containerChanged: function(change) { - this._includeChanged('host', 'instances', 'hosts', change.data.resource); - }, - - virtualMachineChanged: function(change) { - this._includeChanged('host', 'instances', 'hosts', change.data.resource); - }, - - instanceChanged: function(change) { - this._includeChanged('host', 'instances', 'hosts', change.data.resource); - }, - - ipAddressChanged: function(change) { - this._includeChanged('host', 'ipAddresses', 'hosts', change.data.resource); -// this._includeChanged('container', 'container', 'ipAddresses', 'containers', change.data.resource); - }, - - loadBalancerTargetChanged: function(change) { - this._includeChanged('loadBalancer', 'loadBalancerTargets', 'loadBalancerId', change.data.resource); - }, - - loadBalancerChanged: function(change) { - var balancer = change.data.resource; - var config = balancer.get('loadBalancerConfig'); - var balancers = config.get('loadBalancers'); - if ( !balancers ) - { - balancers = []; - config.set('loadBalancers',balancers); - } - - if ( config.get('state') === 'removed' ) - { - balancers.removeObject(balancer); - } - else - { - balancers.addObject(balancer); - } - }, - - mountChanged: function(change) { - var mount = change.data.resource; - var volume = this.get('store').getById('volume', mount.get('volumeId')); - if ( volume ) - { - var mounts = volume.get('mounts'); - if ( !Ember.isArray(mounts) ) - { - mounts = []; - volume.set('mounts',mounts); - } - - var existingMount = mounts.filterBy('id', mount.get('id')).get('firstObject'); - if ( existingMount ) - { - existingMount.setProperties(mount); - } - else - { - mounts.pushObject(mount); - } - } - }, - - registryCredentialChanged: function(change) { - this._includeChanged('registry', 'credentials', 'registryId', change.data.resource); - }, - - loadBalancerServiceChanged: function(change) { - this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - }, - - dnsServiceChanged: function(change) { - this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - }, - - externalServiceChanged: function(change) { - this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - }, - - serviceChanged: function(change) { - this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - }, - - kubernetesServiceChanged: function(change) { - this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - }, - - k8sResourceChanged: function(changeType, obj) { - //console.log('k8s change', changeType, (obj && obj.metadata && obj.metadata.uid ? obj.metadata.uid : 'none')); - if ( obj && obj.metadata && obj.metadata.uid && this.get('k8sUidBlacklist').indexOf(obj.metadata.uid) >= 0 ) - { - //console.log('^-- Ignoring', changeType, 'for removed resource'); - return; - } - - var resource = this.get('k8s')._typeify(obj); - - if ( changeType === 'deleted' ) - { - this.get('k8sUidBlacklist').pushObject(obj.metadata.uid); - this.get('store')._remove(resource.get('type'), resource); - } - } - }, - - _trySend: function(/*arguments*/) { - try - { - this.send.apply(this,arguments); - } - catch (err) - { - if ( err instanceof Ember.Error && err.message.indexOf('Nothing handled the action') === 0 ) - { - // Don't care - } - else - { - throw err; - } - } - }, - - - // Update the `?include=`-ed arrays of a host, - // e.g. when an instance changes: - // Update the destProperty='instances' array on all models of type resourceName='hosts'. - // to match the list in the the 'changed' resource's expectedProperty='hosts' - // _includeChanged( 'host', 'hosts', 'instances', 'hosts', instance) - _includeChanged: function(resourceName, destProperty, expectedProperty, changed) { - if (!changed) - { - return; - } - - var changedId = changed.get('id'); - var store = this.get('store'); - - //console.log('Include changed',resourceName,destProperty,expectedProperty,changedId); - - // All the resources - var all = store.all(resourceName); - - // IDs the resource should be on - var expectedIds = []; - var expected = changed.get(expectedProperty)||[]; - if ( !Ember.isArray(expected) ) - { - expected = [expected]; - } - - if ( changed.get('state') !== 'purged' ) - { - expectedIds = expected.map(function(item) { - if ( typeof item === 'object' ) - { - return item.get('id'); - } - else - { - return item; - } - }); - } - - // IDs it is currently on - var curIds = []; - all.forEach(function(item) { - var existing = (item.get(destProperty)||[]).filterBy('id', changedId); - if ( existing.length ) - { - curIds.push(item.get('id')); - } - }); - - // Remove from resources the changed shouldn't be on - var remove = Util.arrayDiff(curIds, expectedIds); - remove.forEach((id) => { - //console.log('Remove',id); - store.find(resourceName, id).then((item) => { - var list = item.get(destProperty); - if ( list ) - { - //console.log('Removing',changedId,'from',item.get('id')); - list.removeObjects(list.filterBy('id', changedId)); - } - }).catch(() => {}); - }); - - // Add or update resources the changed should be on - expectedIds.forEach((id) => { - //console.log('Expect',id); - store.find(resourceName, id).then((item) => { - var list = item.get(destProperty); - if ( !list ) - { - list = []; - //console.log('Adding empty to',item.get('id'), destProperty); - item.set(destProperty, list); - } - - var existing = list.filterBy('id', changedId); - if ( existing.length === 0) - { - //console.log('Adding',changedId,'to',item.get('id'), destProperty); - list.pushObject(changed); - } - }).catch(() => {}); - }); - }, }); diff --git a/app/authenticated/route.js b/app/authenticated/route.js index 03355b509..74bce7a1f 100644 --- a/app/authenticated/route.js +++ b/app/authenticated/route.js @@ -1,8 +1,9 @@ import Ember from 'ember'; import C from 'ui/utils/constants'; import Service from 'ui/models/service'; +import Subscribe from 'ui/mixins/subscribe'; -export default Ember.Route.extend({ +export default Ember.Route.extend(Subscribe, { prefs : Ember.inject.service(), projects : Ember.inject.service(), k8s : Ember.inject.service(), @@ -29,26 +30,35 @@ export default Ember.Route.extend({ preferences: this.loadPreferences(), settings: this.loadPublicSettings(), }).then((hash) => { + var projectId = null; if ( transition.params && transition.params['authenticated.project'] && transition.params['authenticated.project'].project_id ) { - return hash; + projectId = transition.params['authenticated.project'].project_id; } - else - { - // If not going to a project-specific page, make sure a project is selected - return this.get('projects').selectDefault().then(() => { - return hash; + + // Make sure a valid project is selected + return this.get('projects').selectDefault(projectId).then((project) => { + hash.project = project; + return this.loadKubernetes(project, hash).then((out) => { + return Ember.Object.create(out); }); - } + }); }).catch((err) => { return this.loadingError(err, transition, Ember.Object.create({ projects: [], + project: null, })); }); }, + activate() { + this._super(); + this.connectSubscribe(); + }, + deactivate() { this._super(); + this.disconnectSubscribe(); // Forget all the things this.reset(); @@ -81,6 +91,36 @@ export default Ember.Route.extend({ }); }, + loadKubernetes(project, hash) { + hash = hash || {}; + + if ( !project.get('kubernetes') ) + { + hash.kubernetesReady = false; + return Ember.RSVP.resolve(hash); + } + + var svc = this.get('k8s'); + return svc.isReady().then((ready) => { + if ( ready ) + { + return this.get('k8s').allNamespaces().then((all) => { + return this.get('k8s').selectNamespace().then((ns) => { + hash.kubernetesReady = true; + hash.namespaces = all; + hash.namespace = ns; + return hash; + }); + }); + } + else + { + hash.kubernetesReady = false; + return Ember.RSVP.resolve(hash); + } + }); + }, + loadProjects() { var svc = this.get('projects'); return svc.getAll().then((all) => { @@ -126,6 +166,13 @@ export default Ember.Route.extend({ this.refresh(); }, + refreshKubernetes() { + var model = this.get('controller.model'); + this.loadKubernetes(model.get('project')).then((hash) => { + model.setProperties(hash); + }); + }, + switchNamespace(namespaceId) { var route = window.lc('application').get('currentRouteName'); var okRoutes = [ diff --git a/app/components/form-healthcheck/component.js b/app/components/form-healthcheck/component.js index 3c16a5a9c..47eb5c547 100644 --- a/app/components/form-healthcheck/component.js +++ b/app/components/form-healthcheck/component.js @@ -136,11 +136,13 @@ export default Ember.Component.extend({ var requestLine=''; if ( path ) { - requestLine = method + ' ' + path + ' ' + version; + requestLine = method + ' ' + path + ' "' + version; if ( host ) { - requestLine += '\r\nHost:\\ ' + host; + requestLine += '\r\nHost: ' + host; } + + requestLine += '"'; } this.set('healthCheck.requestLine', requestLine); } diff --git a/app/components/page-header/template.hbs b/app/components/page-header/template.hbs index ef5eed1ec..2b94f2e2d 100644 --- a/app/components/page-header/template.hbs +++ b/app/components/page-header/template.hbs @@ -119,7 +119,7 @@ {{/if}} - {{#if isKubernetesTab}} + {{#if (and isKubernetesTab k8s.namespace)}}