Skip to content

Commit e823b55

Browse files
bkelley17rohanKanojia
authored andcommitted
Allow the "retries" parameter to apply to pull as well as push.
Signed-off-by: Ben Kelley <[email protected]>
1 parent bb612ed commit e823b55

20 files changed

+141
-56
lines changed

src/main/asciidoc/inc/build/_configuration.adoc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,9 @@ a| Scan the archive specified in `dockerArchive` and find the actual repository
120120
| *shell*
121121
| Shell to be used for the *runCmds*. It contains *arg* elements which are defining the executable and its params.
122122

123+
| *retries*
124+
| If pulling an image is required, how often should a pull be retried before giving up. This useful for flaky registries which tend to return 500 error codes from time to time. The default is 0 which means no retry at all.
125+
123126
| *runCmds*
124127
| Commands to be run during the build process. It contains *run* elements which are passed to the shell. Whitespace is trimmed from each element and empty elements are ignored. The run commands are inserted right after the assembly and after *workdir* into the Dockerfile. This tag is not to be confused with the `<run>` section for this image which specifies the runtime behaviour when starting containers.
125128

src/main/asciidoc/inc/start/_configuration.adoc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ In addition to the <<global-configuration>>, this goal supports the following gl
99
| Default pattern for naming all containers when they are created. See <<container-name, Container Names>> for details.
1010
| `docker.containerNamePattern`
1111

12+
| *retries*
13+
| If pulling an image is required, how often should a pull be retried before giving up. This useful for flaky registries which tend to return 500 error codes from time to time. The default is 0 which means no retry at all.
14+
| `docker.pull.retries`
15+
1216
| *showLogs*
1317
| In order to switch on globally the logs *showLogs* can be used as global configuration (i.e. outside of `<images>`). If set it will print out all standard
1418
output and standard error messages for all containers started. As value the images for which logs should be shown can be given as a comma separated list.
@@ -18,7 +22,6 @@ In addition to the <<global-configuration>>, this goal supports the following gl
1822
| *startParallel*
1923
| Starts docker images in parallel while dependencies expressed as <<start-links,Link>> or <<start-depends-on,dependsOn>> are respected. This option can significantly reduce the startup time because independent containers do not need to wait for each other.
2024
| `docker.startParallel`
21-
2225
|===
2326

2427
The `<run>` configuration element knows the following sub elements:

src/main/asciidoc/inc/watch/_configuration.adoc

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,22 @@ below how this can be specified.
4949
| *watchPostGoal*
5050
| A maven goal which should be called if a rebuild or a restart has been performed. This goal must have the format `<pluginGroupId>:<pluginArtifactId>:<goal>` and the plugin must be configured in the `pom.xml`. For example a post-goal `io.fabric8:fabric8:delete-pods` will trigger the deletion of PODs in Kubernetes which in turn triggers are new start of a POD within the Kubernetes cluster. The value specified here is the the default post goal which can be overridden by `<postGoal>` in a `<watch>` configuration.
5151
|
52+
53+
| *keepRunning*
54+
| If set to `true` all container will be kept running after `{plugin}:watch` has been stopped. By default this is set to `false`.
55+
| `docker.keepRunning`
56+
57+
| *keepContainer*
58+
| As for `{plugin}:stop`, if this is set to `true` (and `keepRunning` is disabled) then all container will be removed after they have been stopped. The default is `true`.
59+
| `docker.keepContainer`
60+
61+
| *removeVolumes*
62+
| if set to `true` will remove any volumes associated to the container as well. This option will be ignored if either `keepContainer` or `keepRunning` are `true`.
63+
| `docker.removeVolumes`
64+
65+
| *retries*
66+
| If pulling an image is required, how often should a pull be retried before giving up. This useful for flaky registries which tend to return 500 error codes from time to time. The default is 0 which means no retry at all.
67+
| `docker.pull.retries`
5268
|===
5369

5470
Image specific watch configuration goes into an extra image-level `<watch>` section (i.e. `+<image><watch>...</watch></image>+`). The following parameters are recognized:

src/main/java/io/fabric8/maven/docker/AbstractDockerMojo.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,9 @@ public abstract class AbstractDockerMojo extends AbstractMojo implements Context
121121
@Parameter(property = "docker.removeVolumes", defaultValue = "false")
122122
protected boolean removeVolumes;
123123

124+
@Parameter(property = "docker.pull.retries", defaultValue = "0")
125+
protected int retries;
126+
124127
@Parameter(property = "docker.apiVersion")
125128
private String apiVersion;
126129

@@ -577,7 +580,7 @@ protected void pullImage(RegistryService registryService, ImageConfiguration ima
577580
RunImageConfiguration runConfiguration = imageConfig.getRunConfiguration();
578581
ImagePullManager pullManager = getImagePullManager(determinePullPolicy(runConfiguration), autoPull);
579582
RegistryConfig registryConfig = getRegistryConfig(pullRegistry);
580-
registryService.pullImageWithPolicy(imageName, pullManager, registryConfig, imageConfig.getBuildConfiguration());
583+
registryService.pullImageWithPolicy(imageName, pullManager, registryConfig, imageConfig.getBuildConfiguration(), retries);
581584
}
582585

583586
protected boolean shouldSkipPom() {
@@ -601,7 +604,7 @@ private boolean containerMatchesPattern(Container container, Matcher imageNameMa
601604
}
602605
}
603606

604-
private String determinePullPolicy(RunImageConfiguration runConfig) {
607+
protected String determinePullPolicy(RunImageConfiguration runConfig) {
605608
return runConfig.getImagePullPolicy() != null ? runConfig.getImagePullPolicy() : imagePullPolicy;
606609
}
607610

src/main/java/io/fabric8/maven/docker/BuildMojo.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ public class BuildMojo extends AbstractBuildSupportMojo {
6464
*/
6565
@Parameter(property = "docker.skip.tag", defaultValue = "false")
6666
protected boolean skipTag;
67+
@Parameter(property = "docker.pull.retries", defaultValue = "0")
68+
private int retries;
6769

6870
@Override
6971
protected void executeInternal(ServiceHub hub) throws IOException, MojoExecutionException {
@@ -111,7 +113,7 @@ private void proceedWithDockerBuild(ServiceHub hub, BuildService.BuildContext bu
111113
if (imageConfig.isBuildX()) {
112114
hub.getBuildXService().build(createProjectPaths(), imageConfig, null, getAuthConfig(imageConfig), buildArchiveFile);
113115
} else {
114-
buildService.buildImage(imageConfig, pullManager, buildContext, buildArchiveFile);
116+
buildService.buildImage(imageConfig, pullManager, buildContext, buildArchiveFile, retries);
115117
if (!skipTag) {
116118
buildService.tagImage(imageConfig);
117119
}

src/main/java/io/fabric8/maven/docker/StartMojo.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import io.fabric8.maven.docker.config.RunVolumeConfiguration;
3535
import io.fabric8.maven.docker.config.VolumeConfiguration;
3636
import io.fabric8.maven.docker.log.LogDispatcher;
37+
import io.fabric8.maven.docker.service.ImagePullManager;
3738
import io.fabric8.maven.docker.service.QueryService;
3839
import io.fabric8.maven.docker.service.RegistryService;
3940
import io.fabric8.maven.docker.service.RunService;
@@ -336,6 +337,7 @@ private Queue<ImageConfiguration> prepareStart(ServiceHub hub, QueryService quer
336337
pullImage(registryService, imageConfig, pullRegistry);
337338

338339
RunImageConfiguration runConfig = imageConfig.getRunConfiguration();
340+
339341
NetworkConfig config = runConfig.getNetworkingConfig();
340342
List<String> bindMounts = extractBindMounts(runConfig.getVolumeConfiguration());
341343
List<VolumeConfiguration> volumes = getVolumes();

src/main/java/io/fabric8/maven/docker/WatchMojo.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,17 @@ public class WatchMojo extends AbstractBuildSupportMojo {
7373
@Parameter(property = "docker.autoCreateCustomNetworks", defaultValue = "false")
7474
protected boolean autoCreateCustomNetworks;
7575

76+
@Parameter(property = "docker.pull.retries", defaultValue = "0")
77+
private int retries;
78+
7679
@Override
7780
protected synchronized void executeInternal(ServiceHub hub) throws IOException,
7881
MojoExecutionException {
7982

8083
BuildService.BuildContext buildContext = getBuildContext();
8184
WatchService.WatchContext watchContext = getWatchContext(hub);
8285

83-
hub.getWatchService().watch(watchContext, buildContext, getResolvedImages());
86+
hub.getWatchService().watch(watchContext, buildContext, getResolvedImages(), retries);
8487
}
8588

8689
protected WatchService.WatchContext getWatchContext(ServiceHub hub) throws IOException {

src/main/java/io/fabric8/maven/docker/access/DockerAccess.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -241,7 +241,7 @@ void copyArchiveFromContainer(String containerId, String containerPath, File arc
241241
* @param options additional query arguments to add when creating the image. Can be null.
242242
* @throws DockerAccessException if the image couldn't be pulled.
243243
*/
244-
void pullImage(String image, AuthConfig authConfig, String registry, CreateImageOptions options) throws DockerAccessException;
244+
void pullImage(String image, AuthConfig authConfig, String registry, CreateImageOptions options, int retries) throws DockerAccessException;
245245

246246
/**
247247
* Push an image to a registry. A registry can be specified which is used as target

src/main/java/io/fabric8/maven/docker/access/hc/DockerAccessWithHcClient.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -535,13 +535,12 @@ public void loadImage(String image, File tarArchive) throws DockerAccessExceptio
535535
}
536536

537537
@Override
538-
public void pullImage(String image, AuthConfig authConfig, String registry, CreateImageOptions options)
538+
public void pullImage(String image, AuthConfig authConfig, String registry, CreateImageOptions options, int retries)
539539
throws DockerAccessException {
540540
String pullUrl = urlBuilder.pullImage(options);
541541
log.verbose(Logger.LogVerboseCategory.API, API_LOG_FORMAT_POST, pullUrl);
542542
try {
543-
delegate.post(pullUrl, null, createAuthHeader(authConfig),
544-
createPullOrPushResponseHandler(), HTTP_OK);
543+
doPushPullImage(pullUrl, createAuthHeader(authConfig), createBuildResponseHandler(), HTTP_OK, retries);
545544
} catch (IOException e) {
546545
throw new DockerAccessException(e, "Unable to pull '%s'%s", image, (registry != null) ? " from registry '" + registry + "'" : "");
547546
}
@@ -556,7 +555,7 @@ public void pushImage(String image, AuthConfig authConfig, String registry, int
556555
TemporaryImageHandler temporaryImageHandler = tagTemporaryImage(name, registry);
557556
DockerAccessException dae = null;
558557
try {
559-
doPushImage(pushUrl, createAuthHeader(authConfig), createPullOrPushResponseHandler(), HTTP_OK, retries);
558+
doPushPullImage(pushUrl, createAuthHeader(authConfig), createPullOrPushResponseHandler(), HTTP_OK, retries);
560559
} catch (IOException e) {
561560
dae = new DockerAccessException(e, "Unable to push '%s'%s", image, (registry != null) ? " to registry '" + registry + "'" : "");
562561
throw dae;
@@ -764,16 +763,16 @@ private boolean isRetryableErrorCode(int errorCode) {
764763
return errorCode == HTTP_INTERNAL_ERROR;
765764
}
766765

767-
private void doPushImage(String url, Map<String, String> header, HcChunkedResponseHandlerWrapper handler, int status,
766+
private void doPushPullImage(String url, Map<String, String> header, HcChunkedResponseHandlerWrapper handler, int status,
768767
int retries) throws IOException {
769768
// 0: The original attempt, 1..retry: possible retries.
770769
for (int i = 0; i <= retries; i++) {
771770
try {
772-
delegate.post(url, null, header, handler, HTTP_OK);
771+
delegate.post(url, null, header, handler, status);
773772
return;
774773
} catch (HttpResponseException e) {
775774
if (isRetryableErrorCode(e.getStatusCode()) && i != retries) {
776-
log.warn("failed to push image to [{}], retrying...", url);
775+
log.warn("failed to push/pull image to/from [%s], retrying...", url);
777776
} else {
778777
throw e;
779778
}

src/main/java/io/fabric8/maven/docker/service/BuildService.java

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,15 +57,16 @@ public class BuildService {
5757
*
5858
* @param imageConfig the image configuration
5959
* @param buildContext the build context
60+
* @param pullRetries the number of times to retry if pulling an image fails
6061
* @throws DockerAccessException
6162
* @throws MojoExecutionException
6263
*/
63-
public void buildImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext, File buildArchiveFile)
64+
public void buildImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext, File buildArchiveFile, int pullRetries)
6465
throws DockerAccessException, MojoExecutionException {
6566

6667
if (imagePullManager != null) {
67-
autoPullBaseImage(imageConfig, imagePullManager, buildContext);
68-
autoPullCacheFromImage(imageConfig, imagePullManager, buildContext);
68+
autoPullBaseImage(imageConfig, imagePullManager, buildContext, pullRetries);
69+
autoPullCacheFromImage(imageConfig, imagePullManager, buildContext, pullRetries);
6970
}
7071

7172
buildImage(imageConfig, buildContext.getMojoParameters(), checkForNocache(imageConfig), checkForSquash(imageConfig), addBuildArgs(buildContext), buildArchiveFile);
@@ -356,7 +357,7 @@ private Map<String, String> addBuildArgsFromDockerConfig() {
356357
return buildArgs;
357358
}
358359

359-
private void autoPullBaseImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext)
360+
private void autoPullBaseImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext, int pullRetries)
360361
throws DockerAccessException, MojoExecutionException {
361362
BuildImageConfiguration buildConfig = imageConfig.getBuildConfiguration();
362363
CleanupMode cleanupMode = buildConfig.cleanupMode();
@@ -383,7 +384,7 @@ private void autoPullBaseImage(ImageConfiguration imageConfig, ImagePullManager
383384
oldImageId = queryService.getImageId(fromImage);
384385
}
385386

386-
registryService.pullImageWithPolicy(fromImage, imagePullManager, buildContext.getRegistryConfig(), buildConfig);
387+
registryService.pullImageWithPolicy(fromImage, imagePullManager, buildContext.getRegistryConfig(), buildConfig, pullRetries);
387388

388389
String newImageId = queryService.getImageId(fromImage);
389390

@@ -392,7 +393,7 @@ private void autoPullBaseImage(ImageConfiguration imageConfig, ImagePullManager
392393
}
393394
}
394395

395-
private void autoPullCacheFromImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext) throws DockerAccessException, MojoExecutionException {
396+
private void autoPullCacheFromImage(ImageConfiguration imageConfig, ImagePullManager imagePullManager, BuildContext buildContext, int pullRetries) throws DockerAccessException, MojoExecutionException {
396397
if (imageConfig.getBuildConfiguration().getCacheFrom() == null) {
397398
return;
398399
}
@@ -407,7 +408,7 @@ private void autoPullCacheFromImage(ImageConfiguration imageConfig, ImagePullMan
407408
}
408409

409410
try {
410-
registryService.pullImageWithPolicy(cacheFromImage, imagePullManager, buildContext.getRegistryConfig(), buildConfig);
411+
registryService.pullImageWithPolicy(cacheFromImage, imagePullManager, buildContext.getRegistryConfig(), buildConfig, pullRetries);
411412
} catch (DockerAccessException e) {
412413
log.warn("Could not pull cacheFrom image: '%s'. Reason: %s", cacheFromImage, e.getMessage());
413414
}

0 commit comments

Comments
 (0)