UNPKG

berlioz

Version:

Berlioz - cloud deployment and migration services

389 lines (334 loc) 13.4 kB
const Promise = require("the-promise"); const _ = require("the-lodash"); const TableFetcher = require("./table-fetcher"); class PeersFetcher { constructor(logger, tableImpl, scope) { this._tables = {}; this._logger = logger; this._rootScope = scope; this._logger.info("[constructor] root scope: ", this._rootScope); this._fetchers = {} this._fetchers["public"] = new TableFetcher(logger.sublogger("TableFetcher"), "final_endpoints_public", tableImpl); this._fetchers["internal"] = new TableFetcher(logger.sublogger("TableFetcher"), "final_endpoints_internal", tableImpl); this._fetchers["consumer-meta"] = new TableFetcher(logger.sublogger("TableFetcher"), "consumer_meta", tableImpl); this._fetchers["provider-meta"] = new TableFetcher(logger.sublogger("TableFetcher"), "provider_meta", tableImpl); this._endpoints = {}; this._consumerMetas = {}; this._providerMetas = {}; } prefetchClusterDependencies(clusterEntity) { this._logger.info("[prefetchClusterDependencies] %s", clusterEntity.id); return Promise.resolve() .then(() => this._prefetchProviderMetas(clusterEntity)) .then(() => Promise.serial(clusterEntity.services, x => this._prefetchServiceDependencies(x))) .then(() => { this._logger.info("[prefetchClusterDependencies] Peers: ", this._endpoints); this._logger.info("[prefetchClusterDependencies] Consumer Metas: ", this._consumerMetas); this._logger.info("[prefetchClusterDependencies] Provider Metas: ", this._providerMetas); // this._logger.info("[prefetchClusterDependencies] VPC Connections: ", this.getVpcConnections()); }) } prefetchClusterPublicEndpoints(clusterEntity) { this._logger.info("[prefetchClusterPublicEndpoints] %s", clusterEntity.id); var scope = {cluster: clusterEntity.name}; return this._prefetchService('public', scope); } prefetchClusterPublicProvides(clusterProvided) { this._logger.info("[_prefetchClusterProvides] %s", clusterProvided.id); var serviceId = [clusterProvided.cluster.id, clusterProvided.name].join('-'); var scope = {service: serviceId}; return this._prefetchService('public', scope); } _prefetchServiceDependencies(serviceEntity) { this._logger.info("[_prefetchServiceDependencies] %s", serviceEntity.id); return Promise.resolve() .then(() => Promise.serial(_.values(serviceEntity.provides), x => this._prefetchServiceProvided(x))) .then(() => Promise.serial(serviceEntity.consumes, x => this._prefetchConsumedEndpoint(x))) .then(() => Promise.serial(serviceEntity.databasesConsumes, x => this._prefetchConsumedNative(x))) .then(() => Promise.serial(serviceEntity.queuesConsumes, x => this._prefetchConsumedNative(x))) } getServiceProvidedConsumerMetas(serviceProvided) { this._logger.info("[getServiceProvidedConsumerMetas] %s ... ", serviceProvided.id); if (serviceProvided.id in this._consumerMetas) { return this._consumerMetas[serviceProvided.id]; } return []; } _prefetchProviderMetas(clusterEntity) { this._logger.info("[_prefetchProviderMetas] %s ...", clusterEntity.id); var info; if (this._rootScope) { info = _.clone(this._rootScope); info.consumerRegion = this._rootScope.region; delete info.region; } else { info = {}; } info.consumerCluster = clusterEntity.name; this._logger.info("[_prefetchProviderMetas] %s :: ", clusterEntity.id, info); return Promise.resolve() .then(() => { return this._fetchers["provider-meta"].query(info); }) .then(results => { for(var x of _.keys(results)) { this._providerMetas[x] = results[x]; } }); } _prefetchServiceProvided(serviceProvided) { this._logger.info("[_prefetchServiceProvided] %s", serviceProvided.id); var info = { providerCluster: serviceProvided.service.clusterName, providerService: serviceProvided.service.id, providerEndpoint: serviceProvided.name, } return Promise.resolve() .then(() => this._prefetchConsumerMeta(serviceProvided, info)) .then(() => { var clusterProvided = serviceProvided.clusterProvided; if (clusterProvided) { var clusterProvInfo = { providerCluster: clusterProvided.cluster.name, providerService: clusterProvided.cluster.id, providerEndpoint: clusterProvided.name, } return this._prefetchConsumerMeta(serviceProvided, clusterProvInfo) } }) // .then(() => { // var consumers = this._consumerMetas[serviceProvided.id]; // consumers = _.uniqBy(consumers, _.stableStringify); // this._consumerMetas[serviceProvided.id] = consumers; // }); } _prefetchConsumerMeta(providerEntity, info) { if (this._rootScope) { info = _.defaults(info, this._rootScope); } this._logger.info("[_prefetchConsumerMeta] ", info); return Promise.resolve() .then(() => { return this._fetchers["consumer-meta"].query(info); }) .then(result => { this._logger.info("[_prefetchConsumerMeta] result:", result); var consumers = []; if (result) { consumers = _.values(result); // consumers = consumers.map(x => x.info); } if (providerEntity.id in this._consumerMetas) { consumers = _.concat(this._consumerMetas[providerEntity.id], consumers); } this._consumerMetas[providerEntity.id] = consumers; }) } _prefetchConsumedEndpoint(consumedEndpoint) { this._logger.info("[_prefetchConsumedEndpoint] %s", consumedEndpoint.id); var serviceId = [consumedEndpoint.targetId, consumedEndpoint.targetEndpoint].join('-'); var scope = {service: serviceId}; if (consumedEndpoint.targetKind == 'service') { return this._prefetchService('internal', scope); } if (consumedEndpoint.targetKind == 'cluster') { return this._prefetchService('internal', scope); } } _prefetchConsumedNative(consumedNative) { this._logger.info("[_prefetchConsumedNative] %s", consumedNative.id); var serviceId = [consumedNative.targetId].join('-'); var scope = {service: serviceId}; return this._prefetchService('internal', scope); } _prefetchService(location, scope) { var actualScope = _.clone(scope); if (this._rootScope) { actualScope = _.defaults(actualScope, this._rootScope); } this._logger.info("[_prefetchService] %s :: ", location, actualScope); return Promise.resolve() .then(() => { return this._fetchers[location].query(actualScope); }) .then(result => { this._logger.info("[_prefetchService] peers result:", result); if (!result) { return; } for(var peer of _.values(result)) { if (!(this._endpoints[peer.service])) { this._endpoints[peer.service] = []; } this._endpoints[peer.service].push(peer); } }) } getConsumedEnvironment(serviceEntity) { // this._logger.info("[getConsumedEnvironment] %s ... ", serviceEntity.id); var env = {}; for (var consumed of serviceEntity.consumes) { this._getConsumedEnvironment(env, serviceEntity, consumed); } return env; } _getConsumedEnvironment(env, serviceEntity, consumed) { var peer = this.getConsumedEndpointPeer(consumed); if (peer) { env[this.getConsumedEnvVarName(serviceEntity, consumed, 'host')] = peer.address; env[this.getConsumedEnvVarName(serviceEntity, consumed, 'port')] = peer.port; if (this._peerHasUrl(peer)) { var url = `${peer.protocol}://${peer.address}:${peer.port}`; env[this.getConsumedEnvVarName(serviceEntity, consumed, 'url')] = url; } } } _peerHasUrl(peer) { if (peer.protocol) { if (peer.protocol == 'http' || peer.protocol == 'https' || peer.protocol == 'ws') { return true; } } return false; } getConsumedEnvVarName(serviceEntity, consumed, flavor) { var envNaming = ['berlioz', 'consumed']; envNaming.push(consumed.targetKind); if (consumed.targetKind == "service") { if (consumed.targetNaming[1] != serviceEntity.sectorName) { envNaming.push(consumed.targetNaming[1]); } if (consumed.targetNaming[2] != serviceEntity.name) { envNaming.push(consumed.targetNaming[2]); } } else if (consumed.targetKind == "cluster") { if (consumed.targetNaming[0] != serviceEntity.clusterName) { envNaming.push(consumed.targetNaming[0]); } } if (consumed.targetEndpoint != 'default') { envNaming.push(consumed.targetEndpoint); } if (flavor) { envNaming.push(flavor); } envNaming = envNaming.map(x => x.toUpperCase()); return envNaming.join("_"); } getMyPeers(serviceEntity) { this._logger.info("[getMyPeers] %s ... ", serviceEntity.id); var myPeerData = {}; for (var consumed of serviceEntity.consumes) { this._fillProvidedEndpointData(myPeerData, consumed); } for (var consumed of serviceEntity.databasesConsumes) { this._fillConsumedNativeEndpoint(myPeerData, consumed); } for (var consumed of serviceEntity.queuesConsumes) { this._fillConsumedNativeEndpoint(myPeerData, consumed); } return myPeerData; } getClusterPublicEndpoints(clusterProvided) { var serviceId = [clusterProvided.cluster.id, clusterProvided.name].join('-'); if (!(serviceId in this._endpoints)) { return {}; } var endpoints = this._endpoints[serviceId]; return _.makeDict(endpoints, x => x.identity, x => x.info); } getVpcConnections() { return _(this._providerMetas) .values() .map(x => x.info.vpcConnection) .uniq() .value(); } getServiceVpcConnections(serviceEntity) { return _(this._providerMetas) .values() .filter(x => x.consumerService == serviceEntity.id) .map(x => x.info) .uniq() .value(); } _fillProvidedEndpointData(myPeerData, consumedEndpoint) { var serviceId = [consumedEndpoint.targetId, consumedEndpoint.targetEndpoint].join("-"); myPeerData[serviceId] = this.getConsumedEndpointPeers(consumedEndpoint); } getConsumedEndpointPeer(consumedEndpoint) { var peerMap = this.getConsumedEndpointPeers(consumedEndpoint); var identities = _.keys(peerMap); if (identities.length == 0) { return null; } var peer = peerMap["0"]; if (peer) { return peer; } return peerMap[_.head(identities)]; } getConsumedEndpointPeers(consumedEndpoint) { var serviceId = [consumedEndpoint.targetId, consumedEndpoint.targetEndpoint].join("-"); if (serviceId in this._endpoints) { var peers = this._endpoints[serviceId]; return _.makeDict(peers, x => x.identity, x => x.info); } return {}; } _fillConsumedNativeEndpoint(myPeerData, consumedNative) { this._logger.info("[_fillConsumedNativeEndpoint] %s ... ", consumedNative.id); var serviceId = [consumedNative.targetId].join("-"); var peers; if (serviceId in this._endpoints) { peers = this._endpoints[serviceId]; } else { peers = []; } myPeerData[serviceId] = _.makeDict(peers, x => x.identity, x => x.info); } getHostNameFromParts(parts) { parts = parts.map(x => this._sanitizeHostNamePart(x)); var alias = parts.join("."); return alias; } _sanitizeHostNamePart(str) { str = _.replaceAll(str, '-', ''); str = _.replaceAll(str, '_', ''); return str; } } module.exports = PeersFetcher;