diff --git a/app/authenticated/route.js b/app/authenticated/route.js index b24886fb8..dd1d24101 100644 --- a/app/authenticated/route.js +++ b/app/authenticated/route.js @@ -347,26 +347,19 @@ export default Ember.Route.extend(AuthenticatedRouteMixin, { }, loadBalancerServiceChanged: function(change) { - var service = change.data.resource; this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - service.importLink('consumedservices'); + }, + + 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) { - var service = change.data.resource; this._includeChanged('environment', 'services', 'environmentId', change.data.resource); - - // Remove the service from depenedent services - if ( ['removed','purged','purging'].indexOf(service.get('state')) >= 0 ) - { - ['service','loadBalancerService','dnsService','externalService'].forEach((type) => { - this.get('store').all(type).forEach((otherService) => { - (otherService.get('consumedservices')||[]).removeObject(service); - }); - }); - } - - service.importLink('consumedservices'); }, }, diff --git a/app/components/service-pod/template.hbs b/app/components/service-pod/template.hbs index 814d3a04a..32a373da0 100644 --- a/app/components/service-pod/template.hbs +++ b/app/components/service-pod/template.hbs @@ -13,11 +13,22 @@ -{{#if (or model.consumedservices.length model.externalIpAddresses.length)}} +{{#if (or model.consumedServicesWithNames.length model.externalIpAddresses.length)}}
- {{#each item in model.consumedservices itemController="service"}} -
{{#link-to "service" item.environmentId item.id}} {{item.displayName}}{{/link-to}}
+ {{#each map in model.consumedServicesWithNames}} + {{#with map.service as service controller="service"}} +
+ {{#link-to "service" service.environmentId service.id}} + + {{#if (eq map.name service.displayName)}} + {{map.name}} + {{else}} + {{service.displayName}}{{#if map.name}} (as {{map.name}}){{/if}} + {{/if}} + {{/link-to}} +
+ {{/with}} {{/each}}
{{#if model.externalIpAddresses.length}} diff --git a/app/dnsservice/model.js b/app/dnsservice/model.js index 27fb00be8..267346ec8 100644 --- a/app/dnsservice/model.js +++ b/app/dnsservice/model.js @@ -1,35 +1,11 @@ -import Cattle from 'ui/utils/cattle'; +import Service from 'ui/service/model'; -var DnsService = Cattle.TransitioningResource.extend({ - type: 'service', - - consumedServicesUpdated: 0, - onConsumedServicesChanged: function() { - this.incrementProperty('consumedServicesUpdated'); - }.observes('consumedservices.@each.{id,name,state}'), +var DnsService = Service.extend({ + type: 'dnsService', healthState: function() { return 'healthy'; }.property(), - - combinedState: function() { - var service = this.get('state'); - var health = this.get('healthState'); - if ( ['active','updating-active'].indexOf(service) === -1 ) - { - // If the service isn't active, return its state - return service; - } - - if ( health === 'healthy' ) - { - return service; - } - else - { - return 'degraded'; - } - }.property('state', 'healthState'), }); DnsService.reopenClass({ diff --git a/app/environment/graph/view.js b/app/environment/graph/view.js index b0b85e90f..18ced379c 100644 --- a/app/environment/graph/view.js +++ b/app/environment/graph/view.js @@ -1,6 +1,7 @@ import Ember from 'ember'; import Util from 'ui/utils/util'; import ThrottledResize from 'ui/mixins/throttled-resize'; +import { activeIcon } from 'ui/service/controller'; export default Ember.View.extend(ThrottledResize,{ classNames: ['environment-graph'], @@ -72,7 +73,7 @@ export default Ember.View.extend(ThrottledResize,{ var color = (service.get('state') === 'active' ? 'green' : (service.get('state') === 'inactive' ? 'red' : 'yellow')); var instances = service.get('instances.length')||'No'; - var html = '' + + var html = '' + '

'+ Util.escapeHtml(service.get('name')) + '

' + '
' + instances + ' container' + (instances === 1 ? '' : 's') + '
' + '
' + Util.escapeHtml(Util.ucFirst(service.get('state'))) + '
'; @@ -89,15 +90,24 @@ export default Ember.View.extend(ThrottledResize,{ unremovedServices.forEach(function(service) { var serviceId = service.get('id'); - (service.get('consumedservices')||[]).map(function(target) { + (service.get('consumedServicesWithNames')||[]).map(function(map) { + var target = map.get('service'); var targetId = target.get('id'); var color = (target.get('state') === 'active' ? 'green' : (target.get('state') === 'inactive' ? 'red' : 'yellow')); - g.setEdge(serviceId, targetId, { + var edgeOpts = { arrowhead: 'vee', lineInterpolate: 'bundle', class: color, - }); + }; + + var mapName = map.get('name'); + if ( mapName && mapName !== target.get('name') ) + { + edgeOpts.label = mapName; + } + + g.setEdge(serviceId, targetId, edgeOpts); var existing = unexpectedEdges.filter(function(edge) { return edge.v === serviceId && edge.w === targetId; diff --git a/app/environment/route.js b/app/environment/route.js index 1527de74a..e74bfd828 100644 --- a/app/environment/route.js +++ b/app/environment/route.js @@ -8,9 +8,10 @@ export default Ember.Route.extend({ filter: { environmentId: env.get('id'), }, - include: ['consumedservices','instances'] + include: ['instances'] }).then((services) => { env.set('services', services||[]); + env.set('services.sortProperties', ['name','id']); return env; }); }); diff --git a/app/environments/route.js b/app/environments/route.js index 17806258a..35180b3c9 100644 --- a/app/environments/route.js +++ b/app/environments/route.js @@ -3,14 +3,21 @@ import Ember from 'ember'; export default Ember.Route.extend({ model: function() { var store = this.get('store'); - return store.findAllUnremoved('environment').then((environments) => { + + var promises = [ + store.findAllUnremoved('environment'), + ]; + + return Ember.RSVP.all(promises).then((results) => { + var environments = results[0]; + var promises = []; environments.forEach((env) => { var promise = store.find('service', null, { filter: { environmentId: env.get('id'), }, - include: ['consumedservices','instances'] + include: ['instances'] }).then((services) => { env.set('services', services||[]); env.set('services.sortProperties', ['name','id']); diff --git a/app/externalservice/model.js b/app/externalservice/model.js index 2b320b7db..f7f8f9097 100644 --- a/app/externalservice/model.js +++ b/app/externalservice/model.js @@ -1,35 +1,11 @@ -import Cattle from 'ui/utils/cattle'; +import Service from 'ui/service/model'; -var ExternalService = Cattle.TransitioningResource.extend({ - type: 'service', - - consumedServicesUpdated: 0, - onConsumedServicesChanged: function() { - this.incrementProperty('consumedServicesUpdated'); - }.observes('consumedservices.@each.{id,name,state}'), +var ExternalService = Service.extend({ + type: 'externalService', healthState: function() { return 'healthy'; }.property(), - - combinedState: function() { - var service = this.get('state'); - var health = this.get('healthState'); - if ( ['active','updating-active'].indexOf(service) === -1 ) - { - // If the service isn't active, return its state - return service; - } - - if ( health === 'healthy' ) - { - return service; - } - else - { - return 'degraded'; - } - }.property('state', 'healthState'), }); ExternalService.reopenClass({ diff --git a/app/mixins/edit-service.js b/app/mixins/edit-service.js index 210e18772..a6070703a 100644 --- a/app/mixins/edit-service.js +++ b/app/mixins/edit-service.js @@ -50,26 +50,27 @@ export default Ember.Mixin.create(EditLabels, { serviceLinksAsMap: null, initServiceLinks: function() { var out = []; - var links = this.get('service.consumedservices')||[]; + var links; + if ( this.get('service.id') ) + { + // Edit + links = this.get('service.consumedServicesWithNames')||[]; + } + else + { + // New / Clone + links = this.get('service.serviceLinks')||[]; + } - links.forEach(function(value) { - // Objects, from edit - var id; - if ( typeof value === 'object' ) - { - id = Ember.get(value,'id'); - if ( id ) - { - out.push(Ember.Object.create({ - obj: value, - serviceId: id, - })); - } - } - else - { - out.push(Ember.Object.create({serviceId: value})); - } + links.forEach(function(obj) { + var linkName = obj.get('name'); + var service = obj.get('service'); + + out.push(Ember.Object.create({ + linkName: (linkName === service.get('name') ? '' : linkName), + obj: service, + serviceId: service.get('id'), + })); }); this.set('serviceLinksArray', out); diff --git a/app/service/controller.js b/app/service/controller.js index acc1982cb..f5249a2e4 100644 --- a/app/service/controller.js +++ b/app/service/controller.js @@ -114,9 +114,13 @@ var ServiceController = Cattle.TransitioningResourceController.extend(ReadLabels }.property('type'), state: Ember.computed.alias('model.combinedState'), + + activeIcon: function() { + return activeIcon(this.get('model')); + }.property('type'), }); -function activeIcon(service) +export function activeIcon(service) { var out = 'ss-layergroup'; switch ( service.get('type').toLowerCase() ) diff --git a/app/service/model.js b/app/service/model.js index 77646e10b..1da3116a4 100644 --- a/app/service/model.js +++ b/app/service/model.js @@ -1,13 +1,85 @@ +import Ember from 'ember'; import Cattle from 'ui/utils/cattle'; import C from 'ui/utils/constants'; +var _allMaps; +var _allServices; +var _allLbServices; +var _allExternalServices; +var _allDnsServices; + var Service = Cattle.TransitioningResource.extend({ type: 'service', + _allMaps: null, consumedServicesUpdated: 0, + serviceLinks: null, // Used for clone + reservedKeys: ['_allMaps','consumedServicesUpdated','serviceLinks'], + + init: function() { + this._super(); + + // Hack: keep only one copy of all the services and serviceconsumemaps + // But you have to load service and serviceconsumemap beforehand somewhere... + // Bonus hack: all('services') doesn't include the other kinds of services, so load all those too. + if ( !_allMaps ) + { + _allMaps = this.get('store').allUnremoved('serviceconsumemap'); + } + + this.set('_allMaps', _allMaps); + + if ( !_allServices ) + { + _allServices = this.get('store').allUnremoved('service'); + } + + if ( !_allLbServices ) + { + _allLbServices = this.get('store').allUnremoved('loadbalancerservice'); + } + + if ( !_allExternalServices ) + { + _allExternalServices = this.get('store').allUnremoved('externalservice'); + } + + if ( !_allDnsServices ) + { + _allDnsServices = this.get('store').allUnremoved('dnsservice'); + } + }, + + consumedServicesWithNames: function() { + var all = [_allServices, _allLbServices, _allExternalServices, _allDnsServices]; + + return this.get('_allMaps').filterProperty('serviceId', this.get('id')).map((map) => { + var i = 0; + var service = null; + while ( i < all.length && !service ) + { + service = all[i].filterProperty('id', map.get('consumedServiceId'))[0]; + i++; + } + + return Ember.Object.create({ + name: map.get('name'), + service: service + }); + }).filter((obj) => { + return obj.get('service.id'); + }); + }.property('id','_allMaps.@each.{name,serviceId,consumedServiceId}'), + + consumedServices: function() { + return this.get('consumedServicesWithNames').map((obj) => { + return obj.get('service'); + }); + }.property('consumedServicesWithNames.@each.service'), + onConsumedServicesChanged: function() { this.incrementProperty('consumedServicesUpdated'); - }.observes('consumedservices.@each.{id,name,state}'), + }.observes('consumedServicesWithNames.@each.{name,service}'), healthState: function() { var isGlobal = Object.keys(this.get('labels')||{}).indexOf(C.LABEL.SCHED_GLOBAL) >= 0; diff --git a/app/service/new-alias/controller.js b/app/service/new-alias/controller.js index c1563e302..722cecf1d 100644 --- a/app/service/new-alias/controller.js +++ b/app/service/new-alias/controller.js @@ -34,7 +34,7 @@ export default Ember.ObjectController.extend(Cattle.NewOrEditMixin, { targetsArray: null, initTargets: function() { - var existing = this.get('dns.consumedservices'); + var existing = this.get('dns.consumedServices'); var out = []; if ( existing ) { diff --git a/app/service/new-alias/route.js b/app/service/new-alias/route.js index 8e29bff41..25fdb907d 100644 --- a/app/service/new-alias/route.js +++ b/app/service/new-alias/route.js @@ -13,7 +13,7 @@ export default Ember.Route.extend({ if ( params.serviceId ) { - dependencies.pushObject(store.find('service', params.serviceId, {include: ['consumedservices']})); + dependencies.pushObject(store.find('service', params.serviceId)); } return Ember.RSVP.all(dependencies, 'Load dependencies').then(function(results) { diff --git a/app/service/new-balancer/controller.js b/app/service/new-balancer/controller.js index 767cfe150..cb51cc51f 100644 --- a/app/service/new-balancer/controller.js +++ b/app/service/new-balancer/controller.js @@ -45,7 +45,7 @@ export default Ember.ObjectController.extend(Cattle.NewOrEditMixin, EditLoadBala targetsArray: null, initTargets: function() { - var existing = this.get('balancer.consumedservices'); + var existing = this.get('balancer.consumedServices'); var out = []; if ( existing ) { diff --git a/app/service/new-balancer/route.js b/app/service/new-balancer/route.js index 83b29fad2..a8ceee4f3 100644 --- a/app/service/new-balancer/route.js +++ b/app/service/new-balancer/route.js @@ -13,7 +13,7 @@ export default Ember.Route.extend({ if ( params.serviceId ) { - dependencies.pushObject(store.find('service', params.serviceId, {include: ['loadbalancerlisteners','consumedservices']})); + dependencies.pushObject(store.find('service', params.serviceId, {include: ['loadbalancerlisteners']})); } return Ember.RSVP.all(dependencies, 'Load dependencies').then(function(results) { diff --git a/app/service/new/route.js b/app/service/new/route.js index deab83da0..468405161 100644 --- a/app/service/new/route.js +++ b/app/service/new/route.js @@ -30,6 +30,7 @@ export default Ember.Route.extend({ var allHosts = results[0]; var environment = results[1]; var serviceOrContainer = results[2]; + var serviceLinks = []; var instanceData, serviceData, healthCheckData; if ( serviceOrContainer ) @@ -37,6 +38,7 @@ export default Ember.Route.extend({ if ( serviceOrContainer.get('type') === 'service' ) { serviceData = serviceOrContainer.serializeForNew(); + serviceLinks = serviceOrContainer.get('consumedServicesWithNames'); instanceData = serviceData.launchConfig; delete serviceData.launchConfig; delete serviceData.instances; @@ -80,7 +82,10 @@ export default Ember.Route.extend({ } var instance = this.get('store').createRecord(instanceData); + var service = store.createRecord(serviceData); + service.set('serviceLinks', serviceLinks); + var healthCheck = store.createRecord(healthCheckData); instance.set('healthCheck', healthCheck); service.set('launchConfig', instance); // Creating a service needs the isntance definition here diff --git a/app/serviceconsumemap/model.js b/app/serviceconsumemap/model.js new file mode 100644 index 000000000..eab77c498 --- /dev/null +++ b/app/serviceconsumemap/model.js @@ -0,0 +1,10 @@ +import Cattle from 'ui/utils/cattle'; + +var ServiceConsumeMap = Cattle.TransitioningResource.extend({ + type: 'serviceConsumeMap', +}); + +ServiceConsumeMap.reopenClass({ +}); + +export default ServiceConsumeMap; diff --git a/app/services/route.js b/app/services/route.js new file mode 100644 index 000000000..215e9f9ca --- /dev/null +++ b/app/services/route.js @@ -0,0 +1,12 @@ +import Ember from 'ember'; + +export default Ember.Route.extend({ + model: function() { + var store = this.get('store'); + return Ember.RSVP.all([ + store.findAllUnremoved('environment'), + store.findAllUnremoved('service'), + store.findAllUnremoved('serviceconsumemap'), + ]); + } +}); diff --git a/config/environment.js b/config/environment.js index a5b6b6d54..5ff48d1da 100644 --- a/config/environment.js +++ b/config/environment.js @@ -49,7 +49,6 @@ module.exports = function(environment) { '&include=loadBalancerTargets' + '&include=loadBalancerListeners' + '&include=instanceLinks' + - '&include=consumedservices' + '&include=ipAddresses', baseAssets: '', }, diff --git a/package.json b/package.json index ac5e40d45..5a3a81e3a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ui", - "version": "0.25.0", + "version": "0.26.0", "private": true, "directories": { "doc": "doc",