diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java index 4f999aa979..cea467bfbb 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/api/Containerizer.java @@ -17,6 +17,7 @@ package com.google.cloud.tools.jib.api; // TODO: Move to com.google.cloud.tools.jib once that package is cleaned up. +import com.google.cloud.tools.jib.builder.steps.BuildResult; import com.google.cloud.tools.jib.builder.steps.StepsRunner; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.configuration.ImageConfiguration; @@ -31,6 +32,7 @@ import java.util.HashSet; import java.util.Optional; import java.util.Set; +import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.function.Consumer; @@ -67,18 +69,7 @@ public static Containerizer to(RegistryImage registryImage) { .build(); Function stepsRunnerFactory = - buildConfiguration -> - StepsRunner.begin(buildConfiguration) - .retrieveTargetRegistryCredentials() - .authenticatePush() - .pullBaseImage() - .pullAndCacheBaseImageLayers() - .pushBaseImageLayers() - .buildAndCacheApplicationLayers() - .buildImage() - .pushContainerConfiguration() - .pushApplicationLayers() - .pushImage(); + buildConfiguration -> StepsRunner.begin(buildConfiguration).registryPushSteps(); return new Containerizer( DESCRIPTION_FOR_DOCKER_REGISTRY, imageConfiguration, stepsRunnerFactory, true); @@ -101,12 +92,7 @@ public static Containerizer to(DockerDaemonImage dockerDaemonImage) { Function stepsRunnerFactory = buildConfiguration -> - StepsRunner.begin(buildConfiguration) - .pullBaseImage() - .pullAndCacheBaseImageLayers() - .buildAndCacheApplicationLayers() - .buildImage() - .loadDocker(dockerClientBuilder.build()); + StepsRunner.begin(buildConfiguration).dockerLoadSteps(dockerClientBuilder.build()); return new Containerizer( DESCRIPTION_FOR_DOCKER_DAEMON, imageConfiguration, stepsRunnerFactory, false); @@ -124,12 +110,7 @@ public static Containerizer to(TarImage tarImage) { Function stepsRunnerFactory = buildConfiguration -> - StepsRunner.begin(buildConfiguration) - .pullBaseImage() - .pullAndCacheBaseImageLayers() - .buildAndCacheApplicationLayers() - .buildImage() - .writeTarFile(tarImage.getOutputFile()); + StepsRunner.begin(buildConfiguration).tarBuildSteps(tarImage.getOutputFile()); return new Containerizer( DESCRIPTION_FOR_TARBALL, imageConfiguration, stepsRunnerFactory, false); @@ -303,9 +284,8 @@ Path getApplicationLayersCacheDirectory() throws CacheDirectoryCreationException if (applicationLayersCacheDirectory == null) { // Uses a temporary directory if application layers cache directory is not set. try { - Path temporaryDirectory = Files.createTempDirectory(null); - temporaryDirectory.toFile().deleteOnExit(); - this.applicationLayersCacheDirectory = temporaryDirectory; + applicationLayersCacheDirectory = Files.createTempDirectory(null); + applicationLayersCacheDirectory.toFile().deleteOnExit(); } catch (IOException ex) { throw new CacheDirectoryCreationException(ex); @@ -338,7 +318,8 @@ ImageConfiguration getImageConfiguration() { return imageConfiguration; } - StepsRunner createStepsRunner(BuildConfiguration buildConfiguration) { - return stepsRunnerFactory.apply(buildConfiguration); + BuildResult run(BuildConfiguration buildConfiguration) + throws ExecutionException, InterruptedException { + return stepsRunnerFactory.apply(buildConfiguration).run(); } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/api/JibContainerBuilder.java b/jib-core/src/main/java/com/google/cloud/tools/jib/api/JibContainerBuilder.java index 70506c17c3..865ffde866 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/api/JibContainerBuilder.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/api/JibContainerBuilder.java @@ -475,7 +475,7 @@ JibContainer containerize( try (TimerEventDispatcher ignored = new TimerEventDispatcher(eventHandlers, containerizer.getDescription())) { - BuildResult result = containerizer.createStepsRunner(buildConfiguration).run(); + BuildResult result = containerizer.run(buildConfiguration); return new JibContainer(result.getImageDigest(), result.getImageId()); } catch (ExecutionException ex) { diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncDependencies.java b/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncDependencies.java deleted file mode 100644 index 7f43957e94..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncDependencies.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2018 Google LLC. - * - * 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. - */ - -package com.google.cloud.tools.jib.async; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Callable; - -/** - * Builds a list of dependency {@link ListenableFuture}s to wait on before calling a {@link - * Callable}. - */ -public class AsyncDependencies { - - /** - * Initialize with a {@link ListeningExecutorService}. - * - * @param listeningExecutorService the {@link ListeningExecutorService} - * @return a new {@link AsyncDependencies} - */ - public static AsyncDependencies using(ListeningExecutorService listeningExecutorService) { - return new AsyncDependencies(listeningExecutorService); - } - - private final ListeningExecutorService listeningExecutorService; - - /** Stores the list of {@link ListenableFuture}s to wait on. */ - private final List> futures = new ArrayList<>(); - - private AsyncDependencies(ListeningExecutorService listeningExecutorService) { - this.listeningExecutorService = listeningExecutorService; - } - - /** - * Adds the future of an {@link AsyncStep}. - * - * @param asyncStep the {@link AsyncStep} - * @return this - */ - public AsyncDependencies addStep(AsyncStep asyncStep) { - futures.add(asyncStep.getFuture()); - return this; - } - - /** - * Adds the futures of a list of {@link AsyncStep}s. - * - * @param asyncSteps the {@link AsyncStep}s - * @return this - */ - public AsyncDependencies addSteps(List> asyncSteps) { - asyncSteps.forEach(this::addStep); - return this; - } - - /** - * Creates the {@link ListenableFuture} which will return the result of calling {@code combiner} - * when all the added futures succeed. - * - * @param combiner the {@link Callable} - * @param the return type of {@code combiner} - * @return a {@link ListenableFuture} to handle completion of the call to {@code combiner} - */ - public ListenableFuture whenAllSucceed(Callable combiner) { - return Futures.whenAllSucceed(futures).call(combiner, listeningExecutorService); - } -} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncStep.java deleted file mode 100644 index bab5363449..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncStep.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2018 Google LLC. - * - * 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. - */ - -package com.google.cloud.tools.jib.async; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import java.util.concurrent.Callable; - -/** - * Holds the future for an asynchronously-running step. Implementations should: - * - *
    - *
  1. Be immutable - *
  2. Construct with the dependent {@link AsyncStep}s and submit a {@link Callable} to the {@link - * ListeningExecutorService} to run after all its dependent {@link AsyncStep}s (for example, - * by using {@link Futures#whenAllSucceed}) - *
  3. Have {@link #getFuture} return the submitted future - *
- * - * @param the object type passed on by this step - */ -public interface AsyncStep { - - /** @return the submitted future */ - // TODO: Consider changing this to be orchestrated by an AsyncStepsBuilder. - ListenableFuture getFuture(); -} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncSteps.java b/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncSteps.java deleted file mode 100644 index 0bb3771a0e..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/async/AsyncSteps.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2018 Google LLC. - * - * 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. - */ - -package com.google.cloud.tools.jib.async; - -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; - -/** Static methods for {@link AsyncStep}. */ -public class AsyncSteps { - - public static AsyncStep immediate(T returnValue) { - ListenableFuture future = Futures.immediateFuture(returnValue); - return () -> future; - } - - private AsyncSteps() {} -} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/async/NonBlockingSteps.java b/jib-core/src/main/java/com/google/cloud/tools/jib/async/NonBlockingSteps.java deleted file mode 100644 index d65b3f5c9a..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/async/NonBlockingSteps.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2018 Google LLC. - * - * 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. - */ - -package com.google.cloud.tools.jib.async; - -import com.google.common.util.concurrent.Futures; -import java.util.concurrent.ExecutionException; - -/** - * Static utility for checking at runtime that the caller attempts to get a result only from a - * completed {@link AsyncStep} by otherwise throwing a runtime exception. - */ -public class NonBlockingSteps { - - /** - * Gets the completed computation result of {@code asyncStep}. - * - * @param the type of the computation result of {@code asyncStep} - * @param asyncStep completed {@link AsyncStep} - * @return the completed computation result - * @throws ExecutionException if the {@code Future} failed with an exception - * @throws IllegalStateException if {@code asyncStep} has not been completed - */ - public static T get(AsyncStep asyncStep) throws ExecutionException { - return Futures.getDone(asyncStep.getFuture()); - } - - private NonBlockingSteps() {} -} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/AuthenticatePushStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/AuthenticatePushStep.java index 196da2b4d4..2510c5f3d5 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/AuthenticatePushStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/AuthenticatePushStep.java @@ -19,19 +19,13 @@ import com.google.cloud.tools.jib.api.Credential; import com.google.cloud.tools.jib.api.InsecureRegistryException; import com.google.cloud.tools.jib.api.RegistryException; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.http.Authorization; import com.google.cloud.tools.jib.registry.RegistryAuthenticator; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; /** @@ -40,42 +34,26 @@ * @see https://docs.docker.com/registry/spec/auth/token/ */ -class AuthenticatePushStep implements AsyncStep, Callable { +class AuthenticatePushStep implements Callable { - private static final String DESCRIPTION = "Authenticating with push to %s"; + private static final String DESCRIPTION = "Authenticating push to %s"; private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - - private final RetrieveRegistryCredentialsStep retrieveTargetRegistryCredentialsStep; - - private final ListenableFuture listenableFuture; + private final Credential registryCredential; AuthenticatePushStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - RetrieveRegistryCredentialsStep retrieveTargetRegistryCredentialsStep) { + Credential registryCredential) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.retrieveTargetRegistryCredentialsStep = retrieveTargetRegistryCredentialsStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(retrieveTargetRegistryCredentialsStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; + this.registryCredential = registryCredential; } @Override @Nullable - public Authorization call() throws ExecutionException, IOException, RegistryException { - Credential registryCredential = NonBlockingSteps.get(retrieveTargetRegistryCredentialsStep); - + public Authorization call() throws IOException, RegistryException { String registry = buildConfiguration.getTargetImageConfiguration().getImageRegistry(); try (ProgressEventDispatcher ignored = progressEventDispatcherFactory.create("authenticating push to " + registry, 1); diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStep.java index 6a2187cee8..4a4de43f40 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStep.java @@ -18,7 +18,6 @@ import com.google.cloud.tools.jib.api.LayerConfiguration; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncStep; import com.google.cloud.tools.jib.blob.Blob; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; @@ -28,30 +27,27 @@ import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.image.ReproducibleLayerBuilder; import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.Optional; import java.util.concurrent.Callable; /** Builds and caches application layers. */ -class BuildAndCacheApplicationLayerStep implements AsyncStep, Callable { +class BuildAndCacheApplicationLayerStep implements Callable { - private static final String DESCRIPTION = "Building application layers"; + private static final String DESCRIPTION = "Preparing application layer builders"; /** * Makes a list of {@link BuildAndCacheApplicationLayerStep} for dependencies, resources, and * classes layers. Optionally adds an extra layer if configured to do so. */ static ImmutableList makeList( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory) { int layerCount = buildConfiguration.getLayerConfigurations().size(); try (ProgressEventDispatcher progressEventDispatcher = progressEventDispatcherFactory.create( - "setting up to build application layers", layerCount); + "preparing application layer builders", layerCount); TimerEventDispatcher ignored = new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { ImmutableList.Builder buildAndCacheApplicationLayerSteps = @@ -64,7 +60,6 @@ static ImmutableList makeList( buildAndCacheApplicationLayerSteps.add( new BuildAndCacheApplicationLayerStep( - listeningExecutorService, buildConfiguration, progressEventDispatcher.newChildProducer(), layerConfiguration.getName(), @@ -79,38 +74,28 @@ static ImmutableList makeList( private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - private final String layerType; + private final String layerName; private final LayerConfiguration layerConfiguration; - private final ListenableFuture listenableFuture; - private BuildAndCacheApplicationLayerStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - String layerType, + String layerName, LayerConfiguration layerConfiguration) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.layerType = layerType; + this.layerName = layerName; this.layerConfiguration = layerConfiguration; - - listenableFuture = listeningExecutorService.submit(this); } @Override - public ListenableFuture getFuture() { - return listenableFuture; - } - - @Override - public CachedLayer call() throws IOException, CacheCorruptedException { - String description = "Building " + layerType + " layer"; + public CachedLayerAndName call() throws IOException, CacheCorruptedException { + String description = "Building " + layerName + " layer"; buildConfiguration.getEventHandlers().dispatch(LogEvent.progress(description + "...")); try (ProgressEventDispatcher ignored = - progressEventDispatcherFactory.create("building " + layerType + " layer", 1); + progressEventDispatcherFactory.create("building " + layerName + " layer", 1); TimerEventDispatcher ignored2 = new TimerEventDispatcher(buildConfiguration.getEventHandlers(), description)) { Cache cache = buildConfiguration.getApplicationLayersCache(); @@ -119,7 +104,7 @@ public CachedLayer call() throws IOException, CacheCorruptedException { Optional optionalCachedLayer = cache.retrieve(layerConfiguration.getLayerEntries()); if (optionalCachedLayer.isPresent()) { - return optionalCachedLayer.get(); + return new CachedLayerAndName(optionalCachedLayer.get(), layerName); } Blob layerBlob = new ReproducibleLayerBuilder(layerConfiguration.getLayerEntries()).build(); @@ -130,11 +115,7 @@ public CachedLayer call() throws IOException, CacheCorruptedException { .getEventHandlers() .dispatch(LogEvent.debug(description + " built " + cachedLayer.getDigest())); - return cachedLayer; + return new CachedLayerAndName(cachedLayer, layerName); } } - - String getLayerType() { - return layerType; - } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java index 644eb5f3d4..bb3783eb75 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/BuildImageStep.java @@ -18,9 +18,6 @@ import com.google.cloud.tools.jib.ProjectInfo; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; @@ -28,81 +25,51 @@ import com.google.cloud.tools.jib.image.Image; import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; import com.google.cloud.tools.jib.image.json.HistoryEntry; +import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.time.Instant; import java.util.List; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; /** Builds a model {@link Image}. */ -class BuildImageStep implements AsyncStep>, Callable> { +class BuildImageStep implements Callable { private static final String DESCRIPTION = "Building container configuration"; - private final ListeningExecutorService listeningExecutorService; private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - private final PullBaseImageStep pullBaseImageStep; - private final PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep; - private final ImmutableList buildAndCacheApplicationLayerSteps; - - private final ListenableFuture> listenableFuture; + private final Image baseImage; + private final List baseImageLayers; + private final List applicationLayers; BuildImageStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - PullBaseImageStep pullBaseImageStep, - PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep, - ImmutableList buildAndCacheApplicationLayerSteps) { - this.listeningExecutorService = listeningExecutorService; + Image baseImage, + List baseImageLayers, + List applicationLayers) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.pullBaseImageStep = pullBaseImageStep; - this.pullAndCacheBaseImageLayersStep = pullAndCacheBaseImageLayersStep; - this.buildAndCacheApplicationLayerSteps = buildAndCacheApplicationLayerSteps; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(pullBaseImageStep) - .addStep(pullAndCacheBaseImageLayersStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture> getFuture() { - return listenableFuture; + this.baseImage = baseImage; + this.baseImageLayers = baseImageLayers; + this.applicationLayers = applicationLayers; } @Override - public AsyncStep call() throws ExecutionException { - ListenableFuture future = - AsyncDependencies.using(listeningExecutorService) - .addSteps(NonBlockingSteps.get(pullAndCacheBaseImageLayersStep)) - .addSteps(buildAndCacheApplicationLayerSteps) - .whenAllSucceed(this::afterCachedLayerSteps); - return () -> future; - } - - private Image afterCachedLayerSteps() throws ExecutionException, LayerPropertyNotFoundException { + public Image call() throws LayerPropertyNotFoundException { try (ProgressEventDispatcher ignored = progressEventDispatcherFactory.create("building image format", 1); TimerEventDispatcher ignored2 = new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { // Constructs the image. Image.Builder imageBuilder = Image.builder(buildConfiguration.getTargetFormat()); - Image baseImage = NonBlockingSteps.get(pullBaseImageStep).getBaseImage(); ContainerConfiguration containerConfiguration = buildConfiguration.getContainerConfiguration(); // Base image layers - List baseImageLayers = - NonBlockingSteps.get(pullAndCacheBaseImageLayersStep); - for (PullAndCacheBaseImageLayerStep pullAndCacheBaseImageLayerStep : baseImageLayers) { - imageBuilder.addLayer(NonBlockingSteps.get(pullAndCacheBaseImageLayerStep)); + for (CachedLayerAndName baseImageLayer : baseImageLayers) { + imageBuilder.addLayer(baseImageLayer.getCachedLayer()); } // Passthrough config and count non-empty history entries @@ -137,16 +104,15 @@ private Image afterCachedLayerSteps() throws ExecutionException, LayerPropertyNo } // Add built layers/configuration - for (BuildAndCacheApplicationLayerStep buildAndCacheApplicationLayerStep : - buildAndCacheApplicationLayerSteps) { + for (CachedLayerAndName applicationLayer : applicationLayers) { imageBuilder - .addLayer(NonBlockingSteps.get(buildAndCacheApplicationLayerStep)) + .addLayer(applicationLayer.getCachedLayer()) .addHistory( HistoryEntry.builder() .setCreationTimestamp(layerCreationTime) .setAuthor("Jib") .setCreatedBy(buildConfiguration.getToolName() + ":" + ProjectInfo.VERSION) - .setComment(buildAndCacheApplicationLayerStep.getLayerType()) + .setComment(Verify.verifyNotNull(applicationLayer.getName())) .build()); } if (containerConfiguration != null) { diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/CachedLayerAndName.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/CachedLayerAndName.java new file mode 100644 index 0000000000..eed59fc14e --- /dev/null +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/CachedLayerAndName.java @@ -0,0 +1,41 @@ +/* + * Copyright 2019 Google LLC. + * + * 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. + */ + +package com.google.cloud.tools.jib.builder.steps; + +import com.google.cloud.tools.jib.cache.CachedLayer; +import javax.annotation.Nullable; + +/** Simple structure to hold a pair of {#link CachedLayer} and its string name. */ +class CachedLayerAndName { + + private CachedLayer cachedLayer; + @Nullable private String name; + + CachedLayerAndName(CachedLayer cachedLayer, @Nullable String name) { + this.cachedLayer = cachedLayer; + this.name = name; + } + + CachedLayer getCachedLayer() { + return cachedLayer; + } + + @Nullable + String getName() { + return name; + } +} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/LoadDockerStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/LoadDockerStep.java index b8f71bd167..9663669898 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/LoadDockerStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/LoadDockerStep.java @@ -18,91 +18,48 @@ import com.google.cloud.tools.jib.api.ImageReference; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.docker.ImageTarball; +import com.google.cloud.tools.jib.event.EventHandlers; import com.google.cloud.tools.jib.image.Image; -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; /** Adds image layers to a tarball and loads into Docker daemon. */ -class LoadDockerStep implements AsyncStep, Callable { +class LoadDockerStep implements Callable { - private final ListeningExecutorService listeningExecutorService; private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; private final DockerClient dockerClient; - - private final PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep; - private final ImmutableList buildAndCacheApplicationLayerSteps; - private final BuildImageStep buildImageStep; - - private final ListenableFuture listenableFuture; + private final Image builtImage; LoadDockerStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, DockerClient dockerClient, - PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep, - ImmutableList buildAndCacheApplicationLayerSteps, - BuildImageStep buildImageStep) { - this.listeningExecutorService = listeningExecutorService; + Image builtImage) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; this.dockerClient = dockerClient; - this.pullAndCacheBaseImageLayersStep = pullAndCacheBaseImageLayersStep; - this.buildAndCacheApplicationLayerSteps = buildAndCacheApplicationLayerSteps; - this.buildImageStep = buildImageStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(pullAndCacheBaseImageLayersStep) - .addStep(buildImageStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; + this.builtImage = builtImage; } @Override - public BuildResult call() throws ExecutionException, InterruptedException { - return AsyncDependencies.using(listeningExecutorService) - .addSteps(NonBlockingSteps.get(pullAndCacheBaseImageLayersStep)) - .addSteps(buildAndCacheApplicationLayerSteps) - .addStep(NonBlockingSteps.get(buildImageStep)) - .whenAllSucceed(this::afterPushBaseImageLayerFuturesFuture) - .get(); - } - - private BuildResult afterPushBaseImageLayerFuturesFuture() - throws ExecutionException, InterruptedException, IOException { - buildConfiguration - .getEventHandlers() - .dispatch(LogEvent.progress("Loading to Docker daemon...")); + public BuildResult call() throws InterruptedException, IOException { + EventHandlers eventHandlers = buildConfiguration.getEventHandlers(); + eventHandlers.dispatch(LogEvent.progress("Loading to Docker daemon...")); try (ProgressEventDispatcher ignored = progressEventDispatcherFactory.create("loading to Docker daemon", 1)) { - Image image = NonBlockingSteps.get(NonBlockingSteps.get(buildImageStep)); ImageReference targetImageReference = buildConfiguration.getTargetImageConfiguration().getImage(); // Load the image to docker daemon. - buildConfiguration - .getEventHandlers() - .dispatch( - LogEvent.debug(dockerClient.load(new ImageTarball(image, targetImageReference)))); + eventHandlers.dispatch( + LogEvent.debug(dockerClient.load(new ImageTarball(builtImage, targetImageReference)))); // Tags the image with all the additional tags, skipping the one 'docker load' already loaded. for (String tag : buildConfiguration.getAllTargetImageTags()) { @@ -113,7 +70,7 @@ private BuildResult afterPushBaseImageLayerFuturesFuture() dockerClient.tag(targetImageReference, targetImageReference.withTag(tag)); } - return BuildResult.fromImage(image, buildConfiguration.getTargetFormat()); + return BuildResult.fromImage(builtImage, buildConfiguration.getTargetFormat()); } } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayerStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayerStep.java index 9f5913cecd..7fbf042b75 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayerStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayerStep.java @@ -17,7 +17,6 @@ package com.google.cloud.tools.jib.builder.steps; import com.google.cloud.tools.jib.api.DescriptorDigest; -import com.google.cloud.tools.jib.async.AsyncStep; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.cache.Cache; @@ -26,15 +25,13 @@ import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.http.Authorization; import com.google.cloud.tools.jib.registry.RegistryClient; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.Optional; import java.util.concurrent.Callable; import javax.annotation.Nullable; /** Pulls and caches a single base image layer. */ -class PullAndCacheBaseImageLayerStep implements AsyncStep, Callable { +class PullAndCacheBaseImageLayerStep implements Callable { private static final String DESCRIPTION = "Pulling base image layer %s"; @@ -44,10 +41,7 @@ class PullAndCacheBaseImageLayerStep implements AsyncStep, Callable private final DescriptorDigest layerDigest; private final @Nullable Authorization pullAuthorization; - private final ListenableFuture listenableFuture; - PullAndCacheBaseImageLayerStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, DescriptorDigest layerDigest, @@ -56,17 +50,10 @@ class PullAndCacheBaseImageLayerStep implements AsyncStep, Callable this.progressEventDispatcherFactory = progressEventDispatcherFactory; this.layerDigest = layerDigest; this.pullAuthorization = pullAuthorization; - - listenableFuture = listeningExecutorService.submit(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; } @Override - public CachedLayer call() throws IOException, CacheCorruptedException { + public CachedLayerAndName call() throws IOException, CacheCorruptedException { try (ProgressEventDispatcher progressEventDispatcher = progressEventDispatcherFactory.create("checking base image layer " + layerDigest, 1); TimerEventDispatcher ignored = @@ -77,7 +64,7 @@ public CachedLayer call() throws IOException, CacheCorruptedException { // Checks if the layer already exists in the cache. Optional optionalCachedLayer = cache.retrieve(layerDigest); if (optionalCachedLayer.isPresent()) { - return optionalCachedLayer.get(); + return new CachedLayerAndName(optionalCachedLayer.get(), null); } else if (buildConfiguration.isOffline()) { throw new IOException( "Cannot run Jib in offline mode; local Jib cache for base image is missing image layer " @@ -95,11 +82,13 @@ public CachedLayer call() throws IOException, CacheCorruptedException { new ThrottledProgressEventDispatcherWrapper( progressEventDispatcher.newChildProducer(), "pulling base image layer " + layerDigest)) { - return cache.writeCompressedLayer( - registryClient.pullBlob( - layerDigest, - progressEventDispatcherWrapper::setProgressTarget, - progressEventDispatcherWrapper::dispatchProgress)); + CachedLayer cachedLayer = + cache.writeCompressedLayer( + registryClient.pullBlob( + layerDigest, + progressEventDispatcherWrapper::setProgressTarget, + progressEventDispatcherWrapper::dispatchProgress)); + return new CachedLayerAndName(cachedLayer, null); } } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayersStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayersStep.java index 18a499e10a..1ade0d839e 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayersStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullAndCacheBaseImageLayersStep.java @@ -16,81 +16,44 @@ package com.google.cloud.tools.jib.builder.steps; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; -import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.BaseImageWithAuthorization; +import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.ImageAndAuthorization; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.image.Layer; -import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; +import java.util.ArrayList; +import java.util.List; /** Pulls and caches the base image layers. */ -class PullAndCacheBaseImageLayersStep - implements AsyncStep>, - Callable> { +// TODO: following the same pattern as "BuildAndCacheApplicationLayerStep", move the sole "makeList" +// static into "PullAndCacheBaseImageLayerStep" and remove this class. +class PullAndCacheBaseImageLayersStep { - private static final String DESCRIPTION = "Setting up base image caching"; + private static final String DESCRIPTION = "Preparing base image layer pullers"; - private final BuildConfiguration buildConfiguration; - private final ListeningExecutorService listeningExecutorService; - private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - - private final PullBaseImageStep pullBaseImageStep; - - private final ListenableFuture> listenableFuture; - - PullAndCacheBaseImageLayersStep( - ListeningExecutorService listeningExecutorService, + static ImmutableList makeList( BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - PullBaseImageStep pullBaseImageStep) { - this.listeningExecutorService = listeningExecutorService; - this.buildConfiguration = buildConfiguration; - this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.pullBaseImageStep = pullBaseImageStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(pullBaseImageStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture> getFuture() { - return listenableFuture; - } - - @Override - public ImmutableList call() - throws ExecutionException, LayerPropertyNotFoundException { - BaseImageWithAuthorization pullBaseImageStepResult = NonBlockingSteps.get(pullBaseImageStep); - ImmutableList baseImageLayers = pullBaseImageStepResult.getBaseImage().getLayers(); + ImageAndAuthorization baseImageAndAuth) { + ImmutableList baseImageLayers = baseImageAndAuth.getImage().getLayers(); try (ProgressEventDispatcher progressEventDispatcher = progressEventDispatcherFactory.create( - "checking base image layers", baseImageLayers.size()); + "preparing base image layer pullers", baseImageLayers.size()); TimerEventDispatcher ignored = new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { - ImmutableList.Builder pullAndCacheBaseImageLayerStepsBuilder = - ImmutableList.builderWithExpectedSize(baseImageLayers.size()); + + List layerPullers = new ArrayList<>(); for (Layer layer : baseImageLayers) { - pullAndCacheBaseImageLayerStepsBuilder.add( + layerPullers.add( new PullAndCacheBaseImageLayerStep( - listeningExecutorService, buildConfiguration, progressEventDispatcher.newChildProducer(), layer.getBlobDescriptor().getDigest(), - pullBaseImageStepResult.getBaseImageAuthorization())); + baseImageAndAuth.getAuthorization())); } - - return pullAndCacheBaseImageLayerStepsBuilder.build(); + return ImmutableList.copyOf(layerPullers); } } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullBaseImageStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullBaseImageStep.java index 3c45b54816..0fbae70398 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullBaseImageStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PullBaseImageStep.java @@ -23,12 +23,10 @@ import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.api.RegistryException; import com.google.cloud.tools.jib.api.RegistryUnauthorizedException; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.blob.Blobs; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; -import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.BaseImageWithAuthorization; +import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.ImageAndAuthorization; import com.google.cloud.tools.jib.cache.CacheCorruptedException; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.configuration.ImageConfiguration; @@ -49,75 +47,61 @@ import com.google.cloud.tools.jib.json.JsonTemplateMapper; import com.google.cloud.tools.jib.registry.RegistryAuthenticator; import com.google.cloud.tools.jib.registry.RegistryClient; +import com.google.cloud.tools.jib.registry.credentials.CredentialRetrievalException; import com.google.common.annotations.VisibleForTesting; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; import java.util.Optional; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; import javax.annotation.Nullable; /** Pulls the base image manifest. */ -class PullBaseImageStep - implements AsyncStep, Callable { +class PullBaseImageStep implements Callable { private static final String DESCRIPTION = "Pulling base image manifest"; /** Structure for the result returned by this step. */ - static class BaseImageWithAuthorization { + static class ImageAndAuthorization { - private final Image baseImage; - private final @Nullable Authorization baseImageAuthorization; + private final Image image; + private final @Nullable Authorization authorization; @VisibleForTesting - BaseImageWithAuthorization(Image baseImage, @Nullable Authorization baseImageAuthorization) { - this.baseImage = baseImage; - this.baseImageAuthorization = baseImageAuthorization; + ImageAndAuthorization(Image image, @Nullable Authorization authorization) { + this.image = image; + this.authorization = authorization; } - Image getBaseImage() { - return baseImage; + Image getImage() { + return image; } @Nullable - Authorization getBaseImageAuthorization() { - return baseImageAuthorization; + Authorization getAuthorization() { + return authorization; } } private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - private final ListenableFuture listenableFuture; - PullBaseImageStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - - listenableFuture = listeningExecutorService.submit(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; } @Override - public BaseImageWithAuthorization call() + public ImageAndAuthorization call() throws IOException, RegistryException, LayerPropertyNotFoundException, - LayerCountMismatchException, ExecutionException, BadContainerConfigurationFormatException, - CacheCorruptedException { + LayerCountMismatchException, BadContainerConfigurationFormatException, + CacheCorruptedException, CredentialRetrievalException { EventHandlers eventHandlers = buildConfiguration.getEventHandlers(); // Skip this step if this is a scratch image ImageConfiguration baseImageConfiguration = buildConfiguration.getBaseImageConfiguration(); if (baseImageConfiguration.getImage().isScratch()) { eventHandlers.dispatch(LogEvent.progress("Getting scratch base image...")); - return new BaseImageWithAuthorization( + return new ImageAndAuthorization( Image.builder(buildConfiguration.getTargetFormat()).build(), null); } @@ -128,7 +112,7 @@ public BaseImageWithAuthorization call() + "...")); if (buildConfiguration.isOffline()) { - return new BaseImageWithAuthorization(pullBaseImageOffline(), null); + return new ImageAndAuthorization(pullBaseImageOffline(), null); } try (ProgressEventDispatcher progressEventDispatcher = @@ -137,7 +121,7 @@ public BaseImageWithAuthorization call() new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { // First, try with no credentials. try { - return new BaseImageWithAuthorization(pullBaseImage(null, progressEventDispatcher), null); + return new ImageAndAuthorization(pullBaseImage(null, progressEventDispatcher), null); } catch (RegistryUnauthorizedException ex) { eventHandlers.dispatch( @@ -148,15 +132,12 @@ public BaseImageWithAuthorization call() // If failed, then, retrieve base registry credentials and try with retrieved credentials. // TODO: Refactor the logic in RetrieveRegistryCredentialsStep out to - // registry.credentials.RegistryCredentialsRetriever to avoid this direct executor hack. - ListeningExecutorService directExecutorService = MoreExecutors.newDirectExecutorService(); - RetrieveRegistryCredentialsStep retrieveBaseRegistryCredentialsStep = + // registry.credentials.RegistryCredentialsRetriever. + Credential registryCredential = RetrieveRegistryCredentialsStep.forBaseImage( - directExecutorService, - buildConfiguration, - progressEventDispatcher.newChildProducer()); + buildConfiguration, progressEventDispatcher.newChildProducer()) + .call(); - Credential registryCredential = NonBlockingSteps.get(retrieveBaseRegistryCredentialsStep); Authorization registryAuthorization = registryCredential == null || registryCredential.isOAuth2RefreshToken() ? null @@ -164,7 +145,7 @@ public BaseImageWithAuthorization call() registryCredential.getUsername(), registryCredential.getPassword()); try { - return new BaseImageWithAuthorization( + return new ImageAndAuthorization( pullBaseImage(registryAuthorization, progressEventDispatcher), registryAuthorization); } catch (RegistryUnauthorizedException registryUnauthorizedException) { @@ -180,7 +161,7 @@ public BaseImageWithAuthorization call() Authorization pullAuthorization = registryAuthenticator.authenticatePull(registryCredential); - return new BaseImageWithAuthorization( + return new ImageAndAuthorization( pullBaseImage(pullAuthorization, progressEventDispatcher), pullAuthorization); } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushBlobStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushBlobStep.java index 662b37a3cd..4a563802db 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushBlobStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushBlobStep.java @@ -18,62 +18,44 @@ import com.google.cloud.tools.jib.api.LogEvent; import com.google.cloud.tools.jib.api.RegistryException; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.blob.Blob; import com.google.cloud.tools.jib.blob.BlobDescriptor; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.event.progress.ThrottledAccumulatingConsumer; +import com.google.cloud.tools.jib.http.Authorization; import com.google.cloud.tools.jib.registry.RegistryClient; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; /** Pushes a BLOB to the target registry. */ -class PushBlobStep implements AsyncStep, Callable { +class PushBlobStep implements Callable { private static final String DESCRIPTION = "Pushing BLOB "; private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDipatcherFactory; - private final AuthenticatePushStep authenticatePushStep; + private final Authorization authorization; private final BlobDescriptor blobDescriptor; private final Blob blob; - private final ListenableFuture listenableFuture; - PushBlobStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDipatcherFactory, - AuthenticatePushStep authenticatePushStep, + Authorization authorization, BlobDescriptor blobDescriptor, Blob blob) { this.buildConfiguration = buildConfiguration; this.progressEventDipatcherFactory = progressEventDipatcherFactory; - this.authenticatePushStep = authenticatePushStep; + this.authorization = authorization; this.blobDescriptor = blobDescriptor; this.blob = blob; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(authenticatePushStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; } @Override - public BlobDescriptor call() throws IOException, RegistryException, ExecutionException { + public BlobDescriptor call() throws IOException, RegistryException { try (ProgressEventDispatcher progressEventDispatcher = progressEventDipatcherFactory.create( "pushing blob " + blobDescriptor.getDigest(), blobDescriptor.getSize()); @@ -85,7 +67,7 @@ public BlobDescriptor call() throws IOException, RegistryException, ExecutionExc RegistryClient registryClient = buildConfiguration .newTargetImageRegistryClientFactory() - .setAuthorization(NonBlockingSteps.get(authenticatePushStep)) + .setAuthorization(authorization) .newRegistryClient(); // check if the BLOB is available diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushContainerConfigurationStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushContainerConfigurationStep.java index 8ffbe1345a..ef74f438d3 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushContainerConfigurationStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushContainerConfigurationStep.java @@ -16,90 +16,58 @@ package com.google.cloud.tools.jib.builder.steps; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; +import com.google.cloud.tools.jib.api.RegistryException; import com.google.cloud.tools.jib.blob.BlobDescriptor; import com.google.cloud.tools.jib.blob.Blobs; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.hash.Digests; +import com.google.cloud.tools.jib.http.Authorization; import com.google.cloud.tools.jib.image.Image; import com.google.cloud.tools.jib.image.json.ImageToJsonTranslator; import com.google.cloud.tools.jib.json.JsonTemplate; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.IOException; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; /** Pushes the container configuration. */ -class PushContainerConfigurationStep - implements AsyncStep>, Callable> { +class PushContainerConfigurationStep implements Callable { private static final String DESCRIPTION = "Pushing container configuration"; private final BuildConfiguration buildConfiguration; - private final ListeningExecutorService listeningExecutorService; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - private final AuthenticatePushStep authenticatePushStep; - private final BuildImageStep buildImageStep; - - private final ListenableFuture> listenableFuture; + private final Authorization pushAuthorization; + private final Image builtImage; PushContainerConfigurationStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - AuthenticatePushStep authenticatePushStep, - BuildImageStep buildImageStep) { - this.listeningExecutorService = listeningExecutorService; + Authorization authenticatePushStep, + Image builtImage) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.authenticatePushStep = authenticatePushStep; - this.buildImageStep = buildImageStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(buildImageStep) - .whenAllSucceed(this); + this.pushAuthorization = authenticatePushStep; + this.builtImage = builtImage; } @Override - public ListenableFuture> getFuture() { - return listenableFuture; - } - - @Override - public AsyncStep call() throws ExecutionException { - ListenableFuture pushBlobStepFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(authenticatePushStep) - .addStep(NonBlockingSteps.get(buildImageStep)) - .whenAllSucceed(this::afterBuildConfigurationFutureFuture); - return () -> pushBlobStepFuture; - } - - private PushBlobStep afterBuildConfigurationFutureFuture() - throws ExecutionException, IOException { + public BlobDescriptor call() throws IOException, RegistryException { try (ProgressEventDispatcher progressEventDispatcher = progressEventDispatcherFactory.create("pushing container configuration", 1); TimerEventDispatcher ignored = new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { - Image image = NonBlockingSteps.get(NonBlockingSteps.get(buildImageStep)); JsonTemplate containerConfiguration = - new ImageToJsonTranslator(image).getContainerConfiguration(); - BlobDescriptor blobDescriptor = Digests.computeDigest(containerConfiguration); + new ImageToJsonTranslator(builtImage).getContainerConfiguration(); return new PushBlobStep( - listeningExecutorService, - buildConfiguration, - progressEventDispatcher.newChildProducer(), - authenticatePushStep, - blobDescriptor, - Blobs.from(containerConfiguration)); + buildConfiguration, + progressEventDispatcher.newChildProducer(), + pushAuthorization, + Digests.computeDigest(containerConfiguration), + Blobs.from(containerConfiguration)) + .call(); } } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushImageStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushImageStep.java index f967286715..7cbb0172e4 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushImageStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushImageStep.java @@ -18,14 +18,13 @@ import com.google.cloud.tools.jib.api.DescriptorDigest; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.blob.BlobDescriptor; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.hash.Digests; +import com.google.cloud.tools.jib.http.Authorization; +import com.google.cloud.tools.jib.image.Image; import com.google.cloud.tools.jib.image.json.BuildableManifestTemplate; import com.google.cloud.tools.jib.image.json.ImageToJsonTranslator; import com.google.cloud.tools.jib.registry.RegistryClient; @@ -40,84 +39,37 @@ import java.util.concurrent.ExecutionException; /** Pushes the final image. Outputs the pushed image digest. */ -class PushImageStep implements AsyncStep, Callable { +class PushImageStep implements Callable { private static final String DESCRIPTION = "Pushing new image"; private final BuildConfiguration buildConfiguration; - private final ListeningExecutorService listeningExecutorService; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - private final AuthenticatePushStep authenticatePushStep; - - private final PushLayersStep pushBaseImageLayersStep; - private final PushLayersStep pushApplicationLayersStep; - private final PushContainerConfigurationStep pushContainerConfigurationStep; - private final BuildImageStep buildImageStep; + private final Authorization pushAuthorization; + private final BlobDescriptor containerConfigurationDigestAndSize; + private final Image builtImage; - private final ListenableFuture listenableFuture; + private final ListeningExecutorService listeningExecutorService; + // TODO: remove listeningExecutorService like other siblings PushImageStep( ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, - AuthenticatePushStep authenticatePushStep, - PushLayersStep pushBaseImageLayersStep, - PushLayersStep pushApplicationLayersStep, - PushContainerConfigurationStep pushContainerConfigurationStep, - BuildImageStep buildImageStep) { + Authorization pushAuthorization, + BlobDescriptor containerConfigurationDigestAndSize, + Image builtImage) { this.listeningExecutorService = listeningExecutorService; this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.authenticatePushStep = authenticatePushStep; - this.pushBaseImageLayersStep = pushBaseImageLayersStep; - this.pushApplicationLayersStep = pushApplicationLayersStep; - this.pushContainerConfigurationStep = pushContainerConfigurationStep; - this.buildImageStep = buildImageStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(pushBaseImageLayersStep) - .addStep(pushApplicationLayersStep) - .addStep(pushContainerConfigurationStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; + this.pushAuthorization = pushAuthorization; + this.containerConfigurationDigestAndSize = containerConfigurationDigestAndSize; + this.builtImage = builtImage; } @Override - public BuildResult call() throws ExecutionException, InterruptedException { - return AsyncDependencies.using(listeningExecutorService) - .addStep(authenticatePushStep) - .addSteps(NonBlockingSteps.get(pushBaseImageLayersStep)) - .addSteps(NonBlockingSteps.get(pushApplicationLayersStep)) - .addStep(NonBlockingSteps.get(pushContainerConfigurationStep)) - .addStep(NonBlockingSteps.get(buildImageStep)) - .whenAllSucceed(this::afterPushSteps) - .get(); - } - - private BuildResult afterPushSteps() throws ExecutionException, InterruptedException { - AsyncDependencies dependencies = AsyncDependencies.using(listeningExecutorService); - for (AsyncStep pushBaseImageLayerStep : - NonBlockingSteps.get(pushBaseImageLayersStep)) { - dependencies.addStep(NonBlockingSteps.get(pushBaseImageLayerStep)); - } - for (AsyncStep pushApplicationLayerStep : - NonBlockingSteps.get(pushApplicationLayersStep)) { - dependencies.addStep(NonBlockingSteps.get(pushApplicationLayerStep)); - } - return dependencies - .addStep(NonBlockingSteps.get(NonBlockingSteps.get(pushContainerConfigurationStep))) - .whenAllSucceed(this::afterAllPushed) - .get(); - } - - private BuildResult afterAllPushed() - throws ExecutionException, IOException, InterruptedException { + public BuildResult call() throws IOException, InterruptedException, ExecutionException { ImmutableSet targetImageTags = buildConfiguration.getAllTargetImageTags(); ProgressEventDispatcher progressEventDispatcher = progressEventDispatcherFactory.create("pushing image manifest", targetImageTags.size()); @@ -127,20 +79,16 @@ private BuildResult afterAllPushed() RegistryClient registryClient = buildConfiguration .newTargetImageRegistryClientFactory() - .setAuthorization(NonBlockingSteps.get(authenticatePushStep)) + .setAuthorization(pushAuthorization) .newRegistryClient(); // Constructs the image. - ImageToJsonTranslator imageToJsonTranslator = - new ImageToJsonTranslator(NonBlockingSteps.get(NonBlockingSteps.get(buildImageStep))); + ImageToJsonTranslator imageToJsonTranslator = new ImageToJsonTranslator(builtImage); // Gets the image manifest to push. - BlobDescriptor containerConfigurationBlobDescriptor = - NonBlockingSteps.get( - NonBlockingSteps.get(NonBlockingSteps.get(pushContainerConfigurationStep))); BuildableManifestTemplate manifestTemplate = imageToJsonTranslator.getManifestTemplate( - buildConfiguration.getTargetFormat(), containerConfigurationBlobDescriptor); + buildConfiguration.getTargetFormat(), containerConfigurationDigestAndSize); // Pushes to all target image tags. List> pushAllTagsFutures = new ArrayList<>(); @@ -162,7 +110,7 @@ private BuildResult afterAllPushed() } DescriptorDigest imageDigest = Digests.computeJsonDigest(manifestTemplate); - DescriptorDigest imageId = containerConfigurationBlobDescriptor.getDigest(); + DescriptorDigest imageId = containerConfigurationDigestAndSize.getDigest(); BuildResult result = new BuildResult(imageDigest, imageId); return Futures.whenAllSucceed(pushAllTagsFutures) diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayerStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayerStep.java new file mode 100644 index 0000000000..26e9b552b8 --- /dev/null +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayerStep.java @@ -0,0 +1,91 @@ +/* + * Copyright 2018 Google LLC. + * + * 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. + */ + +package com.google.cloud.tools.jib.builder.steps; + +import com.google.cloud.tools.jib.api.RegistryException; +import com.google.cloud.tools.jib.blob.BlobDescriptor; +import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; +import com.google.cloud.tools.jib.builder.TimerEventDispatcher; +import com.google.cloud.tools.jib.cache.CachedLayer; +import com.google.cloud.tools.jib.configuration.BuildConfiguration; +import com.google.cloud.tools.jib.http.Authorization; +import com.google.common.collect.ImmutableList; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; + +class PushLayerStep implements Callable { + + private static final String DESCRIPTION = "Preparing application layer pushers"; + + private final BuildConfiguration buildConfiguration; + private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; + + private final Authorization pushAuthorization; + private final Future cachedLayerAndName; + + static ImmutableList makeList( + BuildConfiguration buildConfiguration, + ProgressEventDispatcher.Factory progressEventDispatcherFactory, + Authorization pushAuthorization, + List> cachedLayers) { + try (TimerEventDispatcher ignored = + new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION); + ProgressEventDispatcher progressEventDispatcher = + progressEventDispatcherFactory.create( + "Preparing application layer pushers", cachedLayers.size())) { + + // Constructs a PushBlobStep for each layer. + List blobPushers = new ArrayList<>(); + for (Future layer : cachedLayers) { + ProgressEventDispatcher.Factory childProgressProducer = + progressEventDispatcher.newChildProducer(); + blobPushers.add( + new PushLayerStep(buildConfiguration, childProgressProducer, pushAuthorization, layer)); + } + + return ImmutableList.copyOf(blobPushers); + } + } + + PushLayerStep( + BuildConfiguration buildConfiguration, + ProgressEventDispatcher.Factory progressEventDispatcherFactory, + Authorization pushAuthorization, + Future cachedLayerAndName) { + this.buildConfiguration = buildConfiguration; + this.progressEventDispatcherFactory = progressEventDispatcherFactory; + this.pushAuthorization = pushAuthorization; + this.cachedLayerAndName = cachedLayerAndName; + } + + @Override + public BlobDescriptor call() + throws IOException, RegistryException, ExecutionException, InterruptedException { + CachedLayer layer = cachedLayerAndName.get().getCachedLayer(); + return new PushBlobStep( + buildConfiguration, + progressEventDispatcherFactory, + pushAuthorization, + new BlobDescriptor(layer.getSize(), layer.getDigest()), + layer.getBlob()) + .call(); + } +} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayersStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayersStep.java deleted file mode 100644 index 299b6c0bd9..0000000000 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/PushLayersStep.java +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright 2018 Google LLC. - * - * 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. - */ - -package com.google.cloud.tools.jib.builder.steps; - -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; -import com.google.cloud.tools.jib.blob.BlobDescriptor; -import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; -import com.google.cloud.tools.jib.builder.TimerEventDispatcher; -import com.google.cloud.tools.jib.cache.CachedLayer; -import com.google.cloud.tools.jib.configuration.BuildConfiguration; -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -class PushLayersStep - implements AsyncStep>>, - Callable>> { - - private static final String DESCRIPTION = "Setting up to push layers"; - - private final BuildConfiguration buildConfiguration; - private final ListeningExecutorService listeningExecutorService; - private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; - - private final AuthenticatePushStep authenticatePushStep; - private final AsyncStep>> - cachedLayerStep; - - private final ListenableFuture>> listenableFuture; - - PushLayersStep( - ListeningExecutorService listeningExecutorService, - BuildConfiguration buildConfiguration, - ProgressEventDispatcher.Factory progressEventDispatcherFactory, - AuthenticatePushStep authenticatePushStep, - AsyncStep>> - cachedLayerStep) { - this.listeningExecutorService = listeningExecutorService; - this.buildConfiguration = buildConfiguration; - this.progressEventDispatcherFactory = progressEventDispatcherFactory; - this.authenticatePushStep = authenticatePushStep; - this.cachedLayerStep = cachedLayerStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(cachedLayerStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture>> getFuture() { - return listenableFuture; - } - - @Override - public ImmutableList> call() throws ExecutionException { - try (TimerEventDispatcher ignored = - new TimerEventDispatcher(buildConfiguration.getEventHandlers(), DESCRIPTION)) { - ImmutableList> cachedLayers = - NonBlockingSteps.get(cachedLayerStep); - - try (ProgressEventDispatcher progressEventDispatcher = - progressEventDispatcherFactory.create("setting up to push layers", cachedLayers.size())) { - // Constructs a PushBlobStep for each layer. - ImmutableList.Builder> pushBlobStepsBuilder = - ImmutableList.builder(); - for (AsyncStep cachedLayerStep : cachedLayers) { - ProgressEventDispatcher.Factory childProgressEventDispatcherFactory = - progressEventDispatcher.newChildProducer(); - ListenableFuture pushBlobStepFuture = - Futures.whenAllSucceed(cachedLayerStep.getFuture()) - .call( - () -> makePushBlobStep(cachedLayerStep, childProgressEventDispatcherFactory), - listeningExecutorService); - pushBlobStepsBuilder.add(() -> pushBlobStepFuture); - } - - return pushBlobStepsBuilder.build(); - } - } - } - - private PushBlobStep makePushBlobStep( - AsyncStep cachedLayerStep, - ProgressEventDispatcher.Factory progressEventDispatcherFactory) - throws ExecutionException { - CachedLayer cachedLayer = NonBlockingSteps.get(cachedLayerStep); - - return new PushBlobStep( - listeningExecutorService, - buildConfiguration, - progressEventDispatcherFactory, - authenticatePushStep, - new BlobDescriptor(cachedLayer.getSize(), cachedLayer.getDigest()), - cachedLayer.getBlob()); - } -} diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStep.java index 0cf0d1c4c8..15da9bc07f 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStep.java @@ -19,33 +19,23 @@ import com.google.cloud.tools.jib.api.Credential; import com.google.cloud.tools.jib.api.CredentialRetriever; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncStep; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.builder.TimerEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.registry.credentials.CredentialRetrievalException; -import com.google.common.annotations.VisibleForTesting; import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.util.Optional; import java.util.concurrent.Callable; import javax.annotation.Nullable; /** Attempts to retrieve registry credentials. */ -class RetrieveRegistryCredentialsStep implements AsyncStep, Callable { - - private static String makeDescription(String registry) { - return "Retrieving registry credentials for " + registry; - } +class RetrieveRegistryCredentialsStep implements Callable { /** Retrieves credentials for the base image. */ static RetrieveRegistryCredentialsStep forBaseImage( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory) { return new RetrieveRegistryCredentialsStep( - listeningExecutorService, buildConfiguration, progressEventDispatcherFactory, buildConfiguration.getBaseImageConfiguration().getImageRegistry(), @@ -54,11 +44,9 @@ static RetrieveRegistryCredentialsStep forBaseImage( /** Retrieves credentials for the target image. */ static RetrieveRegistryCredentialsStep forTargetImage( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory) { return new RetrieveRegistryCredentialsStep( - listeningExecutorService, buildConfiguration, progressEventDispatcherFactory, buildConfiguration.getTargetImageConfiguration().getImageRegistry(), @@ -71,11 +59,7 @@ static RetrieveRegistryCredentialsStep forTargetImage( private final String registry; private final ImmutableList credentialRetrievers; - private final ListenableFuture listenableFuture; - - @VisibleForTesting RetrieveRegistryCredentialsStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, String registry, @@ -84,20 +68,12 @@ static RetrieveRegistryCredentialsStep forTargetImage( this.progressEventDispatcherFactory = progressEventDispatcherFactory; this.registry = registry; this.credentialRetrievers = credentialRetrievers; - - listenableFuture = listeningExecutorService.submit(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; } @Override @Nullable public Credential call() throws CredentialRetrievalException { - String description = makeDescription(registry); - + String description = "Retrieving registry credentials for " + registry; buildConfiguration.getEventHandlers().dispatch(LogEvent.progress(description + "...")); try (ProgressEventDispatcher ignored = diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/StepsRunner.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/StepsRunner.java index fff5d935eb..b4872c5ac1 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/StepsRunner.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/StepsRunner.java @@ -16,19 +16,30 @@ package com.google.cloud.tools.jib.builder.steps; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.AsyncSteps; +import com.google.cloud.tools.jib.api.Credential; +import com.google.cloud.tools.jib.blob.BlobDescriptor; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; +import com.google.cloud.tools.jib.builder.steps.PullBaseImageStep.ImageAndAuthorization; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.docker.DockerClient; import com.google.cloud.tools.jib.global.JibSystemProperties; +import com.google.cloud.tools.jib.http.Authorization; +import com.google.cloud.tools.jib.image.Image; import com.google.common.base.Preconditions; +import com.google.common.base.Verify; import com.google.common.collect.ImmutableList; +import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; +import java.util.function.Supplier; +import java.util.stream.Collectors; import javax.annotation.Nullable; /** @@ -40,23 +51,24 @@ */ public class StepsRunner { - /** Holds the individual steps. */ - private static class Steps { + /** Holds the individual step results. */ + private static class StepResults { - @Nullable private RetrieveRegistryCredentialsStep retrieveTargetRegistryCredentialsStep; - @Nullable private AuthenticatePushStep authenticatePushStep; - @Nullable private PullBaseImageStep pullBaseImageStep; - @Nullable private PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep; - - @Nullable - private ImmutableList buildAndCacheApplicationLayerSteps; - - @Nullable private PushLayersStep pushBaseImageLayersStep; - @Nullable private PushLayersStep pushApplicationLayersStep; - @Nullable private BuildImageStep buildImageStep; - @Nullable private PushContainerConfigurationStep pushContainerConfigurationStep; + private static Future failedFuture() { + return Futures.immediateFailedFuture( + new IllegalStateException("invalid usage; required step not configured")); + } - @Nullable private AsyncStep finalStep; + private Future baseImageAndAuth = failedFuture(); + private Future>> baseImageLayers = failedFuture(); + @Nullable private List> applicationLayers; + private Future builtImage = failedFuture(); + private Future targetRegistryCredentials = failedFuture(); + private Future pushAuthorization = failedFuture(); + private Future>> baseImageLayerPushResults = failedFuture(); + private Future>> applicationLayerPushResults = failedFuture(); + private Future containerConfigurationPushResult = failedFuture(); + private Future buildResult = failedFuture(); } /** @@ -74,197 +86,237 @@ public static StepsRunner begin(BuildConfiguration buildConfiguration) { return new StepsRunner(MoreExecutors.listeningDecorator(executorService), buildConfiguration); } - private final Steps steps = new Steps(); + private final StepResults results = new StepResults(); - private final ListeningExecutorService listeningExecutorService; + // TODO: use plain ExecutorService; requires refactoring PushImageStep. + private final ListeningExecutorService executorService; private final BuildConfiguration buildConfiguration; - /** Runnable to run all the steps. */ - private Runnable stepsRunnable = () -> {}; - - /** The total number of steps added. */ - private int stepsCount = 0; - - @Nullable private String rootProgressAllocationDescription; - @Nullable private ProgressEventDispatcher rootProgressEventDispatcher; + // We save steps to run by wrapping each step into a Runnable, only because of the unfortunate + // chicken-and-egg situation arising from using ProgressEventDispatcher. The current + // ProgressEventDispatcher model requires knowing in advance how many units of work (i.e., steps) + // we should perform. That is, to instantiate a root ProgressEventDispatcher instance, we should + // know ahead how many steps we will run. However, to instantiate a step, we need a root progress + // dispatcher. So, we wrap steps into Runnables and save them to run them later. Then we can count + // the number of Runnables and, create a root dispatcher, and run the saved Runnables. + private final List stepsToRun = new ArrayList<>(); + + @Nullable private String rootProgressDescription; + private Supplier childProgressDispatcherFactorySupplier = + () -> { + throw new IllegalStateException("root progress dispatcher uninstantiated"); + }; private StepsRunner( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration) { - this.listeningExecutorService = listeningExecutorService; + ListeningExecutorService executorService, BuildConfiguration buildConfiguration) { + this.executorService = executorService; this.buildConfiguration = buildConfiguration; } - public StepsRunner retrieveTargetRegistryCredentials() { - return enqueueStep( - () -> - steps.retrieveTargetRegistryCredentialsStep = - RetrieveRegistryCredentialsStep.forTargetImage( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer())); + private void retrieveTargetRegistryCredentials() { + results.targetRegistryCredentials = + executorService.submit( + RetrieveRegistryCredentialsStep.forTargetImage( + buildConfiguration, childProgressDispatcherFactorySupplier.get())); } - public StepsRunner authenticatePush() { - return enqueueStep( - () -> - steps.authenticatePushStep = + private void authenticatePush() { + results.pushAuthorization = + executorService.submit( + () -> new AuthenticatePushStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.retrieveTargetRegistryCredentialsStep))); + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.targetRegistryCredentials.get()) + .call()); } - public StepsRunner pullBaseImage() { - return enqueueStep( - () -> - steps.pullBaseImageStep = - new PullBaseImageStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer())); + private void pullBaseImage() { + results.baseImageAndAuth = + executorService.submit( + new PullBaseImageStep( + buildConfiguration, childProgressDispatcherFactorySupplier.get())); } - public StepsRunner pullAndCacheBaseImageLayers() { - return enqueueStep( - () -> - steps.pullAndCacheBaseImageLayersStep = - new PullAndCacheBaseImageLayersStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.pullBaseImageStep))); + private void pullAndCacheBaseImageLayers() { + results.baseImageLayers = + executorService.submit( + () -> + scheduleCallables( + PullAndCacheBaseImageLayersStep.makeList( + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.baseImageAndAuth.get()))); } - public StepsRunner pushBaseImageLayers() { - return enqueueStep( - () -> - steps.pushBaseImageLayersStep = - new PushLayersStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.authenticatePushStep), - Preconditions.checkNotNull(steps.pullAndCacheBaseImageLayersStep))); + private void pushBaseImageLayers() { + results.baseImageLayerPushResults = + executorService.submit( + () -> + scheduleCallables( + PushLayerStep.makeList( + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.pushAuthorization.get(), + results.baseImageLayers.get()))); } - public StepsRunner buildAndCacheApplicationLayers() { - return enqueueStep( - () -> - steps.buildAndCacheApplicationLayerSteps = - BuildAndCacheApplicationLayerStep.makeList( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer())); + private void buildAndCacheApplicationLayers() { + results.applicationLayers = + scheduleCallables( + BuildAndCacheApplicationLayerStep.makeList( + buildConfiguration, childProgressDispatcherFactorySupplier.get())); } - public StepsRunner buildImage() { - return enqueueStep( - () -> - steps.buildImageStep = + private void buildImage() { + results.builtImage = + executorService.submit( + () -> new BuildImageStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.pullBaseImageStep), - Preconditions.checkNotNull(steps.pullAndCacheBaseImageLayersStep), - Preconditions.checkNotNull(steps.buildAndCacheApplicationLayerSteps))); + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.baseImageAndAuth.get().getImage(), + realizeFutures(results.baseImageLayers.get()), + realizeFutures(Verify.verifyNotNull(results.applicationLayers))) + .call()); } - public StepsRunner pushContainerConfiguration() { - return enqueueStep( - () -> - steps.pushContainerConfigurationStep = + private void pushContainerConfiguration() { + results.containerConfigurationPushResult = + executorService.submit( + () -> new PushContainerConfigurationStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.authenticatePushStep), - Preconditions.checkNotNull(steps.buildImageStep))); + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.pushAuthorization.get(), + results.builtImage.get()) + .call()); } - public StepsRunner pushApplicationLayers() { - return enqueueStep( - () -> - steps.pushApplicationLayersStep = - new PushLayersStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.authenticatePushStep), - AsyncSteps.immediate( - Preconditions.checkNotNull(steps.buildAndCacheApplicationLayerSteps)))); + private void pushApplicationLayers() { + results.applicationLayerPushResults = + executorService.submit( + () -> + scheduleCallables( + PushLayerStep.makeList( + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.pushAuthorization.get(), + Verify.verifyNotNull(results.applicationLayers)))); } - public StepsRunner pushImage() { - rootProgressAllocationDescription = "building image to registry"; - - return enqueueStep( - () -> - steps.finalStep = - new PushImageStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - Preconditions.checkNotNull(steps.authenticatePushStep), - Preconditions.checkNotNull(steps.pushBaseImageLayersStep), - Preconditions.checkNotNull(steps.pushApplicationLayersStep), - Preconditions.checkNotNull(steps.pushContainerConfigurationStep), - Preconditions.checkNotNull(steps.buildImageStep))); + private void pushImage() { + results.buildResult = + executorService.submit( + () -> { + realizeFutures(results.baseImageLayerPushResults.get()); + realizeFutures(results.applicationLayerPushResults.get()); + + return new PushImageStep( + executorService, + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + results.pushAuthorization.get(), + results.containerConfigurationPushResult.get(), + results.builtImage.get()) + .call(); + }); } - public StepsRunner loadDocker(DockerClient dockerClient) { - rootProgressAllocationDescription = "building image to Docker daemon"; - - return enqueueStep( - () -> - steps.finalStep = + private void loadDocker(DockerClient dockerClient) { + results.buildResult = + executorService.submit( + () -> new LoadDockerStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - dockerClient, - Preconditions.checkNotNull(steps.pullAndCacheBaseImageLayersStep), - Preconditions.checkNotNull(steps.buildAndCacheApplicationLayerSteps), - Preconditions.checkNotNull(steps.buildImageStep))); + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + dockerClient, + results.builtImage.get()) + .call()); } - public StepsRunner writeTarFile(Path outputPath) { - rootProgressAllocationDescription = "building image to tar file"; - - return enqueueStep( - () -> - steps.finalStep = + private void writeTarFile(Path outputPath) { + results.buildResult = + executorService.submit( + () -> new WriteTarFileStep( - listeningExecutorService, - buildConfiguration, - Preconditions.checkNotNull(rootProgressEventDispatcher).newChildProducer(), - outputPath, - Preconditions.checkNotNull(steps.pullAndCacheBaseImageLayersStep), - Preconditions.checkNotNull(steps.buildAndCacheApplicationLayerSteps), - Preconditions.checkNotNull(steps.buildImageStep))); + buildConfiguration, + childProgressDispatcherFactorySupplier.get(), + outputPath, + results.builtImage.get()) + .call()); } public BuildResult run() throws ExecutionException, InterruptedException { - Preconditions.checkNotNull(rootProgressAllocationDescription); + Preconditions.checkNotNull(rootProgressDescription); try (ProgressEventDispatcher progressEventDispatcher = ProgressEventDispatcher.newRoot( - buildConfiguration.getEventHandlers(), rootProgressAllocationDescription, stepsCount)) { - rootProgressEventDispatcher = progressEventDispatcher; - stepsRunnable.run(); - return Preconditions.checkNotNull(steps.finalStep).getFuture().get(); + buildConfiguration.getEventHandlers(), rootProgressDescription, stepsToRun.size())) { + childProgressDispatcherFactorySupplier = progressEventDispatcher::newChildProducer; + stepsToRun.forEach(Runnable::run); + return results.buildResult.get(); + + } catch (ExecutionException ex) { + ExecutionException unrolled = ex; + while (unrolled.getCause() instanceof ExecutionException) { + unrolled = (ExecutionException) unrolled.getCause(); + } + throw unrolled; + } + } + + private static List realizeFutures(List> futures) + throws InterruptedException, ExecutionException { + List values = new ArrayList<>(); + for (Future future : futures) { + values.add(future.get()); } + return values; + } + + private List> scheduleCallables(ImmutableList> callables) { + return callables.stream().map(executorService::submit).collect(Collectors.toList()); + } + + public StepsRunner dockerLoadSteps(DockerClient dockerClient) { + rootProgressDescription = "building image to Docker daemon"; + // build and cache + stepsToRun.add(this::pullBaseImage); + stepsToRun.add(this::pullAndCacheBaseImageLayers); + stepsToRun.add(this::buildAndCacheApplicationLayers); + stepsToRun.add(this::buildImage); + // load to Docker + stepsToRun.add(() -> loadDocker(dockerClient)); + return this; + } + + public StepsRunner tarBuildSteps(Path outputPath) { + rootProgressDescription = "building image to tar file"; + // build and cache + stepsToRun.add(this::pullBaseImage); + stepsToRun.add(this::pullAndCacheBaseImageLayers); + stepsToRun.add(this::buildAndCacheApplicationLayers); + stepsToRun.add(this::buildImage); + // create a tar + stepsToRun.add(() -> writeTarFile(outputPath)); + return this; } - private StepsRunner enqueueStep(Runnable stepRunnable) { - Runnable previousStepsRunnable = stepsRunnable; - stepsRunnable = - () -> { - previousStepsRunnable.run(); - stepRunnable.run(); - }; - stepsCount++; + public StepsRunner registryPushSteps() { + rootProgressDescription = "building image to registry"; + // build and cache + stepsToRun.add(this::pullBaseImage); + stepsToRun.add(this::pullAndCacheBaseImageLayers); + stepsToRun.add(this::buildAndCacheApplicationLayers); + stepsToRun.add(this::buildImage); + // push to registry + stepsToRun.add(this::retrieveTargetRegistryCredentials); + stepsToRun.add(this::authenticatePush); + stepsToRun.add(this::pushBaseImageLayers); + stepsToRun.add(this::pushApplicationLayers); + stepsToRun.add(this::pushContainerConfiguration); + stepsToRun.add(this::pushImage); return this; } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/WriteTarFileStep.java b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/WriteTarFileStep.java index f57625d92a..5d1681ed80 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/WriteTarFileStep.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/builder/steps/WriteTarFileStep.java @@ -17,17 +17,11 @@ package com.google.cloud.tools.jib.builder.steps; import com.google.cloud.tools.jib.api.LogEvent; -import com.google.cloud.tools.jib.async.AsyncDependencies; -import com.google.cloud.tools.jib.async.AsyncStep; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.docker.ImageTarball; import com.google.cloud.tools.jib.filesystem.FileOperations; import com.google.cloud.tools.jib.image.Image; -import com.google.common.collect.ImmutableList; -import com.google.common.util.concurrent.ListenableFuture; -import com.google.common.util.concurrent.ListeningExecutorService; import java.io.BufferedOutputStream; import java.io.IOException; import java.io.OutputStream; @@ -36,75 +30,42 @@ import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; -public class WriteTarFileStep implements AsyncStep, Callable { +public class WriteTarFileStep implements Callable { - private final ListeningExecutorService listeningExecutorService; private final BuildConfiguration buildConfiguration; private final ProgressEventDispatcher.Factory progressEventDispatcherFactory; private final Path outputPath; - private final PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep; - private final ImmutableList buildAndCacheApplicationLayerSteps; - private final BuildImageStep buildImageStep; - - private final ListenableFuture listenableFuture; + private final Image builtImage; WriteTarFileStep( - ListeningExecutorService listeningExecutorService, BuildConfiguration buildConfiguration, ProgressEventDispatcher.Factory progressEventDispatcherFactory, Path outputPath, - PullAndCacheBaseImageLayersStep pullAndCacheBaseImageLayersStep, - ImmutableList buildAndCacheApplicationLayerSteps, - BuildImageStep buildImageStep) { - this.listeningExecutorService = listeningExecutorService; + Image builtImage) { this.buildConfiguration = buildConfiguration; this.progressEventDispatcherFactory = progressEventDispatcherFactory; this.outputPath = outputPath; - this.pullAndCacheBaseImageLayersStep = pullAndCacheBaseImageLayersStep; - this.buildAndCacheApplicationLayerSteps = buildAndCacheApplicationLayerSteps; - this.buildImageStep = buildImageStep; - - listenableFuture = - AsyncDependencies.using(listeningExecutorService) - .addStep(pullAndCacheBaseImageLayersStep) - .addStep(buildImageStep) - .whenAllSucceed(this); - } - - @Override - public ListenableFuture getFuture() { - return listenableFuture; + this.builtImage = builtImage; } @Override - public BuildResult call() throws ExecutionException, InterruptedException { - return AsyncDependencies.using(listeningExecutorService) - .addSteps(NonBlockingSteps.get(pullAndCacheBaseImageLayersStep)) - .addSteps(buildAndCacheApplicationLayerSteps) - .addStep(NonBlockingSteps.get(buildImageStep)) - .whenAllSucceed(this::writeTarFile) - .get(); - } - - private BuildResult writeTarFile() throws ExecutionException, IOException { + public BuildResult call() throws ExecutionException, InterruptedException, IOException { buildConfiguration .getEventHandlers() .dispatch(LogEvent.progress("Building image to tar file...")); try (ProgressEventDispatcher ignored = progressEventDispatcherFactory.create("writing to tar file", 1)) { - Image image = NonBlockingSteps.get(NonBlockingSteps.get(buildImageStep)); - // Builds the image to a tarball. Files.createDirectories(outputPath.getParent()); try (OutputStream outputStream = new BufferedOutputStream(FileOperations.newLockingOutputStream(outputPath))) { - new ImageTarball(image, buildConfiguration.getTargetImageConfiguration().getImage()) + new ImageTarball(builtImage, buildConfiguration.getTargetImageConfiguration().getImage()) .writeTo(outputStream); } - return BuildResult.fromImage(image, buildConfiguration.getTargetFormat()); + return BuildResult.fromImage(builtImage, buildConfiguration.getTargetFormat()); } } } diff --git a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java index b6309455a1..407c333348 100644 --- a/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java +++ b/jib-core/src/main/java/com/google/cloud/tools/jib/image/json/ImageToJsonTranslator.java @@ -219,7 +219,6 @@ public T getManifestTemplate( layer.getBlobDescriptor().getSize(), layer.getBlobDescriptor().getDigest()); } - // Serializes into JSON. return template; } catch (InstantiationException diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/api/JibContainerBuilderTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/api/JibContainerBuilderTest.java index b1b7359774..eb05866a7f 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/api/JibContainerBuilderTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/api/JibContainerBuilderTest.java @@ -17,7 +17,6 @@ package com.google.cloud.tools.jib.api; import com.google.cloud.tools.jib.builder.steps.BuildResult; -import com.google.cloud.tools.jib.builder.steps.StepsRunner; import com.google.cloud.tools.jib.configuration.BuildConfiguration; import com.google.cloud.tools.jib.configuration.ContainerConfiguration; import com.google.cloud.tools.jib.configuration.ImageConfiguration; @@ -263,14 +262,12 @@ private Containerizer createMockContainerizer() ImageReference targetImage = ImageReference.parse("target-image"); Containerizer mockContainerizer = Mockito.mock(Containerizer.class); - StepsRunner stepsRunner = Mockito.mock(StepsRunner.class); BuildResult mockBuildResult = Mockito.mock(BuildResult.class); Mockito.when(mockContainerizer.getImageConfiguration()) .thenReturn(ImageConfiguration.builder(targetImage).build()); - Mockito.when(mockContainerizer.createStepsRunner(Mockito.any(BuildConfiguration.class))) - .thenReturn(stepsRunner); - Mockito.when(stepsRunner.run()).thenReturn(mockBuildResult); + Mockito.when(mockContainerizer.run(Mockito.any(BuildConfiguration.class))) + .thenReturn(mockBuildResult); Mockito.when(mockBuildResult.getImageDigest()) .thenReturn( DescriptorDigest.fromHash( diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStepTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStepTest.java index f3d56e4725..a8c7a76068 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStepTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildAndCacheApplicationLayerStepTest.java @@ -19,7 +19,6 @@ import com.google.cloud.tools.jib.api.AbsoluteUnixPath; import com.google.cloud.tools.jib.api.LayerConfiguration; import com.google.cloud.tools.jib.api.LayerEntry; -import com.google.cloud.tools.jib.async.NonBlockingSteps; import com.google.cloud.tools.jib.blob.Blob; import com.google.cloud.tools.jib.blob.Blobs; import com.google.cloud.tools.jib.builder.ProgressEventDispatcher; @@ -32,13 +31,11 @@ import com.google.cloud.tools.jib.image.LayerPropertyNotFoundException; import com.google.common.collect.ImmutableList; import com.google.common.io.Resources; -import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; import java.net.URISyntaxException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.concurrent.ExecutionException; import java.util.stream.Stream; import org.junit.Assert; import org.junit.Before; @@ -126,18 +123,18 @@ public void setUp() throws IOException, URISyntaxException { Mockito.when(mockBuildConfiguration.getApplicationLayersCache()).thenReturn(cache); } - private ImageLayers buildFakeLayersToCache() throws ExecutionException { + private ImageLayers buildFakeLayersToCache() + throws LayerPropertyNotFoundException, IOException, CacheCorruptedException { ImageLayers.Builder applicationLayersBuilder = ImageLayers.builder(); ImmutableList buildAndCacheApplicationLayerSteps = BuildAndCacheApplicationLayerStep.makeList( - MoreExecutors.newDirectExecutorService(), mockBuildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()); for (BuildAndCacheApplicationLayerStep buildAndCacheApplicationLayerStep : buildAndCacheApplicationLayerSteps) { - applicationLayersBuilder.add(NonBlockingSteps.get(buildAndCacheApplicationLayerStep)); + applicationLayersBuilder.add(buildAndCacheApplicationLayerStep.call().getCachedLayer()); } return applicationLayersBuilder.build(); @@ -145,8 +142,7 @@ private ImageLayers buildFakeLayersToCache() throws ExecutionException { @Test public void testRun() - throws LayerPropertyNotFoundException, IOException, ExecutionException, - CacheCorruptedException { + throws LayerPropertyNotFoundException, IOException, CacheCorruptedException { ImmutableList fakeLayerConfigurations = ImmutableList.of( fakeDependenciesLayerConfiguration, @@ -207,8 +203,7 @@ public void testRun() } @Test - public void testRun_emptyLayersIgnored() - throws IOException, ExecutionException, CacheCorruptedException { + public void testRun_emptyLayersIgnored() throws IOException, CacheCorruptedException { ImmutableList fakeLayerConfigurations = ImmutableList.of( fakeDependenciesLayerConfiguration, diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java index 3da452d9c1..96b65640fa 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/BuildImageStepTest.java @@ -32,14 +32,11 @@ import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; -import com.google.common.util.concurrent.Futures; -import com.google.common.util.concurrent.MoreExecutors; import java.security.DigestException; import java.time.Duration; import java.time.Instant; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.stream.Stream; +import java.util.Arrays; +import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; @@ -52,17 +49,15 @@ @RunWith(MockitoJUnitRunner.class) public class BuildImageStepTest { - @Mock private EventHandlers mockEventHandlers; + @Mock private ProgressEventDispatcher.Factory mockProgressEventDispatcherFactory; @Mock private BuildConfiguration mockBuildConfiguration; @Mock private ContainerConfiguration mockContainerConfiguration; - @Mock private PullBaseImageStep mockPullBaseImageStep; - @Mock private PullAndCacheBaseImageLayersStep mockPullAndCacheBaseImageLayersStep; - @Mock private PullAndCacheBaseImageLayerStep mockPullAndCacheBaseImageLayerStep; - @Mock private BuildAndCacheApplicationLayerStep mockBuildAndCacheApplicationLayerStepDependencies; - @Mock private BuildAndCacheApplicationLayerStep mockBuildAndCacheApplicationLayerStepResources; - @Mock private BuildAndCacheApplicationLayerStep mockBuildAndCacheApplicationLayerStepClasses; - @Mock private BuildAndCacheApplicationLayerStep mockBuildAndCacheApplicationLayerStepExtraFiles; @Mock private CachedLayer mockCachedLayer; + + private Image baseImage; + private List baseImageLayers; + private List applicationLayers; + private DescriptorDigest testDescriptorDigest; private HistoryEntry nonEmptyLayerHistory; private HistoryEntry emptyLayerHistory; @@ -73,7 +68,7 @@ public void setUp() throws DigestException { DescriptorDigest.fromHash( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"); - Mockito.when(mockBuildConfiguration.getEventHandlers()).thenReturn(mockEventHandlers); + Mockito.when(mockBuildConfiguration.getEventHandlers()).thenReturn(EventHandlers.NONE); Mockito.when(mockBuildConfiguration.getContainerConfiguration()) .thenReturn(mockContainerConfiguration); Mockito.when(mockBuildConfiguration.getToolName()).thenReturn("jib"); @@ -100,7 +95,7 @@ public void setUp() throws DigestException { .setEmptyLayer(true) .build(); - Image baseImage = + baseImage = Image.builder(V22ManifestTemplate.class) .setArchitecture("wasm") .setOs("js") @@ -125,60 +120,35 @@ public void setUp() throws DigestException { .addHistory(emptyLayerHistory) .addHistory(emptyLayerHistory) .build(); - Mockito.when(mockPullAndCacheBaseImageLayerStep.getFuture()) - .thenReturn(Futures.immediateFuture(mockCachedLayer)); - Mockito.when(mockPullAndCacheBaseImageLayersStep.getFuture()) - .thenReturn( - Futures.immediateFuture( - ImmutableList.of( - mockPullAndCacheBaseImageLayerStep, - mockPullAndCacheBaseImageLayerStep, - mockPullAndCacheBaseImageLayerStep))); - Mockito.when(mockPullBaseImageStep.getFuture()) - .thenReturn( - Futures.immediateFuture( - new PullBaseImageStep.BaseImageWithAuthorization(baseImage, null))); - - Stream.of( - mockBuildAndCacheApplicationLayerStepClasses, - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepExtraFiles, - mockBuildAndCacheApplicationLayerStepResources) - .forEach( - layerStep -> - Mockito.when(layerStep.getFuture()) - .thenReturn(Futures.immediateFuture(mockCachedLayer))); - - Mockito.when(mockBuildAndCacheApplicationLayerStepClasses.getLayerType()).thenReturn("classes"); - Mockito.when(mockBuildAndCacheApplicationLayerStepDependencies.getLayerType()) - .thenReturn("dependencies"); - Mockito.when(mockBuildAndCacheApplicationLayerStepExtraFiles.getLayerType()) - .thenReturn("extra files"); - Mockito.when(mockBuildAndCacheApplicationLayerStepResources.getLayerType()) - .thenReturn("resources"); + baseImageLayers = + Arrays.asList( + new CachedLayerAndName(mockCachedLayer, null), + new CachedLayerAndName(mockCachedLayer, null), + new CachedLayerAndName(mockCachedLayer, null)); + applicationLayers = + Arrays.asList( + new CachedLayerAndName(mockCachedLayer, "dependencies"), + new CachedLayerAndName(mockCachedLayer, "resources"), + new CachedLayerAndName(mockCachedLayer, "classes"), + new CachedLayerAndName(mockCachedLayer, "extra files")); } @Test - public void test_validateAsyncDependencies() throws ExecutionException, InterruptedException { - BuildImageStep buildImageStep = + public void test_validateAsyncDependencies() { + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals( testDescriptorDigest, image.getLayers().asList().get(0).getBlobDescriptor().getDigest()); } @Test - public void test_propagateBaseImageConfiguration() - throws ExecutionException, InterruptedException { + public void test_propagateBaseImageConfiguration() { Mockito.when(mockContainerConfiguration.getEnvironmentMap()) .thenReturn(ImmutableMap.of("MY_ENV", "MY_ENV_VALUE", "BASE_ENV_2", "NEW_VALUE")); Mockito.when(mockContainerConfiguration.getLabels()) @@ -189,18 +159,14 @@ public void test_propagateBaseImageConfiguration() .thenReturn( ImmutableSet.of( AbsoluteUnixPath.get("/new/path1"), AbsoluteUnixPath.get("/new/path2"))); - BuildImageStep buildImageStep = + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals("wasm", image.getArchitecture()); Assert.assertEquals("js", image.getOs()); Assert.assertEquals( @@ -248,110 +214,88 @@ public void test_propagateBaseImageConfiguration() } @Test - public void testOverrideWorkingDirectory() throws InterruptedException, ExecutionException { + public void testOverrideWorkingDirectory() { Mockito.when(mockContainerConfiguration.getWorkingDirectory()) .thenReturn(AbsoluteUnixPath.get("/my/directory")); - BuildImageStep buildImageStep = + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals("/my/directory", image.getWorkingDirectory()); } @Test - public void test_inheritedEntrypoint() throws ExecutionException, InterruptedException { + public void test_inheritedEntrypoint() { Mockito.when(mockContainerConfiguration.getEntrypoint()).thenReturn(null); Mockito.when(mockContainerConfiguration.getProgramArguments()) .thenReturn(ImmutableList.of("test")); - BuildImageStep buildImageStep = + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals(ImmutableList.of("baseImageEntrypoint"), image.getEntrypoint()); Assert.assertEquals(ImmutableList.of("test"), image.getProgramArguments()); } @Test - public void test_inheritedEntrypointAndProgramArguments() - throws ExecutionException, InterruptedException { + public void test_inheritedEntrypointAndProgramArguments() { Mockito.when(mockContainerConfiguration.getEntrypoint()).thenReturn(null); Mockito.when(mockContainerConfiguration.getProgramArguments()).thenReturn(null); - BuildImageStep buildImageStep = + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals(ImmutableList.of("baseImageEntrypoint"), image.getEntrypoint()); Assert.assertEquals(ImmutableList.of("catalina.sh", "run"), image.getProgramArguments()); } @Test - public void test_notInheritedProgramArguments() throws ExecutionException, InterruptedException { + public void test_notInheritedProgramArguments() { Mockito.when(mockContainerConfiguration.getEntrypoint()) .thenReturn(ImmutableList.of("myEntrypoint")); Mockito.when(mockContainerConfiguration.getProgramArguments()).thenReturn(null); - BuildImageStep buildImageStep = + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); Assert.assertEquals(ImmutableList.of("myEntrypoint"), image.getEntrypoint()); Assert.assertNull(image.getProgramArguments()); } @Test - public void test_generateHistoryObjects() throws ExecutionException, InterruptedException { - BuildImageStep buildImageStep = + public void test_generateHistoryObjects() { + Image image = new BuildImageStep( - MoreExecutors.listeningDecorator(Executors.newSingleThreadExecutor()), - mockBuildConfiguration, - ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer(), - mockPullBaseImageStep, - mockPullAndCacheBaseImageLayersStep, - ImmutableList.of( - mockBuildAndCacheApplicationLayerStepDependencies, - mockBuildAndCacheApplicationLayerStepResources, - mockBuildAndCacheApplicationLayerStepClasses, - mockBuildAndCacheApplicationLayerStepExtraFiles)); - Image image = buildImageStep.getFuture().get().getFuture().get(); + mockBuildConfiguration, + mockProgressEventDispatcherFactory, + baseImage, + baseImageLayers, + applicationLayers) + .call(); // Make sure history is as expected HistoryEntry expectedAddedBaseLayerHistory = diff --git a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStepTest.java b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStepTest.java index ad4ce0a2b4..2121f33c81 100644 --- a/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStepTest.java +++ b/jib-core/src/test/java/com/google/cloud/tools/jib/builder/steps/RetrieveRegistryCredentialsStepTest.java @@ -26,7 +26,6 @@ import com.google.cloud.tools.jib.event.EventHandlers; import com.google.cloud.tools.jib.event.events.ProgressEvent; import com.google.cloud.tools.jib.registry.credentials.CredentialRetrievalException; -import com.google.common.util.concurrent.ListeningExecutorService; import com.google.common.util.concurrent.MoreExecutors; import java.io.IOException; import java.nio.file.Paths; @@ -46,7 +45,6 @@ public class RetrieveRegistryCredentialsStepTest { @Mock private EventHandlers mockEventHandlers; - @Mock private ListeningExecutorService mockListeningExecutorService; @Test public void testCall_retrieved() throws CredentialRetrievalException, IOException { @@ -62,14 +60,12 @@ public void testCall_retrieved() throws CredentialRetrievalException, IOExceptio Assert.assertEquals( Credential.from("baseusername", "basepassword"), RetrieveRegistryCredentialsStep.forBaseImage( - mockListeningExecutorService, buildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()) .call()); Assert.assertEquals( Credential.from("targetusername", "targetpassword"), RetrieveRegistryCredentialsStep.forTargetImage( - mockListeningExecutorService, buildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()) .call()); @@ -82,7 +78,6 @@ public void testCall_none() throws CredentialRetrievalException, IOException { Arrays.asList(Optional::empty, Optional::empty), Collections.emptyList()); Assert.assertNull( RetrieveRegistryCredentialsStep.forBaseImage( - mockListeningExecutorService, buildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()) .call()); @@ -94,7 +89,6 @@ public void testCall_none() throws CredentialRetrievalException, IOException { Assert.assertNull( RetrieveRegistryCredentialsStep.forTargetImage( - mockListeningExecutorService, buildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()) .call()); @@ -116,7 +110,6 @@ public void testCall_exception() throws IOException { Collections.emptyList()); try { RetrieveRegistryCredentialsStep.forBaseImage( - mockListeningExecutorService, buildConfiguration, ProgressEventDispatcher.newRoot(mockEventHandlers, "ignored", 1).newChildProducer()) .call(); diff --git a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/JibBuildRunnerTest.java b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/JibBuildRunnerTest.java index 4f1135bbf3..f5e775609d 100644 --- a/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/JibBuildRunnerTest.java +++ b/jib-plugins-common/src/test/java/com/google/cloud/tools/jib/plugins/common/JibBuildRunnerTest.java @@ -91,7 +91,7 @@ public void testBuildImage_httpHostConnectException() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals(TEST_HELPFUL_SUGGESTIONS.forHttpHostConnect(), ex.getMessage()); @@ -110,7 +110,7 @@ public void testBuildImage_unknownHostException() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals(TEST_HELPFUL_SUGGESTIONS.forUnknownHost(), ex.getMessage()); @@ -130,7 +130,7 @@ public void testBuildImage_insecureRegistryException() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals(TEST_HELPFUL_SUGGESTIONS.forInsecureRegistry(), ex.getMessage()); @@ -155,7 +155,7 @@ public void testBuildImage_registryUnauthorizedException_statusCodeForbidden() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals( @@ -181,7 +181,7 @@ public void testBuildImage_registryUnauthorizedException_noCredentials() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals( @@ -201,7 +201,7 @@ public void testBuildImage_registryCredentialsNotSentException() try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals(TEST_HELPFUL_SUGGESTIONS.forCredentialsNotSent(), ex.getMessage()); @@ -212,15 +212,14 @@ public void testBuildImage_registryCredentialsNotSentException() public void testBuildImage_other() throws InterruptedException, IOException, CacheDirectoryCreationException, RegistryException, ExecutionException { - RegistryException registryException = new RegistryException("messagePrefix"); - Mockito.doThrow(registryException) + Mockito.doThrow(new RegistryException("messagePrefix")) .when(mockJibContainerBuilder) .containerize(mockContainerizer); try { testJibBuildRunner.build( mockJibContainerBuilder, mockContainerizer, logEvent -> {}, TEST_HELPFUL_SUGGESTIONS); - Assert.fail("buildImage should have thrown an exception"); + Assert.fail(); } catch (BuildStepsExecutionException ex) { Assert.assertEquals(TEST_HELPFUL_SUGGESTIONS.none(), ex.getMessage());