-
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.
feat(toolkit): a programmatic toolkit for the AWS CDK
- Loading branch information
Showing
35 changed files
with
1,589 additions
and
202 deletions.
There are no files selected for viewing
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
import { StackSelector } from '../types'; | ||
|
||
export interface CloudFormationDiffOptions { | ||
/** | ||
* Whether to run the diff against the template after the CloudFormation Transforms inside it have been executed | ||
* (as opposed to the original template, the default, which contains the unprocessed Transforms). | ||
* | ||
* @default false | ||
*/ | ||
readonly compareAgainstProcessedTemplate?: boolean; | ||
} | ||
|
||
export interface ChangeSetDiffOptions extends CloudFormationDiffOptions { | ||
/** | ||
* Enable falling back to template-based diff in case creating the changeset is not possible or results in an error. | ||
* | ||
* Should be used for stacks containing nested stacks or when change set permissions aren't available. | ||
* | ||
* @default true | ||
*/ | ||
readonly fallbackToTemplate?: boolean; | ||
|
||
/** | ||
* Additional parameters for CloudFormation when creating a diff change set | ||
* | ||
* @default {} | ||
*/ | ||
readonly parameters?: { [name: string]: string | undefined }; | ||
} | ||
|
||
export class DiffMode { | ||
/** | ||
* Use a changeset to compute the diff. | ||
* | ||
* This will create, analyze, and subsequently delete a changeset against the CloudFormation stack. | ||
*/ | ||
public static ChangeSet(options: ChangeSetDiffOptions = {}) {} | ||
public static TemplateOnly(options: CloudFormationDiffOptions = {}) {} | ||
public static LocalTemplate(path: string) {} | ||
|
||
private constructor(public readonly mode: string) { | ||
|
||
} | ||
} | ||
|
||
export interface DiffOptions { | ||
/** | ||
* Select the stacks | ||
*/ | ||
readonly stacks: StackSelector; | ||
|
||
/** | ||
* The mode to create a stack diff. | ||
* | ||
* Use changeset diff for the highest fidelity, including analyze resource replacements. | ||
* In this mode, diff will use the deploy role instead of the lookup role. | ||
* | ||
* Use template-only diff for a faster, less accurate diff that doesn't require | ||
* permissions to create a change-set. | ||
* | ||
* Use local-template diff for a fast, local-only diff that doesn't require | ||
* any permissions or internet access. | ||
* | ||
* @default DiffMode.ChangeSet | ||
*/ | ||
readonly mode: DiffMode; | ||
|
||
/** | ||
* Strict diff mode | ||
* When enabled, this will not filter out AWS::CDK::Metadata resources, mangled non-ASCII characters, or the CheckBootstrapVersionRule. | ||
* | ||
* @default false | ||
*/ | ||
readonly strict?: boolean; | ||
|
||
/** | ||
* How many lines of context to show in the diff | ||
* | ||
* @default 3 | ||
*/ | ||
readonly contextLines?: number; | ||
|
||
/** | ||
* Only include broadened security changes in the diff | ||
* | ||
* @default false | ||
*/ | ||
readonly securityOnly?: boolean; | ||
} |
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,8 @@ | ||
import { StackSelector } from '../types'; | ||
|
||
export interface ListOptions { | ||
/** | ||
* Select the stacks | ||
*/ | ||
readonly stacks: StackSelector; | ||
} |
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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
/** | ||
* Options for the default SDK provider | ||
*/ | ||
export interface SdkOptions { | ||
/** | ||
* Profile to read from ~/.aws | ||
* | ||
* @default - No profile | ||
*/ | ||
readonly profile?: string; | ||
|
||
/** | ||
* Proxy address to use | ||
* | ||
* @default No proxy | ||
*/ | ||
readonly region?: string; | ||
|
||
/** | ||
* HTTP options for SDK | ||
*/ | ||
readonly httpOptions?: SdkHttpOptions; | ||
} | ||
|
||
/** | ||
* Options for individual SDKs | ||
*/ | ||
export interface SdkHttpOptions { | ||
/** | ||
* Proxy address to use | ||
* | ||
* @default No proxy | ||
*/ | ||
readonly proxyAddress?: string; | ||
|
||
/** | ||
* A path to a certificate bundle that contains a cert to be trusted. | ||
* | ||
* @default No certificate bundle | ||
*/ | ||
readonly caBundlePath?: string; | ||
} |
25 changes: 25 additions & 0 deletions
25
packages/@aws-cdk/toolkit/lib/api/cloud-assembly/cached-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,25 @@ | ||
import { CloudAssembly } from '@aws-cdk/cx-api'; | ||
import { ICloudAssemblySource } from './types'; | ||
|
||
/** | ||
* A CloudAssemblySource that is caching its result once produced. | ||
* | ||
* Most Toolkit interactions should use a cached source. | ||
* Not caching is relevant when the source changes frequently | ||
* and it is to expensive to predict if the source has changed. | ||
*/ | ||
export class CachedCloudAssemblySource implements ICloudAssemblySource { | ||
private source: ICloudAssemblySource; | ||
private cloudAssembly: CloudAssembly | undefined; | ||
|
||
public constructor(source: ICloudAssemblySource) { | ||
this.source = source; | ||
} | ||
|
||
public async produce(): Promise<CloudAssembly> { | ||
if (!this.cloudAssembly) { | ||
this.cloudAssembly = await this.source.produce(); | ||
} | ||
return this.cloudAssembly; | ||
} | ||
} |
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 { SdkProvider } from 'aws-cdk/lib/api/aws-auth'; | ||
import * as contextproviders from 'aws-cdk/lib/context-providers'; | ||
import { debug } from 'aws-cdk/lib/logging'; | ||
import { Context, PROJECT_CONTEXT } from 'aws-cdk/lib/settings'; | ||
import { ICloudAssemblySource } from './types'; | ||
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; | ||
} |
Oops, something went wrong.