Skip to content

Commit 2f60622

Browse files
authored
feat(codecatalyst): add environment variable overrides for service configs (#4359)
* feat(codecatalyst): add environment variable overrides for service configs Problem: While we have user settings.json overrides for codecatalyst, it is not easy for settings.json to be updated in CI environments. Solution: Add ability to override on environment variables as well. Also, add generic functions for other services to do the same. * add cleanup after getServiceEnvVarConfig test
1 parent 436d99c commit 2f60622

File tree

4 files changed

+96
-2
lines changed

4 files changed

+96
-2
lines changed

CONTRIBUTING.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,7 @@ Example:
344344
}
345345
```
346346

347-
Overrides specifically for CodeCatalyst can be set using the `aws.dev.codecatalystService` setting. This is a JSON object consisting of keys/values required to override API calls to CodeCatalyst: `region`, `endpoint`, `hostname`, and `gitHostname`. If this setting is present, then all keys need to be explicitly provided.
347+
<a name="codecatalyst-settings">Overrides specifically for CodeCatalyst can be set using the `aws.dev.codecatalystService` setting. This is a JSON object consisting of keys/values required to override API calls to CodeCatalyst: `region`, `endpoint`, `hostname`, and `gitHostname`. If this setting is present, then all keys need to be explicitly provided.</a>
348348

349349
Example:
350350

@@ -398,6 +398,14 @@ Environment variables can be used to modify the behaviour of VSCode. The followi
398398
- `__DEV_ENVIRONMENT_SPACE_NAME`: The space name associated with the running development environment. Automatically set when running the toolkit in Codecatalyst
399399
- `__DEV_ENVIRONMENT_ORGANIZATION_NAME`: The organization name associated with the running development environment. Automatically set when running the toolkit in Codecatalyst
400400

401+
The following are environment variable versions of the user `settings.json` overrides mentioned [here](#codecatalyst-settings). These will always override the toolkit defaults and those defined in `settings.json`.
402+
Unlike the user setting overrides, not all of these environment variables have to be set to make use of them.
403+
404+
- `__CODECATALYST_REGION`: for aws.dev.codecatalystService.region
405+
- `__CODECATALYST_ENDPOINT`: for aws.dev.codecatalystService.endpoint
406+
- `__CODECATALYST_HOSTNAME`: for aws.dev.codecatalystService.hostname
407+
- `__CODECATALYST_GIT_HOSTNAME`: for aws.dev.codecatalystService.gitHostname
408+
401409
#### Lambda
402410

403411
- `AUTH_UTIL_LAMBDA_ARN`: The Amazon Resource Name (ARN) of the lambda function

src/shared/clients/codecatalystClient.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ import { truncateProps } from '../utilities/textUtilities'
3131
import { SsoConnection } from '../../auth/connection'
3232
import { DevSettings } from '../settings'
3333
import { RetryDelayOptions } from 'aws-sdk/lib/config-base'
34+
import { getServiceEnvVarConfig } from '../vscode/env'
3435

3536
export interface CodeCatalystConfig {
3637
readonly region: string
@@ -39,6 +40,13 @@ export interface CodeCatalystConfig {
3940
readonly gitHostname: string
4041
}
4142

43+
const configToEnvMap: { [K in keyof CodeCatalystConfig]: string } = {
44+
region: '__CODECATALYST_REGION',
45+
endpoint: '__CODECATALYST_ENDPOINT',
46+
hostname: '__CODECATALYST_HOSTNAME',
47+
gitHostname: '__CODECATALYST_GIT_HOSTNAME',
48+
}
49+
4250
export const defaultServiceConfig: CodeCatalystConfig = {
4351
region: 'us-east-1',
4452
endpoint: 'https://codecatalyst.global.api.aws',
@@ -47,7 +55,12 @@ export const defaultServiceConfig: CodeCatalystConfig = {
4755
}
4856

4957
export function getCodeCatalystConfig(): CodeCatalystConfig {
50-
return DevSettings.instance.getServiceConfig('codecatalystService', defaultServiceConfig)
58+
return {
59+
...DevSettings.instance.getServiceConfig('codecatalystService', defaultServiceConfig),
60+
61+
// Environment variable overrides
62+
...getServiceEnvVarConfig('codecatalyst', configToEnvMap),
63+
}
5164
}
5265

5366
export interface DevEnvironment extends CodeCatalyst.DevEnvironmentSummary {

src/shared/vscode/env.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
import * as semver from 'semver'
77
import * as vscode from 'vscode'
88
import * as packageJson from '../../../package.json'
9+
import { getLogger } from '../logger'
10+
import { onceChanged } from '../utilities/functionUtils'
911

1012
/**
1113
* Returns true if the current build is running on CI (build server).
@@ -89,3 +91,39 @@ export function getCodeCatalystSpaceName(): string | undefined {
8991
// TODO: remove legacy __DEV_ENVIRONMENT_ORGANIZATION_NAME
9092
return process.env['__DEV_ENVIRONMENT_SPACE_NAME'] || process.env['__DEV_ENVIRONMENT_ORGANIZATION_NAME']
9193
}
94+
95+
type ConfigToEnvMap = { [key: string]: string }
96+
type ServiceConfig = Partial<{ [K in keyof ConfigToEnvMap]: any }>
97+
const logConfigsOnce: { [key: string]: ReturnType<typeof onceChanged> } = {}
98+
99+
/**
100+
* Accepts a service name and a {config key -> expected env var name} map.
101+
* For each config key, check if the associated env var exists and return
102+
* a config map with the found values. Changes are logged once for each
103+
* service/found env var combos.
104+
*/
105+
export function getServiceEnvVarConfig(service: string, configToEnvMap: ConfigToEnvMap): ServiceConfig {
106+
const config: ServiceConfig = {}
107+
const overriden: string[] = []
108+
109+
// Find env vars for each field in the config
110+
for (const [field, envKey] of Object.entries(configToEnvMap)) {
111+
if (envKey in process.env) {
112+
config[field] = process.env[envKey]
113+
overriden.push(envKey)
114+
}
115+
}
116+
117+
// Log env var overrides, keeping track of which service we are logging for.
118+
// This allows us to log only once when env vars for a service change.
119+
if (overriden.length > 0) {
120+
if (!(service in logConfigsOnce)) {
121+
logConfigsOnce[service] = onceChanged(vars => {
122+
getLogger().info(`using env vars for ${service} config: ${vars}`)
123+
})
124+
}
125+
logConfigsOnce[service](overriden)
126+
}
127+
128+
return config
129+
}

src/test/shared/vscode/env.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import assert from 'assert'
7+
import { getServiceEnvVarConfig } from '../../../shared/vscode/env'
8+
9+
describe('getServiceEnvVarConfig', function () {
10+
const envVars: string[] = []
11+
12+
afterEach(() => {
13+
envVars.forEach(v => delete process.env[v])
14+
envVars.length = 0
15+
})
16+
17+
function addEnvVar(k: string, v: string) {
18+
process.env[k] = v
19+
envVars.push(k)
20+
}
21+
22+
it('gets service config', async function () {
23+
const service = 'codecatalyst'
24+
const configToEnvMap = {
25+
region: '__CODECATALYST_REGION',
26+
endpoint: '__CODECATALYST_ENDPOINT',
27+
}
28+
addEnvVar('__CODECATALYST_ENDPOINT', 'test.endpoint')
29+
30+
const expectedConfig = {
31+
endpoint: 'test.endpoint',
32+
}
33+
assert.deepStrictEqual(getServiceEnvVarConfig(service, configToEnvMap), expectedConfig)
34+
})
35+
})

0 commit comments

Comments
 (0)