@go-to-k/cdkd 0.115.1 → 0.115.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -15,12 +15,11 @@ import { GetParameterCommand, SSMClient } from "@aws-sdk/client-ssm";
|
|
|
15
15
|
import { GetCloudFrontOriginAccessIdentityCommand } from "@aws-sdk/client-cloudfront";
|
|
16
16
|
import { createReadStream, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
17
17
|
import { basename, join, resolve } from "node:path";
|
|
18
|
-
import {
|
|
18
|
+
import { spawn } from "node:child_process";
|
|
19
19
|
import { homedir, tmpdir } from "node:os";
|
|
20
20
|
import { GetHostedZoneCommand, ListHostedZonesByNameCommand, Route53Client } from "@aws-sdk/client-route-53";
|
|
21
21
|
import { DescribeListenersCommand, DescribeLoadBalancersCommand, ElasticLoadBalancingV2Client } from "@aws-sdk/client-elastic-load-balancing-v2";
|
|
22
22
|
import { KMSClient, ListAliasesCommand } from "@aws-sdk/client-kms";
|
|
23
|
-
import { promisify } from "node:util";
|
|
24
23
|
import { DescribeImagesCommand as DescribeImagesCommand$1, ECRClient, GetAuthorizationTokenCommand } from "@aws-sdk/client-ecr";
|
|
25
24
|
import { hostname } from "os";
|
|
26
25
|
import graphlib from "graphlib";
|
|
@@ -2796,82 +2795,229 @@ var FileAssetPublisher = class {
|
|
|
2796
2795
|
}
|
|
2797
2796
|
};
|
|
2798
2797
|
|
|
2798
|
+
//#endregion
|
|
2799
|
+
//#region src/utils/docker-cmd.ts
|
|
2800
|
+
/**
|
|
2801
|
+
* Shared helpers for invoking the docker-compatible CLI binary across cdkd.
|
|
2802
|
+
*
|
|
2803
|
+
* Two parity decisions with `aws-cdk-cli`'s `cdk-assets-lib`:
|
|
2804
|
+
* 1. `CDK_DOCKER` env var swaps the binary so podman / finch users can
|
|
2805
|
+
* run cdkd without code changes (`CDK_DOCKER=podman cdkd deploy`).
|
|
2806
|
+
* 2. `runDockerStreaming` uses streaming spawn rather than `execFile`'s
|
|
2807
|
+
* buffered `maxBuffer` ceiling. BuildKit's progress output can run to
|
|
2808
|
+
* tens of MB on multi-stage builds with `# syntax=docker/dockerfile:1`
|
|
2809
|
+
* frontend downloads + heredoc / `RUN --mount=...` features; the 50 MB
|
|
2810
|
+
* `execFile` ceiling cdkd used to set silently killed those builds
|
|
2811
|
+
* with `ERR_CHILD_PROCESS_STDIO_MAXBUFFER`.
|
|
2812
|
+
*
|
|
2813
|
+
* Output handling: stdout/stderr are collected in memory unconditionally so
|
|
2814
|
+
* `runDockerStreaming` can return them to the caller for error wrapping.
|
|
2815
|
+
* When the logger is at debug level (i.e. the user passed `--verbose`),
|
|
2816
|
+
* the chunks are ALSO mirrored to `process.stdout` / `process.stderr` so
|
|
2817
|
+
* the user sees live build progress.
|
|
2818
|
+
*/
|
|
2819
|
+
/**
|
|
2820
|
+
* Return the docker-compatible CLI binary to invoke. Matches CDK CLI:
|
|
2821
|
+
* `CDK_DOCKER` env var overrides the default `docker` so users on
|
|
2822
|
+
* podman / finch / nerdctl can swap without changing cdkd code.
|
|
2823
|
+
*/
|
|
2824
|
+
function getDockerCmd() {
|
|
2825
|
+
const override = process.env["CDK_DOCKER"];
|
|
2826
|
+
return override && override.length > 0 ? override : "docker";
|
|
2827
|
+
}
|
|
2828
|
+
/**
|
|
2829
|
+
* Spawn a docker-compatible CLI binary (resolved via `getDockerCmd`) with
|
|
2830
|
+
* streaming I/O. Collects stdout/stderr in memory and resolves with both
|
|
2831
|
+
* on exit code 0; rejects with a `SpawnError` carrying both streams on any
|
|
2832
|
+
* non-zero exit so the caller can wrap with its own error class without
|
|
2833
|
+
* losing the upstream output.
|
|
2834
|
+
*
|
|
2835
|
+
* No `maxBuffer` ceiling: BuildKit progress output frequently exceeds the
|
|
2836
|
+
* `child_process.execFile` default of 1 MB (cdkd previously bumped to 50 MB
|
|
2837
|
+
* but BuildKit + frontend pulls can still exceed that on first-time builds).
|
|
2838
|
+
*/
|
|
2839
|
+
async function runDockerStreaming(args, options = {}) {
|
|
2840
|
+
return spawnStreaming(getDockerCmd(), args, options);
|
|
2841
|
+
}
|
|
2842
|
+
/**
|
|
2843
|
+
* Generic streaming spawn — used by `runDockerStreaming` AND by the
|
|
2844
|
+
* `executable` source mode in `docker-build.ts` (which runs an arbitrary
|
|
2845
|
+
* user-supplied build command, not docker).
|
|
2846
|
+
*/
|
|
2847
|
+
async function spawnStreaming(cmd, args, options = {}) {
|
|
2848
|
+
const streamLive = options.streamLive ?? getLogger().getLevel() === "debug";
|
|
2849
|
+
const env = options.env ? mergeEnv(options.env) : void 0;
|
|
2850
|
+
return new Promise((resolve, reject) => {
|
|
2851
|
+
const child = spawn(cmd, args, {
|
|
2852
|
+
cwd: options.cwd,
|
|
2853
|
+
env,
|
|
2854
|
+
stdio: [
|
|
2855
|
+
options.input ? "pipe" : "ignore",
|
|
2856
|
+
"pipe",
|
|
2857
|
+
"pipe"
|
|
2858
|
+
]
|
|
2859
|
+
});
|
|
2860
|
+
const stdoutChunks = [];
|
|
2861
|
+
const stderrChunks = [];
|
|
2862
|
+
child.stdout.on("data", (chunk) => {
|
|
2863
|
+
stdoutChunks.push(chunk);
|
|
2864
|
+
if (streamLive) process.stdout.write(chunk);
|
|
2865
|
+
});
|
|
2866
|
+
child.stderr.on("data", (chunk) => {
|
|
2867
|
+
stderrChunks.push(chunk);
|
|
2868
|
+
if (streamLive) process.stderr.write(chunk);
|
|
2869
|
+
});
|
|
2870
|
+
child.once("error", (err) => {
|
|
2871
|
+
if (err.code === "ENOENT") {
|
|
2872
|
+
const usingOverride = process.env["CDK_DOCKER"] === cmd && cmd !== "docker";
|
|
2873
|
+
reject(/* @__PURE__ */ new Error(usingOverride ? `Failed to find and execute '${cmd}' (resolved via CDK_DOCKER). Install '${cmd}' or unset CDK_DOCKER to fall back to 'docker'.` : `Failed to find and execute '${cmd}'. Install Docker (or set the 'CDK_DOCKER' environment variable to a compatible binary such as podman / finch).`));
|
|
2874
|
+
} else reject(err);
|
|
2875
|
+
});
|
|
2876
|
+
child.once("close", (code) => {
|
|
2877
|
+
const stdout = Buffer.concat(stdoutChunks).toString("utf-8");
|
|
2878
|
+
const stderr = Buffer.concat(stderrChunks).toString("utf-8");
|
|
2879
|
+
if (code === 0) resolve({
|
|
2880
|
+
stdout,
|
|
2881
|
+
stderr
|
|
2882
|
+
});
|
|
2883
|
+
else {
|
|
2884
|
+
const message = stderr.trim() || stdout.trim() || `${cmd} ${args[0] ?? ""} exited with code ${code}`;
|
|
2885
|
+
const err = new Error(message);
|
|
2886
|
+
err.stderr = stderr;
|
|
2887
|
+
err.stdout = stdout;
|
|
2888
|
+
err.exitCode = code;
|
|
2889
|
+
reject(err);
|
|
2890
|
+
}
|
|
2891
|
+
});
|
|
2892
|
+
if (options.input !== void 0) {
|
|
2893
|
+
child.stdin.on("error", () => {});
|
|
2894
|
+
child.stdin.write(options.input);
|
|
2895
|
+
child.stdin.end();
|
|
2896
|
+
}
|
|
2897
|
+
});
|
|
2898
|
+
}
|
|
2899
|
+
/**
|
|
2900
|
+
* Format the stderr from a failed `docker login` so the surfaced cdkd
|
|
2901
|
+
* error gives the user an actionable workaround when the underlying
|
|
2902
|
+
* failure is a credential-helper persistence bug (which has nothing to
|
|
2903
|
+
* do with cdkd, AWS, or IAM perms — the docker CLI itself fails to
|
|
2904
|
+
* save the auth token to the platform's credential store). The most
|
|
2905
|
+
* common shape is `osxkeychain` on macOS rejecting an overwrite for
|
|
2906
|
+
* an existing entry, but `wincred` (Windows), `pass` (Linux), and
|
|
2907
|
+
* `secretservice` (Linux) hit the same class of `Error saving
|
|
2908
|
+
* credentials` failure, so the rewritten message stays platform-
|
|
2909
|
+
* agnostic — `docker logout <endpoint>` is the correct recovery on
|
|
2910
|
+
* every backend.
|
|
2911
|
+
*
|
|
2912
|
+
* Detected docker / docker-credential-* output patterns:
|
|
2913
|
+
* - `error storing credentials - err: exit status 1, out: \`The
|
|
2914
|
+
* specified item already exists in the keychain.\`` (osxkeychain)
|
|
2915
|
+
* - `Error saving credentials: ...` (any backend)
|
|
2916
|
+
*
|
|
2917
|
+
* Non-matching failures (genuine IAM / network / endpoint problems)
|
|
2918
|
+
* pass through with just the stderr trimmed — the original message
|
|
2919
|
+
* stays load-bearing for diagnosis.
|
|
2920
|
+
*/
|
|
2921
|
+
function formatDockerLoginError(stderr, endpoint) {
|
|
2922
|
+
const trimmed = stderr.trim();
|
|
2923
|
+
if (trimmed.includes("already exists in the keychain") || trimmed.includes("Error saving credentials")) return `docker's credential helper (osxkeychain on macOS / wincred on Windows / pass / secretservice on Linux) failed to persist the ECR auth token. The "already exists in the keychain" / "Error saving credentials" output is a known docker-credential-helpers issue — unrelated to cdkd, AWS credentials, or IAM perms. Quick fix: run \`docker logout ${endpoint}\` to clear the stale entry, then retry the cdkd command. Permanent fix: edit ~/.docker/config.json and remove (or empty) the platform-specific "credsStore" entry (e.g. "osxkeychain" → "" or "desktop" on macOS Docker Desktop). Original docker stderr: ${trimmed}`;
|
|
2924
|
+
return trimmed;
|
|
2925
|
+
}
|
|
2926
|
+
function mergeEnv(overrides) {
|
|
2927
|
+
const merged = { ...process.env };
|
|
2928
|
+
for (const [k, v] of Object.entries(overrides)) if (v === void 0) delete merged[k];
|
|
2929
|
+
else merged[k] = v;
|
|
2930
|
+
return merged;
|
|
2931
|
+
}
|
|
2932
|
+
|
|
2799
2933
|
//#endregion
|
|
2800
2934
|
//#region src/assets/docker-build.ts
|
|
2801
|
-
|
|
2802
|
-
|
|
2803
|
-
*
|
|
2804
|
-
* `
|
|
2805
|
-
*
|
|
2806
|
-
*
|
|
2807
|
-
*
|
|
2808
|
-
*
|
|
2809
|
-
*
|
|
2810
|
-
*
|
|
2811
|
-
* -
|
|
2812
|
-
*
|
|
2813
|
-
*
|
|
2814
|
-
*
|
|
2815
|
-
|
|
2816
|
-
|
|
2817
|
-
|
|
2818
|
-
* error-handling chain on each side keeps working unchanged.
|
|
2819
|
-
*
|
|
2820
|
-
* `platform` is new in PR 5: container Lambdas declare `Architectures:
|
|
2821
|
-
* [x86_64]` (default) or `[arm64]`, and the local-invoke caller MUST pass the
|
|
2822
|
-
* matching `linux/amd64` / `linux/arm64` so the built image can run on the
|
|
2823
|
-
* developer's host (which may have the opposite arch). The publisher caller
|
|
2824
|
-
* defaults to `undefined` for backward compatibility — passing through is
|
|
2825
|
-
* the no-op, the user's local docker default arch picks up.
|
|
2826
|
-
*/
|
|
2827
|
-
/**
|
|
2828
|
-
* Build a Docker image from a CDK asset's source description.
|
|
2829
|
-
*
|
|
2830
|
-
* @param asset The `DockerImageAsset` entry from the cdk asset
|
|
2831
|
-
* manifest (carries `directory`, `dockerFile`, build args,
|
|
2832
|
-
* target, outputs).
|
|
2833
|
-
* @param cdkOutDir Absolute path to the CDK output directory (`cdk.out`).
|
|
2834
|
-
* Used to resolve `asset.source.directory` to a real
|
|
2835
|
-
* build context on disk.
|
|
2836
|
-
* @param tag Local image tag to apply (`-t`). The caller chooses a
|
|
2837
|
-
* deterministic tag so subsequent runs hit Docker's
|
|
2838
|
-
* layer cache (publisher uses `cdkd-asset-<hash>`;
|
|
2839
|
-
* local-invoke uses `cdkd-local-invoke-<hash>`).
|
|
2840
|
-
* @param platform Optional `--platform` value (e.g. `linux/amd64`,
|
|
2841
|
-
* `linux/arm64`). When `undefined` the flag is omitted
|
|
2842
|
-
* and Docker uses its default platform.
|
|
2843
|
-
* @param wrapError Function the caller provides to wrap the underlying
|
|
2844
|
-
* `docker build` failure in a typed error specific to
|
|
2845
|
-
* its call site.
|
|
2846
|
-
* @throws Whatever `wrapError` returns when `docker build` exits non-zero.
|
|
2847
|
-
*/
|
|
2848
|
-
async function buildDockerImage(asset, cdkOutDir, tag, options) {
|
|
2935
|
+
/**
|
|
2936
|
+
* Build a Docker image from a CDK asset source. Returns the local image
|
|
2937
|
+
* tag the caller should use for `docker tag` / `docker push` (publisher)
|
|
2938
|
+
* or `docker run` (local-invoke).
|
|
2939
|
+
*
|
|
2940
|
+
* Two source modes (mirrors CDK CLI):
|
|
2941
|
+
* - `executable`: run the user-supplied command, capture stdout, return
|
|
2942
|
+
* it as the local tag. The script is responsible for building AND
|
|
2943
|
+
* tagging; cdkd just reads the tag from stdout. Used for Bazel /
|
|
2944
|
+
* custom build pipelines that produce images outside `docker build`.
|
|
2945
|
+
* - `directory`: standard `docker build <dir>` with the full BuildKit
|
|
2946
|
+
* flag set described above. Caller must pass `options.tag`.
|
|
2947
|
+
*
|
|
2948
|
+
* `executable` takes precedence when both fields are set (matches CDK CLI).
|
|
2949
|
+
*/
|
|
2950
|
+
async function buildDockerImage(asset, cdkOutDir, options) {
|
|
2951
|
+
const source = asset.source;
|
|
2849
2952
|
const logger = getLogger().child("docker-build");
|
|
2953
|
+
if (source.executable && source.executable.length > 0) {
|
|
2954
|
+
const [cmd, ...args] = source.executable;
|
|
2955
|
+
if (!cmd) throw options.wrapError("asset source.executable[] is empty");
|
|
2956
|
+
const cwd = source.directory ? `${cdkOutDir}/${source.directory}` : cdkOutDir;
|
|
2957
|
+
logger.debug(`Building Docker image via executable: ${source.executable.join(" ")} (cwd=${cwd})`);
|
|
2958
|
+
let result;
|
|
2959
|
+
try {
|
|
2960
|
+
result = await spawnStreaming(cmd, args, { cwd });
|
|
2961
|
+
} catch (err) {
|
|
2962
|
+
const e = err;
|
|
2963
|
+
throw options.wrapError(e.stderr || e.message || String(err));
|
|
2964
|
+
}
|
|
2965
|
+
const tag = result.stdout.trim();
|
|
2966
|
+
if (!tag) throw options.wrapError(`docker build executable produced no output (expected the local image tag on stdout): ${cmd} ${args.join(" ")}`);
|
|
2967
|
+
return tag;
|
|
2968
|
+
}
|
|
2969
|
+
if (!source.directory) throw options.wrapError(`DockerImageAssetSource must set either 'directory' or 'executable' (got: ${JSON.stringify(source)})`);
|
|
2970
|
+
if (!options.tag) throw options.wrapError("buildDockerImage(directory mode) requires options.tag");
|
|
2971
|
+
const buildArgs = buildDockerBuildCommand(source, options.tag, options.platform);
|
|
2972
|
+
const contextDir = `${cdkOutDir}/${source.directory}`;
|
|
2973
|
+
buildArgs.push(".");
|
|
2974
|
+
logger.debug(`${getDockerCmd()} ${buildArgs.join(" ")} (cwd=${contextDir})`);
|
|
2975
|
+
try {
|
|
2976
|
+
await runDockerStreaming(buildArgs, {
|
|
2977
|
+
cwd: contextDir,
|
|
2978
|
+
env: { BUILDX_NO_DEFAULT_ATTESTATIONS: "1" }
|
|
2979
|
+
});
|
|
2980
|
+
} catch (err) {
|
|
2981
|
+
const e = err;
|
|
2982
|
+
throw options.wrapError(e.stderr || e.message || String(err));
|
|
2983
|
+
}
|
|
2984
|
+
return options.tag;
|
|
2985
|
+
}
|
|
2986
|
+
/**
|
|
2987
|
+
* Construct the `docker build` argv (without the trailing context directory).
|
|
2988
|
+
*
|
|
2989
|
+
* Exported for unit-test inspection — keeps the flag-ordering assertions
|
|
2990
|
+
* independent of the spawn machinery.
|
|
2991
|
+
*/
|
|
2992
|
+
function buildDockerBuildCommand(source, tag, platformOverride) {
|
|
2850
2993
|
const args = [
|
|
2851
2994
|
"build",
|
|
2852
2995
|
"-t",
|
|
2853
2996
|
tag
|
|
2854
2997
|
];
|
|
2855
|
-
if (
|
|
2856
|
-
if (
|
|
2857
|
-
if (
|
|
2858
|
-
if (
|
|
2859
|
-
if (
|
|
2860
|
-
|
|
2861
|
-
args.push(
|
|
2862
|
-
|
|
2863
|
-
|
|
2864
|
-
|
|
2865
|
-
|
|
2866
|
-
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2998
|
+
if (source.dockerBuildArgs) for (const [k, v] of Object.entries(source.dockerBuildArgs)) args.push("--build-arg", `${k}=${v}`);
|
|
2999
|
+
if (source.dockerBuildContexts) for (const [k, v] of Object.entries(source.dockerBuildContexts)) args.push("--build-context", `${k}=${v}`);
|
|
3000
|
+
if (source.dockerBuildSecrets) for (const [k, v] of Object.entries(source.dockerBuildSecrets)) args.push("--secret", `id=${k},${v}`);
|
|
3001
|
+
if (source.dockerBuildSsh) args.push("--ssh", source.dockerBuildSsh);
|
|
3002
|
+
if (source.dockerBuildTarget) args.push("--target", source.dockerBuildTarget);
|
|
3003
|
+
if (source.dockerFile) args.push("-f", source.dockerFile);
|
|
3004
|
+
if (source.networkMode) args.push("--network", source.networkMode);
|
|
3005
|
+
const platform = platformOverride ?? source.platform;
|
|
3006
|
+
if (platform) args.push("--platform", platform);
|
|
3007
|
+
if (source.dockerOutputs) for (const output of source.dockerOutputs) args.push(`--output=${output}`);
|
|
3008
|
+
if (source.cacheFrom) for (const c of source.cacheFrom) args.push("--cache-from", cacheOptionToFlag(c));
|
|
3009
|
+
if (source.cacheTo) args.push("--cache-to", cacheOptionToFlag(source.cacheTo));
|
|
3010
|
+
if (source.cacheDisabled) args.push("--no-cache");
|
|
3011
|
+
return args;
|
|
3012
|
+
}
|
|
3013
|
+
function cacheOptionToFlag(option) {
|
|
3014
|
+
let flag = `type=${option.type}`;
|
|
3015
|
+
if (option.params) for (const [k, v] of Object.entries(option.params)) flag += `,${k}=${v}`;
|
|
3016
|
+
return flag;
|
|
2870
3017
|
}
|
|
2871
3018
|
|
|
2872
3019
|
//#endregion
|
|
2873
3020
|
//#region src/assets/docker-asset-publisher.ts
|
|
2874
|
-
const execFileAsync = promisify(execFile);
|
|
2875
3021
|
/**
|
|
2876
3022
|
* Publishes Docker image assets to ECR
|
|
2877
3023
|
*
|
|
@@ -2913,7 +3059,13 @@ var DockerAssetPublisher = class {
|
|
|
2913
3059
|
}
|
|
2914
3060
|
}
|
|
2915
3061
|
/**
|
|
2916
|
-
* Build a Docker image (public, used by WorkGraph asset-build nodes)
|
|
3062
|
+
* Build a Docker image (public, used by WorkGraph asset-build nodes).
|
|
3063
|
+
*
|
|
3064
|
+
* For `directory` source mode the build tags the result as `localTag`
|
|
3065
|
+
* directly via `docker build -t`. For `executable` source mode the
|
|
3066
|
+
* user-supplied script returns its own tag; cdkd re-tags it to `localTag`
|
|
3067
|
+
* via `docker tag` so the downstream `push()` step (which is wired to
|
|
3068
|
+
* `localTag` at graph-construction time) keeps working unchanged.
|
|
2917
3069
|
*/
|
|
2918
3070
|
async build(asset, cdkOutputDir, localTag) {
|
|
2919
3071
|
await this.buildImage(asset, cdkOutputDir, localTag);
|
|
@@ -2961,69 +3113,79 @@ var DockerAssetPublisher = class {
|
|
|
2961
3113
|
/**
|
|
2962
3114
|
* Build Docker image — delegates to the shared `buildDockerImage`
|
|
2963
3115
|
* helper so this code path stays in sync with `cdkd local invoke`'s
|
|
2964
|
-
* container-Lambda build path. `--platform` is
|
|
2965
|
-
*
|
|
2966
|
-
* a
|
|
2967
|
-
*
|
|
3116
|
+
* container-Lambda build path. `--platform` is read from the asset
|
|
3117
|
+
* manifest's `source.platform` (when set); cdkd does not currently
|
|
3118
|
+
* inject a publish-side override.
|
|
3119
|
+
*
|
|
3120
|
+
* `buildDockerImage` returns the actual local tag. For `directory`
|
|
3121
|
+
* source mode that's always `tag`. For `executable` source mode the
|
|
3122
|
+
* user's script returns its own tag; we re-tag via `docker tag` so the
|
|
3123
|
+
* downstream push step finds the image under the deterministic
|
|
3124
|
+
* `cdkd-asset-<hash>` name it expects.
|
|
2968
3125
|
*/
|
|
2969
3126
|
async buildImage(asset, cdkOutputDir, tag) {
|
|
2970
|
-
await buildDockerImage(asset, cdkOutputDir,
|
|
3127
|
+
const actualTag = await buildDockerImage(asset, cdkOutputDir, {
|
|
3128
|
+
tag,
|
|
3129
|
+
wrapError: (stderr) => new AssetError(`Docker build failed: ${stderr}`)
|
|
3130
|
+
});
|
|
3131
|
+
if (actualTag !== tag) {
|
|
3132
|
+
this.logger.debug(`Re-tagging executable-built image '${actualTag}' → '${tag}'`);
|
|
3133
|
+
try {
|
|
3134
|
+
await this.tagImage(actualTag, tag);
|
|
3135
|
+
} catch (err) {
|
|
3136
|
+
throw new AssetError(`Docker tag failed re-tagging '${actualTag}' → '${tag}': ${err.message ?? String(err)}`);
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
2971
3139
|
}
|
|
2972
3140
|
/**
|
|
2973
|
-
* Authenticate with ECR
|
|
3141
|
+
* Authenticate with ECR via `docker login --password-stdin`.
|
|
2974
3142
|
*/
|
|
2975
3143
|
async ecrLogin(client, accountId, region) {
|
|
2976
3144
|
const authData = (await client.send(new GetAuthorizationTokenCommand({}))).authorizationData?.[0];
|
|
2977
3145
|
if (!authData?.authorizationToken) throw new AssetError("Failed to get ECR authorization token");
|
|
2978
3146
|
const [username, password] = Buffer.from(authData.authorizationToken, "base64").toString().split(":");
|
|
3147
|
+
if (!username || password === void 0) throw new AssetError("ECR authorization token has unexpected shape (missing username/password)");
|
|
2979
3148
|
const endpoint = authData.proxyEndpoint || `https://${accountId}.dkr.ecr.${region}.amazonaws.com`;
|
|
2980
|
-
|
|
2981
|
-
|
|
3149
|
+
try {
|
|
3150
|
+
await runDockerStreaming([
|
|
2982
3151
|
"login",
|
|
2983
3152
|
"--username",
|
|
2984
3153
|
username,
|
|
2985
3154
|
"--password-stdin",
|
|
2986
3155
|
endpoint
|
|
2987
|
-
], {
|
|
2988
|
-
|
|
2989
|
-
|
|
2990
|
-
|
|
2991
|
-
|
|
2992
|
-
let stderr = "";
|
|
2993
|
-
proc.stderr?.on("data", (data) => {
|
|
2994
|
-
stderr += data.toString();
|
|
2995
|
-
});
|
|
2996
|
-
proc.on("close", (code) => {
|
|
2997
|
-
if (code === 0) resolve();
|
|
2998
|
-
else reject(new AssetError(`ECR login failed: ${stderr.trim()}`));
|
|
2999
|
-
});
|
|
3000
|
-
proc.on("error", (err) => {
|
|
3001
|
-
reject(new AssetError(`ECR login failed: ${err.message}`));
|
|
3002
|
-
});
|
|
3003
|
-
proc.stdin?.write(password);
|
|
3004
|
-
proc.stdin?.end();
|
|
3005
|
-
});
|
|
3156
|
+
], { input: password });
|
|
3157
|
+
} catch (err) {
|
|
3158
|
+
const e = err;
|
|
3159
|
+
throw new AssetError(`ECR login failed: ${formatDockerLoginError(e.stderr || e.message || String(err), endpoint)}`);
|
|
3160
|
+
}
|
|
3006
3161
|
}
|
|
3007
3162
|
/**
|
|
3008
3163
|
* Tag Docker image
|
|
3009
3164
|
*/
|
|
3010
3165
|
async tagImage(source, target) {
|
|
3011
|
-
|
|
3012
|
-
|
|
3013
|
-
|
|
3014
|
-
|
|
3015
|
-
|
|
3166
|
+
try {
|
|
3167
|
+
await runDockerStreaming([
|
|
3168
|
+
"tag",
|
|
3169
|
+
source,
|
|
3170
|
+
target
|
|
3171
|
+
]);
|
|
3172
|
+
} catch (err) {
|
|
3173
|
+
const e = err;
|
|
3174
|
+
throw new AssetError(`Docker tag failed: ${e.stderr?.trim() || e.message || String(err)}`);
|
|
3175
|
+
}
|
|
3016
3176
|
}
|
|
3017
3177
|
/**
|
|
3018
|
-
* Push Docker image
|
|
3178
|
+
* Push Docker image. Streams progress to stdout/stderr (via
|
|
3179
|
+
* `runDockerStreaming`) when the logger is at debug level, otherwise
|
|
3180
|
+
* captures silently and surfaces stderr on non-zero exit.
|
|
3019
3181
|
*/
|
|
3020
3182
|
async pushImage(uri) {
|
|
3021
3183
|
this.logger.debug(`Pushing: ${uri}`);
|
|
3022
3184
|
try {
|
|
3023
|
-
await
|
|
3024
|
-
} catch (
|
|
3025
|
-
const
|
|
3026
|
-
throw new AssetError(`Docker push failed: ${
|
|
3185
|
+
await runDockerStreaming(["push", uri]);
|
|
3186
|
+
} catch (err) {
|
|
3187
|
+
const e = err;
|
|
3188
|
+
throw new AssetError(`Docker push failed: ${e.stderr?.trim() || e.message || String(err)}`);
|
|
3027
3189
|
}
|
|
3028
3190
|
}
|
|
3029
3191
|
/**
|
|
@@ -9605,5 +9767,5 @@ var DeployEngine = class {
|
|
|
9605
9767
|
};
|
|
9606
9768
|
|
|
9607
9769
|
//#endregion
|
|
9608
|
-
export {
|
|
9609
|
-
//# sourceMappingURL=deploy-engine-
|
|
9770
|
+
export { StackHasActiveImportsError as $, Synthesizer as A, clearBucketRegionCache as B, AssetPublisher as C, formatDockerLoginError as D, buildDockerImage as E, resolveSkipPrefix as F, DependencyError as G, AssetError as H, resolveStateBucketWithDefault as I, PartialFailureError as J, LocalInvokeBuildError as K, resolveStateBucketWithDefaultAndSource as L, getLegacyStateBucketName as M, resolveApp as N, getDockerCmd as O, resolveCaptureObservedState as P, RouteDiscoveryError as Q, warnDeprecatedNoPrefixCliFlag as R, shouldRetainResource as S, WorkGraph as T, CdkdError as U, resolveBucketRegion as V, ConfigError as W, ResourceTimeoutError as X, ProvisioningError as Y, ResourceUpdateNotSupportedError as Z, DiffCalculator as _, withStackName as _t, withRetry as a, normalizeAwsError as at, LockManager as b, collectInlinePolicyNamesManagedBySiblings as c, getLogger as ct, normalizeAwsTagsToCfn as d, getLiveRenderer as dt, StackTerminationProtectionError as et, resolveExplicitPhysicalId as f, PATTERN_B_NAME_PROPERTIES as ft, IntrinsicFunctionResolver as g, withSkipPrefix as gt, assertRegionMatch as h, generateResourceNameWithFallback as ht, withResourceDeadline as i, isCdkdError as it, getDefaultStateBucketName as j, runDockerStreaming as k, CDK_PATH_TAG as l, setLogger as lt, CloudControlProvider as m, generateResourceName as mt, DEFAULT_RESOURCE_WARN_AFTER_MS as n, SynthesisError as nt, IMPLICIT_DELETE_DEPENDENCIES as o, withErrorHandling as ot, ProviderRegistry as p, PATTERN_B_RESOURCE_TYPES as pt, LockError as q, DeployEngine as r, formatError as rt, IAMRoleProvider as s, ConsoleLogger as st, DEFAULT_RESOURCE_TIMEOUT_MS as t, StateError as tt, matchesCdkPath as u, runStackBuffered as ut, DagBuilder as v, stringifyValue as w, S3StateBackend as x, TemplateParser as y, AssemblyReader as z };
|
|
9771
|
+
//# sourceMappingURL=deploy-engine-VFIYh_NY.js.map
|