berlioz
Version:
Berlioz - cloud deployment and migration services
389 lines (334 loc) • 13.4 kB
JavaScript
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;