diff options
author | Lucas, John (jl1315) <jflucas@research.att.com> | 2017-08-23 18:58:33 +0000 |
---|---|---|
committer | J. F. Lucas <jflucas@research.att.com> | 2017-08-23 19:05:41 +0000 |
commit | 3c1527544df835a831898edbd74a473f027bb855 (patch) | |
tree | 2e2cf0c7060b39aec4829dc866fcb2468fa16b77 /lib/config.js | |
parent | bacbd4c6349f9de9c597d309a6c23eced2058a15 (diff) |
deployment handler initial seed code
Change-Id: I0bfc86d17edead0114ea0012fb469014e978cd15
Issue-Id: DCAEGEN2-43
Signed-off-by: J. F. Lucas <jflucas@research.att.com>
Diffstat (limited to 'lib/config.js')
-rw-r--r-- | lib/config.js | 213 |
1 files changed, 213 insertions, 0 deletions
diff --git a/lib/config.js b/lib/config.js new file mode 100644 index 0000000..4429247 --- /dev/null +++ b/lib/config.js @@ -0,0 +1,213 @@ +/* +Copyright(c) 2017 AT&T Intellectual Property. All rights reserved. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. + +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, +software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and limitations under the License. +*/ + +/* + * Dispatcher configuration + * Configuration may come from environment variables, a value in a Consul key-value store, or defaults, + * in that order of precedence. + * + * The address of the Consul host is passed in an environment variable called CONSUL_HOST. + * If present, the configuration value in the key-value store is a UTF-8 serialization of a JSON object. + * + * + * -------------------------------------------------------------------------------------- + * | JSON property | Environment variable | Required? | Default | + * -------------------------------------------------------------------------------------- + * | logLevel | LOG_LEVEL | Yes | "INFO" | + * -------------------------------------------------------------------------------------- + * | listenHost | LISTEN_HOST | Yes | "0.0.0.0" | + * -------------------------------------------------------------------------------------- + * | listenPort | LISTEN_PORT | Yes | 8443 | + * -------------------------------------------------------------------------------------- + * | cloudify.user | CLOUDIFY_USER | No | none | + * -------------------------------------------------------------------------------------- + * | cloudify.password | CLOUDIFY_PASSWORD | No | none | + * -------------------------------------------------------------------------------------- + * | cloudify.protocol | CLOUDIFY_PROTOCOL | No | "https" | + * -------------------------------------------------------------------------------------- + * | inventory.user | INVENTORY_USER | No | none | + * -------------------------------------------------------------------------------------- + * | inventory.password | INVENTORY_PASSWORD | No | none | + * -------------------------------------------------------------------------------------- + * | inventory.protocol | INVENTORY_PROTOCOL | No | "https" | + * -------------------------------------------------------------------------------------- + * | auth | (no environment var) | No | none | + * -------------------------------------------------------------------------------------- + * auth, if present, is a JSON object, with property names corresponding to user names and + * property values corresponding to passwords. If the auth property has the value: + * {"admin" : "admin123", "other" : "other123"}, then any incoming HTTP requests must use + * Basic authentication and supply "admin" as a user name with "admin123" as the password or + * supply "other" as the user name with "other123" as the password. + * + * The dispatcher will attempt to run using TLS (i.e., as an HTTPS server) if a certificate + * file in pkcs12 format is stored at etc/cert/cert and a file containing the corresponding + * passphrase is stored at etc/cert/pass. These files can be made available to the container + * running the dispatcher by mounting a volume to the container. + */ +"use strict"; + +const fs = require("fs"); +const utils = require("./utils"); +const consul = require("./consul"); + +const SSL_CERT_FILE = "etc/cert/cert"; +const SSL_PASS_FILE = "etc/cert/pass"; + +const CONFIG_KEY = "deployment_handler"; /* Configuration is stored under the name "deployment_handler" */ +const CM_NAME = "cloudify_manager"; +const INV_NAME = "inventory"; + +const CM_API_PATH = "/api/v2.1"; +const INV_API_PATH = ""; + +const DEFAULT_CLOUDIFY_PROTOCOL = "https"; +const DEFAULT_INVENTORY_PROTOCOL = "https"; +const DEFAULT_LISTEN_PORT = 8443; +const DEFAULT_LISTEN_HOST = "0.0.0.0"; +const DEFAULT_LOG_LEVEL = "INFO"; + +/* Check configuration for completeness */ +const findMissingConfig = function(cfg) { + const requiredProps = ['logLevel', 'listenHost', 'listenPort', 'cloudify.url', 'inventory.url']; + return requiredProps.filter(function(p){return !utils.hasProperty(cfg,p);}); +}; + +/* Fetch configuration */ +const getConfig = function (configStoreAddress) { + const ch = consul({url: configStoreAddress}); + return ch.getKey(CONFIG_KEY) + .then(function(res) { + return res || {}; + }) + .catch(function(err) { + throw err; + }); +}; + +/* Get a service host:port */ +const getService = function (configStoreAddress, serviceName) { + const ch = consul({url: configStoreAddress}); + return ch.getService(serviceName) + .then(function(res) { + if (res.length > 0) { + return res[0]; + } + else { + throw new Error("No service address found for " + serviceName); + } + }) +}; + +/* Get the content of a file */ +const getFileContents = function(path) { + return new Promise(function(resolve, reject) { + fs.readFile(path, function(err, data) { + if (err) { + reject(err); + } + else { + resolve(data); + } + }) + }) +}; + +/* Check for a TLS cert file and passphrase */ +const getTLSCredentials = function() { + var ssl = {}; + + /* Get the passphrase */ + return getFileContents(SSL_PASS_FILE) + .then(function(phrase) { + ssl.passphrase = phrase.toString('utf8').trim(); + + /* Get the cert */ + return getFileContents(SSL_CERT_FILE); + }) + + .then(function(cert) { + ssl.pfx = cert; /* Keep cert contents as a Buffer */ + return ssl; + }) + + .catch(function(err) { + return {}; + }); +} + +exports.configure = function(configStoreAddress) { + + var config = {}; + + /* Construct a URL for Consul, assuming HTTP and the default Consul port */ + const configStoreURL = 'http://' + configStoreAddress + ':8500'; + + /* Get configuration from configuration store */ + return getConfig(configStoreURL) + .then (function(cfg) { + + config = cfg; + + /* Override values with environment variables and set defaults as needed */ + config.listenPort = process.env.LISTEN_PORT || cfg.listenPort || DEFAULT_LISTEN_PORT; + config.listenHost = process.env.LISTEN_HOST || cfg.listenHost || DEFAULT_LISTEN_HOST; + config.logLevel = process.env.LOG_LEVEL || cfg.logLevel || DEFAULT_LOG_LEVEL; + + config.cloudify = config.cloudify || {}; + config.cloudify.protocol = process.env.CLOUDIFY_PROTOCOL || (cfg.cloudify && cfg.cloudify.protocol) || DEFAULT_CLOUDIFY_PROTOCOL; + if ((cfg.cloudify && cfg.cloudify.user) || process.env.CLOUDIFY_USER) { + config.cloudify.user = process.env.CLOUDIFY_USER || cfg.cloudify.user; + config.cloudify.password = process.env.CLOUDIFY_PASSWORD || cfg.cloudify.password || ""; + } + + config.inventory = config.inventory || {}; + config.inventory.protocol = process.env.INVENTORY_PROTOCOL || (cfg.inventory && cfg.inventory.protocol) || DEFAULT_INVENTORY_PROTOCOL; + if ((cfg.inventory && cfg.inventory.user)|| process.env.INVENTORY_USER) { + config.inventory.user = process.env.INVENTORY_USER || cfg.inventory.user; + config.inventory.password = process.env.INVENTORY_PASSWORD || cfg.inventory.password || ""; + } + + /* Get service information for Cloudify Manager */ + return getService(configStoreURL, CM_NAME); + }) + + .then(function(cmService) { + + config.cloudify.url = config.cloudify.protocol +"://" + cmService.address + ":" + cmService.port + CM_API_PATH; + + /* Get service information for inventory */ + return getService(configStoreURL, INV_NAME); + }) + + .then(function(invService) { + config.inventory.url = config.inventory.protocol + "://" + invService.address + ":" + invService.port + INV_API_PATH; + + /* Get TLS credentials, if they exist */ + return getTLSCredentials(); + }) + .then(function(tls) { + config.ssl = tls; + + /* Check for missing required configuration parameters */ + const missing = findMissingConfig(config); + if (missing.length > 0) { + throw new Error ("Required configuration elements missing: " + missing.join(',')); + config = null; + } + + return config; + }); +}; |