packages/@aws-cdk-testing/cli-integ/lib/with-cli-lib.ts (97 lines of code) (raw):
import * as os from 'os';
import * as path from 'path';
import type { TestContext } from './integ-test';
import { RESOURCES_DIR } from './resources';
import type { AwsContext } from './with-aws';
import { withAws } from './with-aws';
import type { CdkCliOptions, DisableBootstrapContext } from './with-cdk-app';
import { cloneDirectory, installNpmPackages, TestFixture, DEFAULT_TEST_TIMEOUT_S, ensureBootstrapped } from './with-cdk-app';
import { withTimeout } from './with-timeout';
/**
* Higher order function to execute a block with a CliLib Integration CDK app fixture
*/
export function withCliLibIntegrationCdkApp<A extends TestContext & AwsContext & DisableBootstrapContext>(
block: (context: CliLibIntegrationTestFixture) => Promise<void>) {
return async (context: A) => {
const randy = context.randomString;
const stackNamePrefix = `cdktest-${randy}`;
const integTestDir = path.join(os.tmpdir(), `cdk-integ-${randy}`);
context.log(` Stack prefix: ${stackNamePrefix}\n`);
context.log(` Test directory: ${integTestDir}\n`);
context.log(` Region: ${context.aws.region}\n`);
await cloneDirectory(path.join(RESOURCES_DIR, 'cdk-apps', 'simple-app'), integTestDir, context.output);
const fixture = new CliLibIntegrationTestFixture(
integTestDir,
stackNamePrefix,
context.output,
context.aws,
context.randomString);
await fixture.ecrPublicLogin();
let success = true;
try {
const installationVersion = fixture.packages.requestedFrameworkVersion();
if (fixture.packages.majorVersion() === '1') {
throw new Error('This test suite is only compatible with AWS CDK v2');
}
const alphaInstallationVersion = fixture.packages.requestedAlphaVersion();
// cli-lib-alpha has a magic alpha version in the old release pipeline,
// but will just mirror the CLI version in the new pipeline.
const cliLibVersion = process.env.CLI_LIB_VERSION_MIRRORS_CLI
? `${fixture.packages.requestedCliVersion()}-alpha.0`
: alphaInstallationVersion;
await installNpmPackages(fixture, {
'aws-cdk-lib': installationVersion,
'@aws-cdk/cli-lib-alpha': cliLibVersion,
'@aws-cdk/aws-lambda-go-alpha': alphaInstallationVersion,
'@aws-cdk/aws-lambda-python-alpha': alphaInstallationVersion,
'constructs': '^10',
});
if (!context.disableBootstrap) {
await ensureBootstrapped(fixture);
}
await block(fixture);
} catch (e: any) {
// We survive certain cases involving gopkg.in
if (errorCausedByGoPkg(e.message)) {
return;
}
success = false;
throw e;
} finally {
if (process.env.INTEG_NO_CLEAN) {
context.log(`Left test directory in '${integTestDir}' ($INTEG_NO_CLEAN)\n`);
} else {
await fixture.dispose(success);
}
}
};
}
/**
* Return whether or not the error is being caused by gopkg.in being down
*
* Our Go build depends on https://gopkg.in/, which has errors pretty often
* (every couple of days). It is run by a single volunteer.
*/
function errorCausedByGoPkg(error: string) {
// The error is different depending on what request fails. Messages recognized:
////////////////////////////////////////////////////////////////////
// go: github.com/aws/aws-lambda-go@v1.28.0 requires
// gopkg.in/yaml.v3@v3.0.0-20200615113413-eeeca48fe776: invalid version: git ls-remote -q origin in /go/pkg/mod/cache/vcs/0901dc1ef67fcce1c9b3ae51078740de4a0e2dc673e720584ac302973af82f36: exit status 128:
// remote: Cannot obtain refs from GitHub: cannot talk to GitHub: Get https://github.com/go-yaml/yaml.git/info/refs?service=git-upload-pack: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
// fatal: unable to access 'https://gopkg.in/yaml.v3/': The requested URL returned error: 502
////////////////////////////////////////////////////////////////////
// go: downloading github.com/aws/aws-lambda-go v1.28.0
// go: github.com/aws/aws-lambda-go@v1.28.0 requires
// gopkg.in/yaml.v3@v3.0.0-20200615113413-eeeca48fe776: unrecognized import path "gopkg.in/yaml.v3": reading https://gopkg.in/yaml.v3?go-get=1: 502 Bad Gateway
// server response: Cannot obtain refs from GitHub: cannot talk to GitHub: Get https://github.com/go-yaml/yaml.git/info/refs?service=git-upload-pack: net/http: request canceled (Client.Timeout exceeded while awaiting headers)
////////////////////////////////////////////////////////////////////
// go: github.com/aws/aws-lambda-go@v1.28.0 requires
// gopkg.in/yaml.v3@v3.0.0-20200615113413-eeeca48fe776: invalid version: git fetch -f origin refs/heads/*:refs/heads/* refs/tags/*:refs/tags/* in /go/pkg/mod/cache/vcs/0901dc1ef67fcce1c9b3ae51078740de4a0e2dc673e720584ac302973af82f36: exit status 128:
// error: RPC failed; HTTP 502 curl 22 The requested URL returned error: 502
// fatal: the remote end hung up unexpectedly
////////////////////////////////////////////////////////////////////
return (error.includes('gopkg\.in.*invalid version.*exit status 128')
|| error.match(/unrecognized import path[^\n]gopkg\.in/));
}
/**
* SAM Integration test fixture for CDK - SAM integration test cases
*/
export function withCliLibFixture(block: (context: CliLibIntegrationTestFixture) => Promise<void>) {
return withAws(withTimeout(DEFAULT_TEST_TIMEOUT_S, withCliLibIntegrationCdkApp(block)));
}
export class CliLibIntegrationTestFixture extends TestFixture {
/**
*
*/
public async cdk(args: string[], options: CdkCliOptions = {}) {
const action = args[0];
const stackName = args[1];
const cliOpts: Record<string, any> = {
stacks: stackName ? [stackName] : undefined,
};
if (action === 'deploy') {
cliOpts.requireApproval = options.neverRequireApproval ? 'never' : 'broadening';
}
return this.shell(['node', '--input-type=module', `<<__EOS__
import { AwsCdkCli } from '@aws-cdk/cli-lib-alpha';
const cli = AwsCdkCli.fromCdkAppDirectory();
await cli.${action}(${JSON.stringify(cliOpts)});
__EOS__`], {
...options,
modEnv: {
...this.cdkShellEnv(),
AWS_REGION: this.aws.region,
AWS_DEFAULT_REGION: this.aws.region,
STACK_NAME_PREFIX: this.stackNamePrefix,
PACKAGE_LAYOUT_VERSION: this.packages.majorVersion(),
// In these tests we want to make a distinction between stdout and sterr
CI: 'false',
...options.modEnv,
},
});
}
}