120 lines
3.4 KiB
JavaScript
120 lines
3.4 KiB
JavaScript
|
'use strict';
|
||
|
|
||
|
const fs = require('fs');
|
||
|
const assert = require('assert');
|
||
|
const path = require('path');
|
||
|
const debug = require('debug')('xsenv');
|
||
|
|
||
|
const DEFAULT_SECRETS_PATH = '/etc/secrets/sapcp/';
|
||
|
const NodeCache = require('node-cache');
|
||
|
const k8sSecretsCache = new NodeCache({ stdTTL: 9 * 60 });
|
||
|
|
||
|
exports.readK8SServices = readK8SServices;
|
||
|
|
||
|
const isFile = filePath => fs.statSync(filePath).isFile();
|
||
|
const isDirectory = dirPath => fs.statSync(dirPath).isDirectory();
|
||
|
|
||
|
function isJsonObject(str) {
|
||
|
// Also consider the case in which the file is written by hand:
|
||
|
// allow new lines and trailing whitespaces.
|
||
|
return /^{(.|\r?\n?)*}(\s)*$/.test(str);
|
||
|
}
|
||
|
|
||
|
function readFileContent(filePath) {
|
||
|
let content = fs.readFileSync(filePath, 'utf8');
|
||
|
|
||
|
const parseAllJson = process.env.XSENV_PARSE_ALL_JSON === 'true' || false;
|
||
|
if (!parseAllJson) {
|
||
|
if (!isJsonObject(content)) {
|
||
|
return content;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
try {
|
||
|
content = JSON.parse(content);
|
||
|
} catch (err) {
|
||
|
debug('Content of file %s is not valid JSON object', filePath);
|
||
|
}
|
||
|
return content;
|
||
|
}
|
||
|
|
||
|
function readFiles(dirPath) {
|
||
|
const result = {};
|
||
|
for (let file of fs.readdirSync(dirPath)) {
|
||
|
const filePath = path.join(dirPath, file);
|
||
|
if (isFile(filePath)) {
|
||
|
result[file] = readFileContent(filePath);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function parseTags(tags, serviceName) {
|
||
|
if (!tags) { return [serviceName]; }
|
||
|
if (process.env.XSENV_PARSE_ALL_JSON) { return [...tags]; }
|
||
|
return JSON.parse(tags);
|
||
|
}
|
||
|
|
||
|
function readInstance(serviceName, instanceName, instancePath) {
|
||
|
const credentials = readFiles(instancePath);
|
||
|
const tags = parseTags(credentials.tags, serviceName);
|
||
|
// previously the library used `serviceName` as derived from the
|
||
|
// file path as the only tag. To keep as close as possible to this
|
||
|
// behaviour we need to make sure this `serviceName` is in `tags`
|
||
|
if (!tags.includes(serviceName)) {
|
||
|
tags.push(serviceName);
|
||
|
}
|
||
|
return {
|
||
|
credentials,
|
||
|
name: instanceName,
|
||
|
label: credentials.label || serviceName,
|
||
|
tags
|
||
|
};
|
||
|
}
|
||
|
|
||
|
function readServiceInstances(serviceName, servicePath) {
|
||
|
const result = {};
|
||
|
for (let instanceName of fs.readdirSync(servicePath)) {
|
||
|
const instancePath = path.join(servicePath, instanceName);
|
||
|
if (isDirectory(instancePath)) {
|
||
|
result[instanceName] = readInstance(serviceName, instanceName, instancePath);
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function readSecrets(secretsPath) {
|
||
|
assert(isDirectory(secretsPath), 'secrets path must be a directory');
|
||
|
|
||
|
const result = {};
|
||
|
for (let serviceName of fs.readdirSync(secretsPath)) {
|
||
|
const servicePath = path.join(secretsPath, serviceName);
|
||
|
if (isDirectory(servicePath)) {
|
||
|
Object.assign(result, readServiceInstances(serviceName, servicePath));
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
function readK8SServices(secretsPath, disableCache) {
|
||
|
secretsPath = secretsPath || DEFAULT_SECRETS_PATH;
|
||
|
assert(typeof secretsPath === 'string', 'secrets directory path must be string');
|
||
|
let result = undefined;
|
||
|
|
||
|
let cachedSecrets = k8sSecretsCache.get(`${secretsPath}-services`);
|
||
|
if (cachedSecrets && !disableCache) {
|
||
|
debug(`Cached Secrets found: ${secretsPath}-services`);
|
||
|
debug(cachedSecrets);
|
||
|
return cachedSecrets;
|
||
|
}
|
||
|
|
||
|
if (fs.existsSync(secretsPath)) {
|
||
|
result = readSecrets(secretsPath);
|
||
|
debug(`Caching Secret: ${secretsPath}-services`);
|
||
|
debug(result);
|
||
|
k8sSecretsCache.set(`${secretsPath}-services`, result);
|
||
|
}
|
||
|
|
||
|
return result;
|
||
|
}
|