github.com/pulumi/pulumi/sdk/v3@v3.108.1/nodejs/runtime/config.ts (about) 1 // Copyright 2016-2018, Pulumi Corporation. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 import { getStore } from "./state"; 16 17 /** 18 * configEnvKey is the environment variable key that the language plugin uses to set configuration values. 19 * 20 * @internal 21 */ 22 export const configEnvKey = "PULUMI_CONFIG"; 23 24 /** 25 * configSecretKeysEnvKey is the environment variable key that the language plugin uses to set configuration keys that 26 * contain secrets. 27 * 28 * @internal 29 */ 30 export const configSecretKeysEnvKey = "PULUMI_CONFIG_SECRET_KEYS"; 31 32 /** 33 * allConfig returns a copy of the full config map. 34 */ 35 export function allConfig(): { [key: string]: string } { 36 const config = parseConfig(); 37 return Object.assign({}, config); 38 } 39 40 /** 41 * setAllConfig overwrites the config map. 42 */ 43 export function setAllConfig(c: { [key: string]: string }, secretKeys?: string[]) { 44 const obj: { [key: string]: string } = {}; 45 for (const k of Object.keys(c)) { 46 obj[cleanKey(k)] = c[k]; 47 } 48 persistConfig(obj, secretKeys); 49 } 50 51 /** 52 * setConfig sets a configuration variable. 53 */ 54 export function setConfig(k: string, v: string): void { 55 const config = parseConfig(); 56 config[cleanKey(k)] = v; 57 persistConfig(config, []); 58 } 59 60 /** 61 * getConfig returns a configuration variable's value or undefined if it is unset. 62 */ 63 export function getConfig(k: string): string | undefined { 64 const config = parseConfig(); 65 return config[k]; 66 } 67 68 /** 69 * isConfigSecret returns true if the key contains a secret value. 70 * @internal 71 */ 72 export function isConfigSecret(k: string): boolean { 73 const { config } = getStore(); 74 const envConfigSecretKeys = config[configSecretKeysEnvKey]; 75 if (envConfigSecretKeys) { 76 const envConfigSecretArray = JSON.parse(envConfigSecretKeys); 77 if (Array.isArray(envConfigSecretArray)) { 78 return envConfigSecretArray.includes(k); 79 } 80 } 81 return false; 82 } 83 84 /** 85 * parseConfig reads config from the source of truth, the environment. 86 * config must always be read this way because automation api introduces 87 * new program lifetime semantics where program lifetime != module lifetime. 88 */ 89 function parseConfig() { 90 const { config } = getStore(); 91 const parsedConfig: { [key: string]: string } = {}; 92 const envConfig = config[configEnvKey]; 93 if (envConfig) { 94 const envObject: { [key: string]: string } = JSON.parse(envConfig); 95 for (const k of Object.keys(envObject)) { 96 parsedConfig[cleanKey(k)] = envObject[k]; 97 } 98 } 99 100 return parsedConfig; 101 } 102 103 /** 104 * persistConfig writes config to the environment. 105 * config changes must always be persisted to the environment because automation api introduces 106 * new program lifetime semantics where program lifetime != module lifetime. 107 */ 108 function persistConfig(config: { [key: string]: string }, secretKeys?: string[]) { 109 const store = getStore(); 110 const serializedConfig = JSON.stringify(config); 111 const serializedSecretKeys = Array.isArray(secretKeys) ? JSON.stringify(secretKeys) : "[]"; 112 store.config[configEnvKey] = serializedConfig; 113 store.config[configSecretKeysEnvKey] = serializedSecretKeys; 114 } 115 116 /** 117 * cleanKey takes a configuration key, and if it is of the form "<string>:config:<string>" removes 118 * the ":config:" portion. Previously, our keys always had the string ":config:" in them, and we'd 119 * like to remove it. However, the language host needs to continue to set it so we can be compatible 120 * with older versions of our packages. Once we stop supporting older packages, we can change the 121 * language host to not add this :config: thing and remove this function. 122 */ 123 function cleanKey(key: string): string { 124 const idx = key.indexOf(":"); 125 126 if (idx > 0 && key.startsWith("config:", idx + 1)) { 127 return key.substring(0, idx) + ":" + key.substring(idx + 1 + "config:".length); 128 } 129 130 return key; 131 }