diff --git a/ui/packages/consul-ui/app/serializers/service.js b/ui/packages/consul-ui/app/serializers/service.js index 9caa9b2cd..f8871fb18 100644 --- a/ui/packages/consul-ui/app/serializers/service.js +++ b/ui/packages/consul-ui/app/serializers/service.js @@ -1,6 +1,10 @@ import Serializer from './application'; import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/service'; import { get } from '@ember/object'; +import { + HEADERS_NAMESPACE as HTTP_HEADERS_NAMESPACE, + HEADERS_PARTITION as HTTP_HEADERS_PARTITION, +} from 'consul-ui/utils/http/consul'; export default class ServiceSerializer extends Serializer { primaryKey = PRIMARY_KEY; @@ -13,31 +17,7 @@ export default class ServiceSerializer extends Serializer { // Services and proxies all come together in the same list. Here we // map the proxies to their related services on a Service.Proxy // property for easy access later on - const services = {}; - body - .filter(function (item) { - return item.Kind !== 'connect-proxy'; - }) - .forEach((item) => { - services[item.Name] = item; - }); - body - .filter(function (item) { - return item.Kind === 'connect-proxy'; - }) - .forEach((item) => { - // Iterating to cover the usecase of a proxy being used by more - // than one service - if (item.ProxyFor) { - item.ProxyFor.forEach((service) => { - if (typeof services[service] !== 'undefined') { - services[service].Proxy = item; - } - }); - } - }); - - return cb(headers, body); + return cb(headers, this._transformServicesPayload(body)); }), query ); @@ -58,4 +38,56 @@ export default class ServiceSerializer extends Serializer { query ); } + + createJSONApiDocumentFromServicesPayload(headers, responseBody, dc) { + const { primaryKey, slugKey, fingerprint } = this; + + const transformedBody = this._transformServicesPayload(responseBody); + const attributes = transformedBody.map( + fingerprint( + primaryKey, + slugKey, + dc, + headers[HTTP_HEADERS_NAMESPACE], + headers[HTTP_HEADERS_PARTITION] + ) + ); + + return { + data: attributes.map((attr) => { + return { + id: attr.uid, + type: 'service', + attributes: attr, + }; + }), + }; + } + + _transformServicesPayload(body) { + const services = {}; + body + .filter(function (item) { + return item.Kind !== 'connect-proxy'; + }) + .forEach((item) => { + services[item.Name] = item; + }); + body + .filter(function (item) { + return item.Kind === 'connect-proxy'; + }) + .forEach((item) => { + // Iterating to cover the usecase of a proxy being used by more + // than one service + if (item.ProxyFor) { + item.ProxyFor.forEach((service) => { + if (typeof services[service] !== 'undefined') { + services[service].Proxy = item; + } + }); + } + }); + return body; + } } diff --git a/ui/packages/consul-ui/app/services/repository/peer.js b/ui/packages/consul-ui/app/services/repository/peer.js index b65027854..c177f2448 100644 --- a/ui/packages/consul-ui/app/services/repository/peer.js +++ b/ui/packages/consul-ui/app/services/repository/peer.js @@ -1,5 +1,6 @@ import RepositoryService from 'consul-ui/services/repository'; import dataSource from 'consul-ui/decorators/data-source'; +import { inject as service } from '@ember/service'; function normalizePeerPayload(peerPayload, dc, partition) { const { @@ -18,10 +19,31 @@ function normalizePeerPayload(peerPayload, dc, partition) { }; } export default class PeerService extends RepositoryService { + @service store; + getModelName() { return 'peer'; } + @dataSource('/:partition/:ns/:ds/exported-services/:name') + async fetchExportedServices({ dc, ns, partition, name }, configuration, request) { + return ( + await request` + GET /v1/internal/ui/exported-services + + ${{ + peer: name, + }} + ` + )((headers, body, cache) => { + const serviceSerializer = this.store.serializerFor('service'); + + return this.store.push( + serviceSerializer.createJSONApiDocumentFromServicesPayload(headers, body, dc) + ); + }); + } + @dataSource('/:partition/:ns/:dc/peering/token-for/:name') async fetchToken({ dc, ns, partition, name }, configuration, request) { return (