Enable PULUMI_CONFIG envvars, use them
This change adds environment variable fallbacks for configuration variables, such that you can either set them explicitly, as a specific variable PULUMI_CONFIG_<K>, or an entire JSON serialized bag via PULUMI_CONFIG. This is convenient when simply invoking programs at the command line, via node, e.g. PULUMI_CONFIG_AWS_CONFIG_REGION=us-west-2 node bin/index.js Our language host also now uses this to communicate config when invoking a Run RPC, rather than at the command line. This fixes pulumi/pulumi#336.
This commit is contained in:
parent
ce87899792
commit
65184ec6bd
|
@ -34,19 +34,7 @@ export function main(args: string[]): void {
|
|||
boolean: [ "dry-run" ],
|
||||
string: [ "parallel", "pwd", "monitor", "engine" ],
|
||||
unknown: (arg: string) => {
|
||||
// If unknown, first see if it's a --config.k=v flag.
|
||||
const cix = arg.indexOf("-config");
|
||||
if (cix === 0 || cix === 1) {
|
||||
const kix = arg.indexOf(".");
|
||||
const vix = arg.indexOf("=");
|
||||
if (kix === -1 || vix === -1) {
|
||||
console.error(`fatal: --config flag malformed (expected '--config.key=val')`);
|
||||
usage();
|
||||
process.exit(-1);
|
||||
}
|
||||
config[arg.substring(kix+1, vix)] = arg.substring(vix+1);
|
||||
return false;
|
||||
} else if (arg.indexOf("-") === 0) {
|
||||
if (arg.indexOf("-") === 0) {
|
||||
console.error(`fatal: Unrecognized flag ${arg}`);
|
||||
usage();
|
||||
process.exit(-1);
|
||||
|
@ -57,9 +45,10 @@ export function main(args: string[]): void {
|
|||
stopEarly: true,
|
||||
});
|
||||
|
||||
// Set any configuration keys/values that were found.
|
||||
for (const key of Object.keys(config)) {
|
||||
runtime.setConfig(key, config[key]);
|
||||
// If any config variables are present, parse and set them, so the subsequent accesses are fast.
|
||||
const envObject: {[key: string]: string} = runtime.getConfigEnv();
|
||||
for (const key of Object.keys(envObject)) {
|
||||
runtime.setConfig(key, envObject[key]);
|
||||
}
|
||||
|
||||
// If there is a --pwd directive, switch directories.
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
// Copyright 2016-2017, Pulumi Corporation. All rights reserved.
|
||||
|
||||
/**
|
||||
* configEnvKey is the environment variable key for configuration that we will check in the event that a
|
||||
* configuration variable is missing. Explicit overrides take precedence.
|
||||
*/
|
||||
export const configEnvKey = "PULUMI_CONFIG";
|
||||
|
||||
let config: {[key: string]: string} = {};
|
||||
|
||||
/**
|
||||
|
@ -13,6 +19,54 @@ export function setConfig(k: string, v: string): void {
|
|||
* getConfig returns a configuration variable's value or undefined if it is unset.
|
||||
*/
|
||||
export function getConfig(k: string): string | undefined {
|
||||
return config[k];
|
||||
// If the config has been set explicitly, use it.
|
||||
if (config.hasOwnProperty(k)) {
|
||||
return config[k];
|
||||
}
|
||||
|
||||
// If there is a specific PULUMI_CONFIG_<k> variable, use it.
|
||||
const envKey: string = getConfigEnvKey(k);
|
||||
if (process.env.hasOwnProperty(envKey)) {
|
||||
return process.env[envKey];
|
||||
}
|
||||
|
||||
// If the config hasn't been set, but there is a process-wide PULUMI_CONFIG envvar, use it.
|
||||
const envObject: {[key: string]: string} = getConfigEnv();
|
||||
if (envObject.hasOwnProperty(k)) {
|
||||
return envObject[k];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* getConfigEnvKey returns a scrubbed environment variable key, PULUMI_CONFIG_<k>, that can be used for
|
||||
* setting explicit varaibles. This is unlike PULUMI_CONFIG which is just a JSON-serialized bag.
|
||||
*/
|
||||
export function getConfigEnvKey(key: string): string {
|
||||
let envkey: string = "";
|
||||
for (let c of key) {
|
||||
if (c == '_' || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')) {
|
||||
envkey += c;
|
||||
}
|
||||
else if (c >= 'a' && c <= 'z') {
|
||||
envkey += c.toUpperCase();
|
||||
}
|
||||
else {
|
||||
envkey += '_';
|
||||
}
|
||||
}
|
||||
return `${configEnvKey}_${envkey}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* getConfigEnv returns the environment map that will be used for config checking when variables aren't set.
|
||||
*/
|
||||
export function getConfigEnv(): {[key: string]: string} {
|
||||
const envConfig = process.env.PULUMI_CONFIG;
|
||||
if (envConfig) {
|
||||
return JSON.parse(envConfig);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
import * as childprocess from "child_process";
|
||||
import * as os from "os";
|
||||
import * as path from "path";
|
||||
import * as runtime from "../runtime";
|
||||
|
||||
let grpc = require("grpc");
|
||||
let langproto = require("../proto/languages_pb.js");
|
||||
|
@ -52,12 +53,17 @@ function runRPC(call: any, callback: any): void {
|
|||
path.join(__filename, "..", "..", "cmd", "run"),
|
||||
];
|
||||
|
||||
// Serialize the config args using "--config.k=v" flags.
|
||||
// Serialize the config args using an environment variable.
|
||||
let env: {[key: string]: string} = {};
|
||||
let config: any = req.getConfigMap();
|
||||
if (config) {
|
||||
// First flatten the config into a regular (non-RPC) object.
|
||||
let configForEnv: {[key: string]: string} = {};
|
||||
for (let entry of config.entries()) {
|
||||
args.push(`--config.${entry[0]}=${entry[1]}`);
|
||||
configForEnv[(entry[0] as string)] = (entry[1] as string);
|
||||
}
|
||||
// Now JSON serialize the config into an environment variable.
|
||||
env[runtime.configEnvKey] = JSON.stringify(configForEnv);
|
||||
}
|
||||
|
||||
// If this is a dry-run, tell the program so.
|
||||
|
@ -111,7 +117,9 @@ function runRPC(call: any, callback: any): void {
|
|||
|
||||
// We spawn a new process to run the program. This is required because we don't want the run to complete
|
||||
// until the Node message loop quiesces. It also gives us an extra level of isolation.
|
||||
proc = childprocess.spawn(process.argv[0], args);
|
||||
proc = childprocess.spawn(process.argv[0], args, {
|
||||
env: Object.assign({}, process.env, env),
|
||||
});
|
||||
proc.stdout.on("data", (data: string | Buffer) => {
|
||||
console.log(stripEOL(data));
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue