mirror of
https://github.com/honeymoose/OpenSearch.git
synced 2025-02-27 15:39:49 +00:00
Explicitly retry failed docker pulls (#63946)
Closes #63869. Perform `docker pull` explicitly instead of as part of `docker build`, and wrap it in a retry loop. This is an attempt to make the build more resilient to transient errors.
This commit is contained in:
parent
2e77523923
commit
410fac5970
@ -20,8 +20,11 @@ package org.elasticsearch.gradle.docker;
|
|||||||
|
|
||||||
import org.elasticsearch.gradle.LoggedExec;
|
import org.elasticsearch.gradle.LoggedExec;
|
||||||
import org.gradle.api.DefaultTask;
|
import org.gradle.api.DefaultTask;
|
||||||
|
import org.gradle.api.GradleException;
|
||||||
import org.gradle.api.file.DirectoryProperty;
|
import org.gradle.api.file.DirectoryProperty;
|
||||||
import org.gradle.api.file.RegularFileProperty;
|
import org.gradle.api.file.RegularFileProperty;
|
||||||
|
import org.gradle.api.logging.Logger;
|
||||||
|
import org.gradle.api.logging.Logging;
|
||||||
import org.gradle.api.provider.ListProperty;
|
import org.gradle.api.provider.ListProperty;
|
||||||
import org.gradle.api.provider.Property;
|
import org.gradle.api.provider.Property;
|
||||||
import org.gradle.api.tasks.Input;
|
import org.gradle.api.tasks.Input;
|
||||||
@ -40,6 +43,8 @@ import java.io.IOException;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
|
||||||
public class DockerBuildTask extends DefaultTask {
|
public class DockerBuildTask extends DefaultTask {
|
||||||
|
private static final Logger LOGGER = Logging.getLogger(DockerBuildTask.class);
|
||||||
|
|
||||||
private final WorkerExecutor workerExecutor;
|
private final WorkerExecutor workerExecutor;
|
||||||
private final RegularFileProperty markerFile = getProject().getObjects().fileProperty();
|
private final RegularFileProperty markerFile = getProject().getObjects().fileProperty();
|
||||||
private final DirectoryProperty dockerContext = getProject().getObjects().directoryProperty();
|
private final DirectoryProperty dockerContext = getProject().getObjects().directoryProperty();
|
||||||
@ -47,6 +52,7 @@ public class DockerBuildTask extends DefaultTask {
|
|||||||
private String[] tags;
|
private String[] tags;
|
||||||
private boolean pull = true;
|
private boolean pull = true;
|
||||||
private boolean noCache = true;
|
private boolean noCache = true;
|
||||||
|
private String[] baseImages;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DockerBuildTask(WorkerExecutor workerExecutor) {
|
public DockerBuildTask(WorkerExecutor workerExecutor) {
|
||||||
@ -62,6 +68,7 @@ public class DockerBuildTask extends DefaultTask {
|
|||||||
params.getTags().set(Arrays.asList(tags));
|
params.getTags().set(Arrays.asList(tags));
|
||||||
params.getPull().set(pull);
|
params.getPull().set(pull);
|
||||||
params.getNoCache().set(noCache);
|
params.getNoCache().set(noCache);
|
||||||
|
params.getBaseImages().set(baseImages);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -98,6 +105,15 @@ public class DockerBuildTask extends DefaultTask {
|
|||||||
this.noCache = noCache;
|
this.noCache = noCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Input
|
||||||
|
public String[] getBaseImages() {
|
||||||
|
return baseImages;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBaseImages(String[] baseImages) {
|
||||||
|
this.baseImages = baseImages;
|
||||||
|
}
|
||||||
|
|
||||||
@OutputFile
|
@OutputFile
|
||||||
public RegularFileProperty getMarkerFile() {
|
public RegularFileProperty getMarkerFile() {
|
||||||
return markerFile;
|
return markerFile;
|
||||||
@ -111,26 +127,56 @@ public class DockerBuildTask extends DefaultTask {
|
|||||||
this.execOperations = execOperations;
|
this.execOperations = execOperations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wraps `docker pull` in a retry loop, to try and provide some resilience against
|
||||||
|
* transient errors
|
||||||
|
* @param baseImage the image to pull.
|
||||||
|
*/
|
||||||
|
private void pullBaseImage(String baseImage) {
|
||||||
|
final int maxAttempts = 10;
|
||||||
|
|
||||||
|
for (int attempt = 1; attempt <= maxAttempts; attempt++) {
|
||||||
|
try {
|
||||||
|
LoggedExec.exec(execOperations, spec -> {
|
||||||
|
spec.executable("docker");
|
||||||
|
spec.args("pull");
|
||||||
|
spec.args(baseImage);
|
||||||
|
});
|
||||||
|
|
||||||
|
return;
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.warn("Attempt {}/{} to pull Docker base image {} failed", attempt, maxAttempts, baseImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we successfully ran `docker pull` above, we would have returned before this point.
|
||||||
|
throw new GradleException("Failed to pull Docker base image [" + baseImage + "], all attempts failed");
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute() {
|
public void execute() {
|
||||||
|
final Parameters parameters = getParameters();
|
||||||
|
|
||||||
|
if (parameters.getPull().get()) {
|
||||||
|
for (String baseImage : parameters.getBaseImages().get()) {
|
||||||
|
pullBaseImage(baseImage);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
LoggedExec.exec(execOperations, spec -> {
|
LoggedExec.exec(execOperations, spec -> {
|
||||||
spec.executable("docker");
|
spec.executable("docker");
|
||||||
|
|
||||||
spec.args("build", getParameters().getDockerContext().get().getAsFile().getAbsolutePath());
|
spec.args("build", parameters.getDockerContext().get().getAsFile().getAbsolutePath());
|
||||||
|
|
||||||
if (getParameters().getPull().get()) {
|
if (parameters.getNoCache().get()) {
|
||||||
spec.args("--pull");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (getParameters().getNoCache().get()) {
|
|
||||||
spec.args("--no-cache");
|
spec.args("--no-cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
getParameters().getTags().get().forEach(tag -> spec.args("--tag", tag));
|
parameters.getTags().get().forEach(tag -> spec.args("--tag", tag));
|
||||||
});
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
getParameters().getMarkerFile().getAsFile().get().createNewFile();
|
parameters.getMarkerFile().getAsFile().get().createNewFile();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("Failed to create marker file", e);
|
throw new RuntimeException("Failed to create marker file", e);
|
||||||
}
|
}
|
||||||
@ -147,5 +193,7 @@ public class DockerBuildTask extends DefaultTask {
|
|||||||
Property<Boolean> getPull();
|
Property<Boolean> getPull();
|
||||||
|
|
||||||
Property<Boolean> getNoCache();
|
Property<Boolean> getNoCache();
|
||||||
|
|
||||||
|
Property<String[]> getBaseImages();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -225,6 +225,7 @@ void addBuildDockerImage(Architecture architecture, boolean oss, DockerBase base
|
|||||||
TaskProvider<Sync> copyContextTask = tasks.named(taskName("copy", architecture, oss, base, "DockerContext"))
|
TaskProvider<Sync> copyContextTask = tasks.named(taskName("copy", architecture, oss, base, "DockerContext"))
|
||||||
dependsOn(copyContextTask)
|
dependsOn(copyContextTask)
|
||||||
dockerContext.fileProvider(copyContextTask.map { it.destinationDir })
|
dockerContext.fileProvider(copyContextTask.map { it.destinationDir })
|
||||||
|
baseImages = [ base.getImage() ]
|
||||||
|
|
||||||
String version = VersionProperties.elasticsearch
|
String version = VersionProperties.elasticsearch
|
||||||
if (oss) {
|
if (oss) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user