From 7d51927797fb1e3b6444a95c194713d1bb93032f Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Thu, 6 Feb 2020 18:54:59 -0800 Subject: [PATCH 01/21] Perform docker builds even during preview so we can get users errors prior to a real update. --- sdk/nodejs/docker.ts | 125 +++++++++++++++++++++++++++---------------- 1 file changed, 79 insertions(+), 46 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index f29b2b86..2b5a76c8 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -162,23 +162,50 @@ export function buildAndPushImage( connectToRegistry?: () => pulumi.Input, skipPush: boolean = false): pulumi.Output { - return pulumi.all([pathOrBuild, repositoryUrl]) - .apply(async ([pathOrBuildVal, repositoryUrlVal]) => { + // We do something rather interesting here. We do not want to proceed if we don't actually have + // a value yet for `pathOrBuild`. So we do a normal `ouput(...).apply(...)`. However, we *do* + // want proceed if we don't have a value yet for `repositoryUrl`. In that case, we'll just + // build without actually pushing. To support that, we run `.apply` on the repoUrl, but we pass + // in `runWithUnknowns:true` to actually continue on in that case. + return pulumi.output(pathOrBuild).apply(pathOrBuild => { + const op = pulumi.output(repositoryUrl); + const res: pulumi.Output = (op).apply( + (u: string | undefined) => buildAndPushImageImpl(pathOrBuild, u), + /*runWithUnknowns:*/ true); + + return res; + }); - // Give an initial message indicating what we're about to do. That way, if anything - // takes a while, the user has an idea about what's going on. - logEphemeral("Starting docker build and push...", logResource); + async function buildAndPushImageImpl( + pathOrBuild: string | pulumi.Unwrap, + repositoryUrl: string | undefined): Promise { - const result = await buildAndPushImageWorkerAsync( - imageName, pathOrBuildVal, repositoryUrlVal, logResource, connectToRegistry, skipPush); + // if we got an unknown repository url, just set to undefined for the remainder of + // processing. The rest of the code can handle that. + if (pulumi.containsUnknowns(repositoryUrl)) { + repositoryUrl = undefined; + } - // If we got here, then building/pushing didn't throw any errors. Update the status bar - // indicating that things worked properly. That way, the info bar isn't stuck showing the very - // last thing printed by some subcommand we launched. - logEphemeral("Successfully pushed to docker", logResource); + if (repositoryUrl) { + checkRepositoryUrl(repositoryUrl); + } - return result; - }); + logEphemeral("Starting docker build...", logResource); + const buildResult = await buildImage(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); + logEphemeral("Completed docker build", logResource); + + // If we have no repository url, then we definitely can't push our build result. Same if + // we're in preview. + if (skipPush || !repositoryUrl || pulumi.runtime.isDryRun()) { + return imageName; + } + + logEphemeral("Starting docker push...", logResource); + const result = await pushImage(repositoryUrl, buildResult, logResource); + logEphemeral("Completed docker build", logResource); + + return result; + } } function logEphemeral(message: string, logResource: pulumi.Resource) { @@ -219,17 +246,12 @@ export function checkRepositoryUrl(repositoryUrl: string) { } } -async function buildAndPushImageWorkerAsync( - baseImageName: string, - pathOrBuild: string | pulumi.Unwrap, - repositoryUrl: string, - logResource: pulumi.Resource, - connectToRegistry: (() => pulumi.Input) | undefined, - skipPush: boolean): Promise { - - checkRepositoryUrl(repositoryUrl); - - const tag = utils.getImageNameAndTag(baseImageName).tag; +async function buildImage( + baseImageName: string, + pathOrBuild: string | pulumi.Unwrap, + repositoryUrl: string | undefined, + logResource: pulumi.Resource, + connectToRegistry: (() => pulumi.Input) | undefined): Promise { // login immediately if we're going to have to actually communicate with a remote registry. // @@ -264,15 +286,25 @@ async function buildAndPushImageWorkerAsync( if (pullFromCache) { const dockerBuild = >pathOrBuild; const cacheFromParam = (typeof dockerBuild.cacheFrom === "boolean" ? {} : dockerBuild.cacheFrom) || {}; - cacheFrom = pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl, logResource); + + // pullFromCache is only true if repositoryUrl is present. + cacheFrom = pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl!, logResource); } // Next, build the image. - const {imageId, stages} = await buildImageAsync(baseImageName, pathOrBuild, logResource, cacheFrom); - if (imageId === undefined) { + const buildResult = await buildImageAsync(baseImageName, pathOrBuild, logResource, cacheFrom); + if (buildResult.imageId === undefined) { throw new Error("Internal error: docker build did not produce an imageId."); } + return buildResult; +} + +async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { + const { imageName: baseImageName, imageId, stages } = buildResult; + + const tag = utils.getImageNameAndTag(baseImageName).tag; + // Generate a name that uniquely will identify this built image. This is similar in purpose to // the name@digest form that can be normally be retrieved from a docker repository. However, // this tag doesn't require actually pushing the image, nor does it require communicating with @@ -283,24 +315,24 @@ async function buildAndPushImageWorkerAsync( // Use those to push the image. Then just return the unique target name. as the final result // for our caller to use. Only push the image during an update, do not push during a preview. - if (!pulumi.runtime.isDryRun() && !skipPush) { - // Push the final image first, then push the stage images to use for caching. - - // First, push with both the optionally-requested-tag *and* imageId (which is guaranteed to - // be defined). By using the imageId we give the image a fully unique location that we can - // successfully pull regardless of whatever else has happened at this repositoryUrl. - - // Next, push only with the optionally-requested-tag. Users of this API still want to get a - // nice and simple url that they can reach this image at, without having the explicit imageId - // hash added to it. Note: this location is not guaranteed to be idempotent. For example, - // pushes on other machines might overwrite that location. - await tagAndPushImageAsync(baseImageName, repositoryUrl, tag, imageId, logResource); - await tagAndPushImageAsync(baseImageName, repositoryUrl, tag, /*imageId:*/ undefined, logResource); - - for (const stage of stages) { - await tagAndPushImageAsync( - localStageImageName(baseImageName, stage), repositoryUrl, stage, /*imageId:*/ undefined, logResource); - } + + + // Push the final image first, then push the stage images to use for caching. + + // First, push with both the optionally-requested-tag *and* imageId (which is guaranteed to + // be defined). By using the imageId we give the image a fully unique location that we can + // successfully pull regardless of whatever else has happened at this repositoryUrl. + + // Next, push only with the optionally-requested-tag. Users of this API still want to get a + // nice and simple url that they can reach this image at, without having the explicit imageId + // hash added to it. Note: this location is not guaranteed to be idempotent. For example, + // pushes on other machines might overwrite that location. + await tagAndPushImageAsync(baseImageName, repositoryUrl, tag, imageId, logResource); + await tagAndPushImageAsync(baseImageName, repositoryUrl, tag, /*imageId:*/ undefined, logResource); + + for (const stage of stages) { + await tagAndPushImageAsync( + localStageImageName(baseImageName, stage), repositoryUrl, stage, /*imageId:*/ undefined, logResource); } return uniqueTaggedImageName; @@ -365,6 +397,7 @@ async function pullCacheAsync( } interface BuildResult { + imageName: string; imageId: string; stages: string[]; } @@ -430,7 +463,7 @@ async function buildImageAsync( const colonIndex = imageId.lastIndexOf(":"); imageId = colonIndex < 0 ? imageId : imageId.substr(colonIndex + 1); - return {imageId, stages}; + return { imageName, imageId, stages }; } async function dockerBuild( From b37310bc94eca31fce0a914fcc0999ace303b646 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 11:34:02 -0800 Subject: [PATCH 02/21] Add test --- examples/aws/index.ts | 3 ++ examples/broken_dockerfile/Pulumi.yaml | 5 +++ examples/broken_dockerfile/app/Dockerfile | 2 ++ .../broken_dockerfile/app/content/index.html | 1 + examples/broken_dockerfile/index.ts | 18 +++++++++++ examples/broken_dockerfile/package.json | 9 ++++++ examples/examples_test.go | 19 ++++++++++- sdk/nodejs/docker.ts | 32 +++++++++---------- 8 files changed, 72 insertions(+), 17 deletions(-) create mode 100644 examples/broken_dockerfile/Pulumi.yaml create mode 100644 examples/broken_dockerfile/app/Dockerfile create mode 100644 examples/broken_dockerfile/app/content/index.html create mode 100644 examples/broken_dockerfile/index.ts create mode 100644 examples/broken_dockerfile/package.json diff --git a/examples/aws/index.ts b/examples/aws/index.ts index e0e818f7..380a8231 100644 --- a/examples/aws/index.ts +++ b/examples/aws/index.ts @@ -66,3 +66,6 @@ const image3 = new docker.Image("path-example", { export const image1Name = image1.imageName; export const image2Name = image2.imageName; export const image3Name = image3.imageName; + +export const image4Name = docker.buildAndPushImage( + "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined); diff --git a/examples/broken_dockerfile/Pulumi.yaml b/examples/broken_dockerfile/Pulumi.yaml new file mode 100644 index 00000000..ac850127 --- /dev/null +++ b/examples/broken_dockerfile/Pulumi.yaml @@ -0,0 +1,5 @@ +name: broken +runtime: nodejs +description: A minimal TypeScript Pulumi program +template: + description: A minimal TypeScript Pulumi program diff --git a/examples/broken_dockerfile/app/Dockerfile b/examples/broken_dockerfile/app/Dockerfile new file mode 100644 index 00000000..3c4e99ee --- /dev/null +++ b/examples/broken_dockerfile/app/Dockerfile @@ -0,0 +1,2 @@ +FR OM nginx +COPY content /usr/share/nginx/html \ No newline at end of file diff --git a/examples/broken_dockerfile/app/content/index.html b/examples/broken_dockerfile/app/content/index.html new file mode 100644 index 00000000..22cf0726 --- /dev/null +++ b/examples/broken_dockerfile/app/content/index.html @@ -0,0 +1 @@ +

Hi from Pulumi

\ No newline at end of file diff --git a/examples/broken_dockerfile/index.ts b/examples/broken_dockerfile/index.ts new file mode 100644 index 00000000..ffd2893f --- /dev/null +++ b/examples/broken_dockerfile/index.ts @@ -0,0 +1,18 @@ +// Copyright 2016-2018, Pulumi Corporation. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +import * as docker from "@pulumi/docker"; + +export const imageName = docker.buildAndPushImage( + "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined); diff --git a/examples/broken_dockerfile/package.json b/examples/broken_dockerfile/package.json new file mode 100644 index 00000000..62e6c1a5 --- /dev/null +++ b/examples/broken_dockerfile/package.json @@ -0,0 +1,9 @@ +{ + "name": "broken", + "devDependencies": { + "@types/node": "^8.0.0" + }, + "dependencies": { + "@pulumi/pulumi": "dev", + } +} diff --git a/examples/examples_test.go b/examples/examples_test.go index f03b79f4..a1fe8a92 100644 --- a/examples/examples_test.go +++ b/examples/examples_test.go @@ -66,6 +66,23 @@ func TestAws(t *testing.T) { } } +func TestBrokenDockerfile(t *testing.T) { + cwd, err := os.Getwd() + if !assert.NoError(t, err) { + t.FailNow() + } + + opts := base.With(integration.ProgramTestOptions{ + Dependencies: []string{ + "@pulumi/docker", + }, + Dir: path.Join(cwd, "broken_dockerfile"), + ExpectFailure: true, + SkipRefresh: true, + }) + integration.ProgramTest(t, &opts) +} + func TestNginx(t *testing.T) { cwd, err := os.Getwd() if !assert.NoError(t, err) { @@ -139,4 +156,4 @@ func TestDockerfileWithMultipleTargets(t *testing.T) { Dir: path.Join(cwd, "dockerfile-with-targets"), }) integration.ProgramTest(t, &opts) -} \ No newline at end of file +} diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 2b5a76c8..40fec871 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -93,7 +93,7 @@ export interface DockerBuild { let dockerPasswordPromise: Promise | undefined; -function useDockerPasswordStdin(logResource: pulumi.Resource) { +function useDockerPasswordStdin(logResource: pulumi.Resource| undefined) { if (!dockerPasswordPromise) { dockerPasswordPromise = useDockerPasswordStdinWorker(); } @@ -157,8 +157,8 @@ export function buildAndPushImageAsync( export function buildAndPushImage( imageName: string, pathOrBuild: pulumi.Input, - repositoryUrl: pulumi.Input, - logResource: pulumi.Resource, + repositoryUrl: pulumi.Input | undefined, + logResource: pulumi.Resource | undefined, connectToRegistry?: () => pulumi.Input, skipPush: boolean = false): pulumi.Output { @@ -169,9 +169,9 @@ export function buildAndPushImage( // in `runWithUnknowns:true` to actually continue on in that case. return pulumi.output(pathOrBuild).apply(pathOrBuild => { const op = pulumi.output(repositoryUrl); - const res: pulumi.Output = (op).apply( - (u: string | undefined) => buildAndPushImageImpl(pathOrBuild, u), - /*runWithUnknowns:*/ true); + + // @ts-ignore Allow calling the 'runWithUnknowns' overload. + const res: pulumi.Output = op.apply(u => buildAndPushImageImpl(pathOrBuild, u), /*runWithUnknowns:*/ true); return res; }); @@ -208,7 +208,7 @@ export function buildAndPushImage( } } -function logEphemeral(message: string, logResource: pulumi.Resource) { +function logEphemeral(message: string, logResource: pulumi.Resource | undefined) { pulumi.log.info(message, logResource, /*streamId:*/ undefined, /*ephemeral:*/ true); } @@ -250,7 +250,7 @@ async function buildImage( baseImageName: string, pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined, - logResource: pulumi.Resource, + logResource: pulumi.Resource | undefined, connectToRegistry: (() => pulumi.Input) | undefined): Promise { // login immediately if we're going to have to actually communicate with a remote registry. @@ -300,7 +300,7 @@ async function buildImage( return buildResult; } -async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { +async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource | undefined): Promise { const { imageName: baseImageName, imageId, stages } = buildResult; const tag = utils.getImageNameAndTag(baseImageName).tag; @@ -364,7 +364,7 @@ async function pullCacheAsync( imageName: string, cacheFrom: pulumi.Unwrap, repoUrl: string, - logResource: pulumi.Resource): Promise { + logResource: pulumi.Resource | undefined): Promise { // Ensure that we have a repository URL. If we don't, we won't be able to pull anything. if (!repoUrl) { @@ -405,7 +405,7 @@ interface BuildResult { async function buildImageAsync( imageName: string, pathOrBuild: string | pulumi.Unwrap, - logResource: pulumi.Resource, + logResource: pulumi.Resource | undefined, cacheFrom: Promise): Promise { let build: pulumi.Unwrap; @@ -470,7 +470,7 @@ async function dockerBuild( imageName: string, build: pulumi.Unwrap, cacheFrom: Promise, - logResource: pulumi.Resource, + logResource: pulumi.Resource | undefined, target?: string): Promise { // Prepare the build arguments. @@ -516,7 +516,7 @@ interface LoginResult { // registry with that user, there's no need to do it again. const loginResults: LoginResult[] = []; -function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi.Resource): Promise { +function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi.Resource| undefined): Promise { const {registry: registryName, username, password} = registry; // See if we've issued an outstanding requests to login into this registry. If so, just @@ -557,7 +557,7 @@ function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi. async function tagAndPushImageAsync( imageName: string, repositoryUrl: string, tag: string | undefined, imageId: string | undefined, - logResource: pulumi.Resource): Promise { + logResource: pulumi.Resource | undefined): Promise { // Ensure we have a unique target name for this image, and tag and push to that unique target. await doTagAndPushAsync(createTaggedImageName(repositoryUrl, tag, imageId)); @@ -605,7 +605,7 @@ function getFailureMessage( async function runCommandThatMustSucceed( cmd: string, args: string[], - logResource: pulumi.Resource, + logResource: pulumi.Resource | undefined, reportFullCommandLine: boolean = true, stdin?: string, env?: { [name: string]: string }): Promise { @@ -643,7 +643,7 @@ async function runCommandThatMustSucceed( async function runCommandThatCanFail( cmd: string, args: string[], - logResource: pulumi.Resource, + logResource: pulumi.Resource | undefined, reportFullCommandLine: boolean, reportErrorAsWarning: boolean, stdin?: string, From 1d9cdf33dcefab3f1e7fec5697590751e5f2fd6e Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 11:55:07 -0800 Subject: [PATCH 03/21] Update CL --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2e259152..0e801e17 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,8 @@ ## HEAD (Unreleased) +* `docker.buildAndPushImage` will now build images during a `preview`, not just during an `update`. + This allows docker errors to be found earlier and more safely in the development cycle. + ## 1.2.0 (2020-01-29) * Upgrade to pulumi-terraform-bridge v1.6.4 From ca63d893685c80b179f56e1c58eb13d4398d3242 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 11:57:06 -0800 Subject: [PATCH 04/21] Revert --- examples/broken_dockerfile/index.ts | 2 +- sdk/nodejs/docker.ts | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/examples/broken_dockerfile/index.ts b/examples/broken_dockerfile/index.ts index ffd2893f..9318c385 100644 --- a/examples/broken_dockerfile/index.ts +++ b/examples/broken_dockerfile/index.ts @@ -15,4 +15,4 @@ import * as docker from "@pulumi/docker"; export const imageName = docker.buildAndPushImage( - "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined); + "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined!); diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 40fec871..c9b9462d 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -93,7 +93,7 @@ export interface DockerBuild { let dockerPasswordPromise: Promise | undefined; -function useDockerPasswordStdin(logResource: pulumi.Resource| undefined) { +function useDockerPasswordStdin(logResource: pulumi.Resource) { if (!dockerPasswordPromise) { dockerPasswordPromise = useDockerPasswordStdinWorker(); } @@ -158,7 +158,7 @@ export function buildAndPushImage( imageName: string, pathOrBuild: pulumi.Input, repositoryUrl: pulumi.Input | undefined, - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, connectToRegistry?: () => pulumi.Input, skipPush: boolean = false): pulumi.Output { @@ -208,7 +208,7 @@ export function buildAndPushImage( } } -function logEphemeral(message: string, logResource: pulumi.Resource | undefined) { +function logEphemeral(message: string, logResource: pulumi.Resource) { pulumi.log.info(message, logResource, /*streamId:*/ undefined, /*ephemeral:*/ true); } @@ -250,7 +250,7 @@ async function buildImage( baseImageName: string, pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined, - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, connectToRegistry: (() => pulumi.Input) | undefined): Promise { // login immediately if we're going to have to actually communicate with a remote registry. @@ -300,7 +300,7 @@ async function buildImage( return buildResult; } -async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource | undefined): Promise { +async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { const { imageName: baseImageName, imageId, stages } = buildResult; const tag = utils.getImageNameAndTag(baseImageName).tag; @@ -364,7 +364,7 @@ async function pullCacheAsync( imageName: string, cacheFrom: pulumi.Unwrap, repoUrl: string, - logResource: pulumi.Resource | undefined): Promise { + logResource: pulumi.Resource): Promise { // Ensure that we have a repository URL. If we don't, we won't be able to pull anything. if (!repoUrl) { @@ -405,7 +405,7 @@ interface BuildResult { async function buildImageAsync( imageName: string, pathOrBuild: string | pulumi.Unwrap, - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, cacheFrom: Promise): Promise { let build: pulumi.Unwrap; @@ -470,7 +470,7 @@ async function dockerBuild( imageName: string, build: pulumi.Unwrap, cacheFrom: Promise, - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, target?: string): Promise { // Prepare the build arguments. @@ -516,7 +516,7 @@ interface LoginResult { // registry with that user, there's no need to do it again. const loginResults: LoginResult[] = []; -function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi.Resource| undefined): Promise { +function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi.Resource): Promise { const {registry: registryName, username, password} = registry; // See if we've issued an outstanding requests to login into this registry. If so, just @@ -557,7 +557,7 @@ function loginToRegistry(registry: pulumi.Unwrap, logResource: pulumi. async function tagAndPushImageAsync( imageName: string, repositoryUrl: string, tag: string | undefined, imageId: string | undefined, - logResource: pulumi.Resource | undefined): Promise { + logResource: pulumi.Resource): Promise { // Ensure we have a unique target name for this image, and tag and push to that unique target. await doTagAndPushAsync(createTaggedImageName(repositoryUrl, tag, imageId)); @@ -605,7 +605,7 @@ function getFailureMessage( async function runCommandThatMustSucceed( cmd: string, args: string[], - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, reportFullCommandLine: boolean = true, stdin?: string, env?: { [name: string]: string }): Promise { @@ -643,7 +643,7 @@ async function runCommandThatMustSucceed( async function runCommandThatCanFail( cmd: string, args: string[], - logResource: pulumi.Resource | undefined, + logResource: pulumi.Resource, reportFullCommandLine: boolean, reportErrorAsWarning: boolean, stdin?: string, From 0adda8c3dcc8dfca5e4b0cbdc8585d889f8318b2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:00:46 -0800 Subject: [PATCH 05/21] revert --- sdk/nodejs/docker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index c9b9462d..70508d62 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -186,10 +186,6 @@ export function buildAndPushImage( repositoryUrl = undefined; } - if (repositoryUrl) { - checkRepositoryUrl(repositoryUrl); - } - logEphemeral("Starting docker build...", logResource); const buildResult = await buildImage(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); logEphemeral("Completed docker build", logResource); @@ -253,6 +249,10 @@ async function buildImage( logResource: pulumi.Resource, connectToRegistry: (() => pulumi.Input) | undefined): Promise { + if (repositoryUrl) { + checkRepositoryUrl(repositoryUrl); + } + // login immediately if we're going to have to actually communicate with a remote registry. // // We know we have to login if: From 238b42a54ef08cfe2d00d0a705629a93ca233102 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:04:22 -0800 Subject: [PATCH 06/21] Remove impossible code. --- sdk/nodejs/docker.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index f29b2b86..2b21a33d 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -269,9 +269,6 @@ async function buildAndPushImageWorkerAsync( // Next, build the image. const {imageId, stages} = await buildImageAsync(baseImageName, pathOrBuild, logResource, cacheFrom); - if (imageId === undefined) { - throw new Error("Internal error: docker build did not produce an imageId."); - } // Generate a name that uniquely will identify this built image. This is similar in purpose to // the name@digest form that can be normally be retrieved from a docker repository. However, From 27ab10cc1c925232efacd738036580511105db23 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:20:40 -0800 Subject: [PATCH 07/21] Simplify how we handle cache-from values when doing a pull. --- sdk/nodejs/docker.ts | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 2b21a33d..a1e77bcb 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -260,11 +260,11 @@ async function buildAndPushImageWorkerAsync( } // If the container specified a cacheFrom parameter, first set up the cached stages. - let cacheFrom = Promise.resolve(undefined); + let cacheFrom: string[] = []; if (pullFromCache) { const dockerBuild = >pathOrBuild; const cacheFromParam = (typeof dockerBuild.cacheFrom === "boolean" ? {} : dockerBuild.cacheFrom) || {}; - cacheFrom = pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl, logResource); + cacheFrom = await pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl, logResource); } // Next, build the image. @@ -329,11 +329,11 @@ async function pullCacheAsync( imageName: string, cacheFrom: pulumi.Unwrap, repoUrl: string, - logResource: pulumi.Resource): Promise { + logResource: pulumi.Resource): Promise { // Ensure that we have a repository URL. If we don't, we won't be able to pull anything. if (!repoUrl) { - return undefined; + return []; } pulumi.log.debug(`pulling cache for ${imageName} from ${repoUrl}`, logResource); @@ -370,7 +370,7 @@ async function buildImageAsync( imageName: string, pathOrBuild: string | pulumi.Unwrap, logResource: pulumi.Resource, - cacheFrom: Promise): Promise { + cacheFrom: string[]): Promise { let build: pulumi.Unwrap; if (typeof pathOrBuild === "string") { @@ -433,7 +433,7 @@ async function buildImageAsync( async function dockerBuild( imageName: string, build: pulumi.Unwrap, - cacheFrom: Promise, + cacheFrom: string[], logResource: pulumi.Resource, target?: string): Promise { @@ -451,9 +451,8 @@ async function dockerBuild( buildArgs.push(...["--target", build.target]); } if (build.cacheFrom) { - const cacheFromImages = await cacheFrom; - if (cacheFromImages && cacheFromImages.length) { - buildArgs.push(...["--cache-from", cacheFromImages.join()]); + if (cacheFrom.length) { + buildArgs.push(...["--cache-from", cacheFrom.join()]); } } if (build.extraOptions) { From 32faa042e4898a6c1b4ce12306bc15355af108cd Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:28:56 -0800 Subject: [PATCH 08/21] Simplify further --- sdk/nodejs/docker.ts | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index a1e77bcb..a055a895 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -450,10 +450,8 @@ async function dockerBuild( if (build.target) { buildArgs.push(...["--target", build.target]); } - if (build.cacheFrom) { - if (cacheFrom.length) { - buildArgs.push(...["--cache-from", cacheFrom.join()]); - } + if (cacheFrom.length) { + buildArgs.push(...["--cache-from", cacheFrom.join()]); } if (build.extraOptions) { buildArgs.push(...build.extraOptions); From 1a36f240977d282f89a73c48324da2a557b2078d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:30:45 -0800 Subject: [PATCH 09/21] Revert --- examples/aws/index.ts | 3 --- 1 file changed, 3 deletions(-) diff --git a/examples/aws/index.ts b/examples/aws/index.ts index 380a8231..e0e818f7 100644 --- a/examples/aws/index.ts +++ b/examples/aws/index.ts @@ -66,6 +66,3 @@ const image3 = new docker.Image("path-example", { export const image1Name = image1.imageName; export const image2Name = image2.imageName; export const image3Name = image3.imageName; - -export const image4Name = docker.buildAndPushImage( - "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined); From 37916a8d02dd7db932a1502b76296a4b92f196f1 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:31:40 -0800 Subject: [PATCH 10/21] Update test --- examples/broken_dockerfile/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/examples/broken_dockerfile/index.ts b/examples/broken_dockerfile/index.ts index 9318c385..aeb17240 100644 --- a/examples/broken_dockerfile/index.ts +++ b/examples/broken_dockerfile/index.ts @@ -14,5 +14,6 @@ import * as docker from "@pulumi/docker"; +// This should fail during preview as ./app points at a broken docker file. export const imageName = docker.buildAndPushImage( "test-name", "./app", /*repositoryUrl:*/ undefined, /*logResource:*/ undefined!); From a479dcd94fd0f6502ba90fbf8f6941b098e0614d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:32:08 -0800 Subject: [PATCH 11/21] Unwrap --- sdk/nodejs/docker.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 5585af54..f249e375 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -176,8 +176,7 @@ export function buildAndPushImage( return res; }); - function helper(pathOrBuild: string | pulumi.Unwrap, - repositoryUrl: string | undefined) { + function helper(pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined) { return buildAndPushImageWorker(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); } } From cffc25cea1376258967719abcba7e46604d02cf3 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:32:46 -0800 Subject: [PATCH 12/21] Unwrap --- sdk/nodejs/docker.ts | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index f249e375..052726a8 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -177,7 +177,7 @@ export function buildAndPushImage( }); function helper(pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined) { - return buildAndPushImageWorker(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); + return buildAndPushImageWorkerAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); } } @@ -219,13 +219,13 @@ export function checkRepositoryUrl(repositoryUrl: string) { } } -async function buildAndPushImageWorker( - imageName: string, - pathOrBuild: string | pulumi.Unwrap, - repositoryUrl: string | undefined, - logResource: pulumi.Resource, - connectToRegistry: (() => pulumi.Input) | undefined, - skipPush: boolean): Promise { +async function buildAndPushImageWorkerAsync( + imageName: string, + pathOrBuild: string | pulumi.Unwrap, + repositoryUrl: string | undefined, + logResource: pulumi.Resource, + connectToRegistry: (() => pulumi.Input) | undefined, + skipPush: boolean): Promise { // if we got an unknown repository url, just set to undefined for the remainder of // processing. The rest of the code can handle that. From 85558962d521b2fac49c0b439d67617e2d5d0c22 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:34:17 -0800 Subject: [PATCH 13/21] Docs --- sdk/nodejs/docker.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 052726a8..42fa6c8b 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -237,10 +237,10 @@ async function buildAndPushImageWorkerAsync( checkRepositoryUrl(repositoryUrl); } - // Immediately start pulling from docker if we can. - const cacheFrom = await pullFromCache(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); + // First, login and pulling from docker if we can. + const cacheFrom = await loginAndPullFromCache(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); - // Then + // Then actually kick off the build. logEphemeral("Starting docker build...", logResource); const buildResult = await buildImage(imageName, pathOrBuild, cacheFrom, logResource); logEphemeral("Completed docker build", logResource); @@ -251,6 +251,7 @@ async function buildAndPushImageWorkerAsync( return imageName; } + // Finally, if this a real update, push the built images to docker. logEphemeral("Starting docker push...", logResource); const result = await pushImage(repositoryUrl, buildResult, logResource); logEphemeral("Completed docker build", logResource); @@ -258,7 +259,7 @@ async function buildAndPushImageWorkerAsync( return result; } -async function pullFromCache( +async function loginAndPullFromCache( baseImageName: string, pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined, From ddbfaf6b7b363f967cf85015b69e80baab2a40f6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:35:19 -0800 Subject: [PATCH 14/21] Simplify --- sdk/nodejs/docker.ts | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 42fa6c8b..75df49a4 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -295,15 +295,15 @@ async function loginAndPullFromCache( } // If the container specified a cacheFrom parameter, first set up the cached stages. - if (!pullFromCache) { - return []; - } + if (pullFromCache) { + const dockerBuild = >pathOrBuild; + const cacheFromParam = (typeof dockerBuild.cacheFrom === "boolean" ? {} : dockerBuild.cacheFrom) || {}; - const dockerBuild = >pathOrBuild; - const cacheFromParam = (typeof dockerBuild.cacheFrom === "boolean" ? {} : dockerBuild.cacheFrom) || {}; + // pullFromCache is only true if repositoryUrl is present. + return await pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl!, logResource); + } - // pullFromCache is only true if repositoryUrl is present. - return await pullCacheAsync(baseImageName, cacheFromParam, repositoryUrl!, logResource); + return []; } async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { From 5f779eae38b950eed47322c8d9ef0654a5f3c176 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:36:09 -0800 Subject: [PATCH 15/21] Consistent naming --- sdk/nodejs/docker.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 75df49a4..01b36f6a 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -238,11 +238,11 @@ async function buildAndPushImageWorkerAsync( } // First, login and pulling from docker if we can. - const cacheFrom = await loginAndPullFromCache(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); + const cacheFrom = await loginAndPullFromCacheAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); // Then actually kick off the build. logEphemeral("Starting docker build...", logResource); - const buildResult = await buildImage(imageName, pathOrBuild, cacheFrom, logResource); + const buildResult = await buildImageAsync(imageName, pathOrBuild, cacheFrom, logResource); logEphemeral("Completed docker build", logResource); // If we have no repository url, then we definitely can't push our build result. Same if @@ -253,13 +253,13 @@ async function buildAndPushImageWorkerAsync( // Finally, if this a real update, push the built images to docker. logEphemeral("Starting docker push...", logResource); - const result = await pushImage(repositoryUrl, buildResult, logResource); + const result = await pushImageAsync(repositoryUrl, buildResult, logResource); logEphemeral("Completed docker build", logResource); return result; } -async function loginAndPullFromCache( +async function loginAndPullFromCacheAsync( baseImageName: string, pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined, @@ -306,7 +306,7 @@ async function loginAndPullFromCache( return []; } -async function pushImage(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { +async function pushImageAsync(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { const { imageName: baseImageName, imageId, stages } = buildResult; const tag = utils.getImageNameAndTag(baseImageName).tag; @@ -408,7 +408,7 @@ interface BuildResult { stages: string[]; } -async function buildImage( +async function buildImageAsync( imageName: string, pathOrBuild: string | pulumi.Unwrap, cacheFrom: string[], From 465e013d06e09f0da947d44594f514ae6b27ce32 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:41:22 -0800 Subject: [PATCH 16/21] Revert --- sdk/nodejs/docker.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 01b36f6a..c333c2f4 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -220,7 +220,7 @@ export function checkRepositoryUrl(repositoryUrl: string) { } async function buildAndPushImageWorkerAsync( - imageName: string, + baseImageName: string, pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined, logResource: pulumi.Resource, @@ -238,17 +238,17 @@ async function buildAndPushImageWorkerAsync( } // First, login and pulling from docker if we can. - const cacheFrom = await loginAndPullFromCacheAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); + const cacheFrom = await loginAndPullFromCacheAsync(baseImageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry); // Then actually kick off the build. logEphemeral("Starting docker build...", logResource); - const buildResult = await buildImageAsync(imageName, pathOrBuild, cacheFrom, logResource); + const buildResult = await buildImageAsync(baseImageName, pathOrBuild, cacheFrom, logResource); logEphemeral("Completed docker build", logResource); // If we have no repository url, then we definitely can't push our build result. Same if // we're in preview. if (skipPush || !repositoryUrl || pulumi.runtime.isDryRun()) { - return imageName; + return baseImageName; } // Finally, if this a real update, push the built images to docker. From 6564a4129b123356adcb5c4b1e7c3c887fce4a91 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:42:14 -0800 Subject: [PATCH 17/21] Simplify --- sdk/nodejs/docker.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index c333c2f4..059e18ee 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -177,6 +177,9 @@ export function buildAndPushImage( }); function helper(pathOrBuild: string | pulumi.Unwrap, repositoryUrl: string | undefined) { + // if we got an unknown repository url, just set to undefined for the remainder of + // processing. The rest of the code can handle that. + repositoryUrl = pulumi.containsUnknowns(repositoryUrl) ? undefined : repositoryUrl; return buildAndPushImageWorkerAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); } } @@ -227,12 +230,6 @@ async function buildAndPushImageWorkerAsync( connectToRegistry: (() => pulumi.Input) | undefined, skipPush: boolean): Promise { - // if we got an unknown repository url, just set to undefined for the remainder of - // processing. The rest of the code can handle that. - if (pulumi.containsUnknowns(repositoryUrl)) { - repositoryUrl = undefined; - } - if (repositoryUrl) { checkRepositoryUrl(repositoryUrl); } From e2420a9aeeee9bf77e5157359d3b8367fb3d1f83 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:47:06 -0800 Subject: [PATCH 18/21] Improve UI message --- sdk/nodejs/docker.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 059e18ee..d543410f 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -240,18 +240,18 @@ async function buildAndPushImageWorkerAsync( // Then actually kick off the build. logEphemeral("Starting docker build...", logResource); const buildResult = await buildImageAsync(baseImageName, pathOrBuild, cacheFrom, logResource); - logEphemeral("Completed docker build", logResource); // If we have no repository url, then we definitely can't push our build result. Same if // we're in preview. if (skipPush || !repositoryUrl || pulumi.runtime.isDryRun()) { + logEphemeral("Completed docker build (without pushing)", logResource); return baseImageName; } // Finally, if this a real update, push the built images to docker. logEphemeral("Starting docker push...", logResource); const result = await pushImageAsync(repositoryUrl, buildResult, logResource); - logEphemeral("Completed docker build", logResource); + logEphemeral("Completed docker build and push", logResource); return result; } From 35ef5bbae7bd580936b0ff933bc923b1adde8a5c Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:47:35 -0800 Subject: [PATCH 19/21] Revert --- sdk/nodejs/docker.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index d543410f..514862db 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -239,7 +239,7 @@ async function buildAndPushImageWorkerAsync( // Then actually kick off the build. logEphemeral("Starting docker build...", logResource); - const buildResult = await buildImageAsync(baseImageName, pathOrBuild, cacheFrom, logResource); + const buildResult = await buildImageAsync(baseImageName, pathOrBuild, logResource, cacheFrom); // If we have no repository url, then we definitely can't push our build result. Same if // we're in preview. @@ -408,8 +408,8 @@ interface BuildResult { async function buildImageAsync( imageName: string, pathOrBuild: string | pulumi.Unwrap, - cacheFrom: string[], - logResource: pulumi.Resource): Promise { + logResource: pulumi.Resource, + cacheFrom: string[]): Promise { let build: pulumi.Unwrap; if (typeof pathOrBuild === "string") { From 2833fb1c561592c9c8124e7b5ed9a944c2ba1a6d Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 12:48:47 -0800 Subject: [PATCH 20/21] Revert --- sdk/nodejs/docker.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 514862db..47bb254a 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -250,7 +250,7 @@ async function buildAndPushImageWorkerAsync( // Finally, if this a real update, push the built images to docker. logEphemeral("Starting docker push...", logResource); - const result = await pushImageAsync(repositoryUrl, buildResult, logResource); + const result = await pushImageAsync(baseImageName, repositoryUrl, buildResult, logResource); logEphemeral("Completed docker build and push", logResource); return result; @@ -303,8 +303,8 @@ async function loginAndPullFromCacheAsync( return []; } -async function pushImageAsync(repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { - const { imageName: baseImageName, imageId, stages } = buildResult; +async function pushImageAsync(baseImageName: string, repositoryUrl: string, buildResult: BuildResult, logResource: pulumi.Resource): Promise { + const { imageId, stages } = buildResult; const tag = utils.getImageNameAndTag(baseImageName).tag; @@ -400,7 +400,6 @@ async function pullCacheAsync( } interface BuildResult { - imageName: string; imageId: string; stages: string[]; } @@ -466,7 +465,7 @@ async function buildImageAsync( const colonIndex = imageId.lastIndexOf(":"); imageId = colonIndex < 0 ? imageId : imageId.substr(colonIndex + 1); - return { imageName, imageId, stages }; + return { imageId, stages }; } async function dockerBuild( From c28858bf82b8d282c0c03e9fd5233ac891a50537 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 7 Feb 2020 13:09:17 -0800 Subject: [PATCH 21/21] Add user-level option to control if we should run docker builds during preview. --- sdk/nodejs/docker.ts | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/sdk/nodejs/docker.ts b/sdk/nodejs/docker.ts index 47bb254a..377e2d2a 100644 --- a/sdk/nodejs/docker.ts +++ b/sdk/nodejs/docker.ts @@ -138,9 +138,10 @@ export function buildAndPushImageAsync( repositoryUrl: pulumi.Input, logResource: pulumi.Resource, connectToRegistry?: () => pulumi.Input, - skipPush: boolean = false): Promise { + skipPush: boolean = false, + runDuringPreview: boolean = true): Promise { - const output = buildAndPushImage(baseImageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); + const output = buildAndPushImage(baseImageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush, runDuringPreview); // Ugly, but necessary to bridge between the proper Output-returning function and this // Promise-returning one. @@ -160,7 +161,8 @@ export function buildAndPushImage( repositoryUrl: pulumi.Input | undefined, logResource: pulumi.Resource, connectToRegistry?: () => pulumi.Input, - skipPush: boolean = false): pulumi.Output { + skipPush: boolean = false, + runDuringPreview: boolean = true): pulumi.Output { // We do something rather interesting here. We do not want to proceed if we don't actually have // a value yet for `pathOrBuild`. So we do a normal `ouput(...).apply(...)`. However, we *do* @@ -171,7 +173,7 @@ export function buildAndPushImage( const op = pulumi.output(repositoryUrl); // @ts-ignore Allow calling the 'runWithUnknowns' overload. - const res: pulumi.Output = op.apply(u => helper(pathOrBuild, u), /*runWithUnknowns:*/ true); + const res: pulumi.Output = op.apply(u => helper(pathOrBuild, u), /*runWithUnknowns:*/ runDuringPreview); return res; }); @@ -180,7 +182,7 @@ export function buildAndPushImage( // if we got an unknown repository url, just set to undefined for the remainder of // processing. The rest of the code can handle that. repositoryUrl = pulumi.containsUnknowns(repositoryUrl) ? undefined : repositoryUrl; - return buildAndPushImageWorkerAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush); + return buildAndPushImageWorkerAsync(imageName, pathOrBuild, repositoryUrl, logResource, connectToRegistry, skipPush, runDuringPreview); } } @@ -228,7 +230,14 @@ async function buildAndPushImageWorkerAsync( repositoryUrl: string | undefined, logResource: pulumi.Resource, connectToRegistry: (() => pulumi.Input) | undefined, - skipPush: boolean): Promise { + skipPush: boolean, + runDuringPreview: boolean): Promise { + + const isPreview = pulumi.runtime.isDryRun() + if (!runDuringPreview && isPreview) { + logEphemeral("Skipping docker build during preview", logResource); + return baseImageName; + } if (repositoryUrl) { checkRepositoryUrl(repositoryUrl); @@ -243,7 +252,7 @@ async function buildAndPushImageWorkerAsync( // If we have no repository url, then we definitely can't push our build result. Same if // we're in preview. - if (skipPush || !repositoryUrl || pulumi.runtime.isDryRun()) { + if (skipPush || !repositoryUrl || isPreview) { logEphemeral("Completed docker build (without pushing)", logResource); return baseImageName; }