-
Notifications
You must be signed in to change notification settings - Fork 4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
197 additions
and
11 deletions.
There are no files selected for viewing
File renamed without changes.
121 changes: 121 additions & 0 deletions
121
packages/@aws-cdk/toolkit/lib/api/cloud-assembly/context-aware-source.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
import type { MissingContext } from '@aws-cdk/cloud-assembly-schema'; | ||
import * as cxapi from '@aws-cdk/cx-api'; | ||
import { ICloudAssemblySource } from './types'; | ||
import * as contextproviders from '../../context-providers'; | ||
import { debug } from '../../logging'; | ||
import { Context, PROJECT_CONTEXT } from '../../settings'; | ||
import { SdkProvider } from '../aws-auth'; | ||
import { ToolkitError } from '../errors'; | ||
|
||
export interface CloudExecutableProps { | ||
/** | ||
* AWS object (used by contextprovider) | ||
*/ | ||
readonly sdkProvider: SdkProvider; | ||
|
||
/** | ||
* Application context | ||
*/ | ||
readonly context: Context; | ||
|
||
/** | ||
* The file used to store application context in (relative to cwd). | ||
* | ||
* @default "cdk.context.json" | ||
*/ | ||
readonly contextFile?: string; | ||
|
||
/** | ||
* Enable context lookups. | ||
* | ||
* Producing a `cxapi.CloudAssembly` will fail if this is disabled and context lookups need to be performed. | ||
* | ||
* @default true | ||
*/ | ||
readonly lookups?: boolean; | ||
} | ||
|
||
/** | ||
* Represent the Cloud Executable and the synthesis we can do on it | ||
*/ | ||
export class ContextAwareCloudAssembly implements ICloudAssemblySource { | ||
private canLookup: boolean; | ||
private context: Context; | ||
private contextFile: string; | ||
|
||
constructor(private readonly source: ICloudAssemblySource, private readonly props: CloudExecutableProps) { | ||
this.canLookup = props.lookups ?? true; | ||
this.context = props.context; | ||
this.contextFile = props.contextFile ?? PROJECT_CONTEXT; // @todo new feature not needed right now | ||
} | ||
|
||
/** | ||
* Produce a Cloud Assembly, i.e. a set of stacks | ||
*/ | ||
public async produce(): Promise<cxapi.CloudAssembly> { | ||
// We may need to run the cloud executable multiple times in order to satisfy all missing context | ||
// (When the executable runs, it will tell us about context it wants to use | ||
// but it missing. We'll then look up the context and run the executable again, and | ||
// again, until it doesn't complain anymore or we've stopped making progress). | ||
let previouslyMissingKeys: Set<string> | undefined; | ||
while (true) { | ||
const assembly = await this.source.produce(); | ||
|
||
if (assembly.manifest.missing && assembly.manifest.missing.length > 0) { | ||
const missingKeys = missingContextKeys(assembly.manifest.missing); | ||
|
||
if (!this.canLookup) { | ||
throw new ToolkitError( | ||
'Context lookups have been disabled. ' | ||
+ 'Make sure all necessary context is already in \'cdk.context.json\' by running \'cdk synth\' on a machine with sufficient AWS credentials and committing the result. ' | ||
+ `Missing context keys: '${Array.from(missingKeys).join(', ')}'`); | ||
} | ||
|
||
let tryLookup = true; | ||
if (previouslyMissingKeys && equalSets(missingKeys, previouslyMissingKeys)) { | ||
debug('Not making progress trying to resolve environmental context. Giving up.'); | ||
tryLookup = false; | ||
} | ||
|
||
previouslyMissingKeys = missingKeys; | ||
|
||
if (tryLookup) { | ||
debug('Some context information is missing. Fetching...'); | ||
|
||
await contextproviders.provideContextValues( | ||
assembly.manifest.missing, | ||
this.context, | ||
this.props.sdkProvider, | ||
); | ||
|
||
// Cache the new context to disk | ||
await this.context.save(this.contextFile); | ||
|
||
// Execute again | ||
continue; | ||
} | ||
} | ||
|
||
return assembly; | ||
} | ||
} | ||
|
||
} | ||
|
||
/** | ||
* Return all keys of missing context items | ||
*/ | ||
function missingContextKeys(missing?: MissingContext[]): Set<string> { | ||
return new Set((missing || []).map(m => m.key)); | ||
} | ||
|
||
/** | ||
* Are two sets equal to each other | ||
*/ | ||
function equalSets<A>(a: Set<A>, b: Set<A>) { | ||
if (a.size !== b.size) { return false; } | ||
for (const x of a) { | ||
if (!b.has(x)) { return false; } | ||
} | ||
return true; | ||
} |
63 changes: 63 additions & 0 deletions
63
packages/@aws-cdk/toolkit/lib/api/cloud-assembly/from-app.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
import { ToolkitError } from '../errors'; | ||
import { ContextAwareCloudAssembly } from './context-aware-source'; | ||
import { ICloudAssemblySource } from './types'; | ||
|
||
/** | ||
* Configuration for creating a CLI from an AWS CDK App directory | ||
*/ | ||
export interface FromCdkAppProps { | ||
/** | ||
* @default - current working directory | ||
*/ | ||
readonly workingDirectory?: string; | ||
|
||
/** | ||
* Emits the synthesized cloud assembly into a directory | ||
* | ||
* @default cdk.out | ||
*/ | ||
readonly output?: string; | ||
} | ||
|
||
/** | ||
* Use a directory containing an AWS CDK app as source. | ||
* @param directory the directory of the AWS CDK app. Defaults to the current working directory. | ||
* @param props additional configuration properties | ||
* @returns an instance of `AwsCdkCli` | ||
*/ | ||
export function fromCdkApp(app: string, props: FromCdkAppProps = {}): ICloudAssemblySource { | ||
return new ContextAwareCloudAssembly( | ||
{ | ||
produce: async () => { | ||
await this.lock?.release(); | ||
|
||
try { | ||
const build = this.props.configuration.settings.get(['build']); | ||
if (build) { | ||
await exec(build, { cwd: props.workingDirectory }); | ||
} | ||
|
||
const commandLine = await guessExecutable(app); | ||
const outdir = props.output ?? 'cdk.out'; | ||
|
||
try { | ||
fs.mkdirpSync(outdir); | ||
} catch (e: any) { | ||
throw new ToolkitError(`Could not create output directory at '${outdir}' (${e.message}).`); | ||
} | ||
|
||
this.lock = await new RWLock(outdir).acquireWrite(); | ||
|
||
const env = await prepareDefaultEnvironment(this.props.sdkProvider, { outdir }); | ||
return await withContext(env, this.props.configuration, async (envWithContext, _context) => { | ||
await exec(commandLine.join(' '), { extraEnv: envWithContext, cwd: props.workingDirectory }); | ||
return createAssembly(outdir); | ||
}); | ||
} finally { | ||
await this.lock?.release(); | ||
} | ||
}, | ||
}, | ||
this.propsForContextAssembly, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters