pulumi/sdk/nodejs/runtime/config.ts
Matt Ellis 5eb78af779 Do not lazy initialize config or settings
The pulumi runtime used to lazily load and parse both config and
settings data set by the language host. The initial reason for this
design was that we wanted the runtime to be usable in a normal node
environment, but we have moved away from supporting that.

In addition, while we claimed we loaded these value "lazily", we
actually forced their loading quite eagerly when we started
up. However, when capturing config (or settings, as we now do), we
would capture all the logic about loading these values from the
environment.

Even worse, in the case where you had two copies of @pulumi/pulumi
loaded, it would be possible to capture a config object which was not
initialized and then at runtime the initialization logic would try to
read PULUMI_CONFIG from the process environment and fail.

So we adopt a new model where configuration and settings are parsed as
we load their containing modules. In addition, to support SxS
scinerios, we continue to use `process.env` as a way to control both
configuration and settings. This means that `run.ts` must now ensure
that these values are present in the environment before either the
config or runtime modules have been loaded.
2018-08-06 15:53:38 -07:00

72 lines
2.3 KiB
TypeScript

// Copyright 2016-2018, Pulumi Corporation.
//
// 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.
/**
* configEnvKey is the environment variable key that the language plugin uses to set configuration values.
*/
const configEnvKey = "PULUMI_CONFIG";
const config: {[key: string]: string} = parseConfig();
/**
* allConfig returns a copy of the full config map.
*/
export function allConfig(): {[key: string]: string} {
return Object.assign({}, config);
}
/**
* setConfig sets a configuration variable.
*/
export function setConfig(k: string, v: string): void {
config[cleanKey(k)] = v;
}
/**
* getConfig returns a configuration variable's value or undefined if it is unset.
*/
export function getConfig(k: string): string | undefined {
return config[k];
}
function parseConfig() {
const parsedConfig: {[key: string]: string} = {};
const envConfig = process.env[configEnvKey];
if (envConfig) {
const envObject: {[key: string]: string} = JSON.parse(envConfig);
for (const k of Object.keys(envObject)) {
parsedConfig[cleanKey(k)] = envObject[k];
}
}
return parsedConfig;
}
/**
* cleanKey takes a configuration key, and if it is of the form "<string>:config:<string>" removes
* the ":config:" portion. Previously, our keys always had the string ":config:" in them, and we'd
* like to remove it. However, the language host needs to continue to set it so we can be compatible
* with older versions of our packages. Once we stop supporting older packages, we can change the
* language host to not add this :config: thing and remove this function.
*/
function cleanKey(key: string): string {
const idx = key.indexOf(":");
if (idx > 0 && key.startsWith("config:", idx + 1)) {
return key.substring(0, idx) + ":" + key.substring(idx + 1 + "config:".length);
}
return key;
}