org.opensearch.gradle.docker.DockerBuildTask Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of build-tools Show documentation
Show all versions of build-tools Show documentation
OpenSearch subproject :build-tools
/*
* SPDX-License-Identifier: Apache-2.0
*
* The OpenSearch Contributors require contributions made to
* this file be licensed under the Apache-2.0 license or a
* compatible open source license.
*/
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you 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.
*/
/*
* Modifications Copyright OpenSearch Contributors. See
* GitHub history for details.
*/
package org.opensearch.gradle.docker;
import org.opensearch.gradle.LoggedExec;
import org.gradle.api.DefaultTask;
import org.gradle.api.GradleException;
import org.gradle.api.file.DirectoryProperty;
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.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputDirectory;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.PathSensitive;
import org.gradle.api.tasks.PathSensitivity;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecOperations;
import org.gradle.workers.WorkAction;
import org.gradle.workers.WorkParameters;
import org.gradle.workers.WorkerExecutor;
import javax.inject.Inject;
import java.io.IOException;
import java.util.Arrays;
public class DockerBuildTask extends DefaultTask {
private static final Logger LOGGER = Logging.getLogger(DockerBuildTask.class);
private final WorkerExecutor workerExecutor;
private final RegularFileProperty markerFile = getProject().getObjects().fileProperty();
private final DirectoryProperty dockerContext = getProject().getObjects().directoryProperty();
private String[] tags;
private boolean pull = true;
private boolean noCache = true;
private String[] baseImages;
@Inject
public DockerBuildTask(WorkerExecutor workerExecutor) {
this.workerExecutor = workerExecutor;
this.markerFile.set(getProject().getLayout().getBuildDirectory().file("markers/" + this.getName() + ".marker"));
}
@TaskAction
public void build() {
workerExecutor.noIsolation().submit(DockerBuildAction.class, params -> {
params.getDockerContext().set(dockerContext);
params.getMarkerFile().set(markerFile);
params.getTags().set(Arrays.asList(tags));
params.getPull().set(pull);
params.getNoCache().set(noCache);
params.getBaseImages().set(baseImages);
});
}
@InputDirectory
@PathSensitive(PathSensitivity.RELATIVE)
public DirectoryProperty getDockerContext() {
return dockerContext;
}
@Input
public String[] getTags() {
return tags;
}
public void setTags(String[] tags) {
this.tags = tags;
}
@Input
public boolean isPull() {
return pull;
}
public void setPull(boolean pull) {
this.pull = pull;
}
@Input
public boolean isNoCache() {
return noCache;
}
public void setNoCache(boolean noCache) {
this.noCache = noCache;
}
@Input
public String[] getBaseImages() {
return baseImages;
}
public void setBaseImages(String[] baseImages) {
this.baseImages = baseImages;
}
@OutputFile
public RegularFileProperty getMarkerFile() {
return markerFile;
}
public abstract static class DockerBuildAction implements WorkAction {
private final ExecOperations execOperations;
@Inject
public DockerBuildAction(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
public void execute() {
final Parameters parameters = getParameters();
if (parameters.getPull().get()) {
for (String baseImage : parameters.getBaseImages().get()) {
pullBaseImage(baseImage);
}
}
LoggedExec.exec(execOperations, spec -> {
spec.executable("docker");
spec.args("build", parameters.getDockerContext().get().getAsFile().getAbsolutePath());
if (parameters.getNoCache().get()) {
spec.args("--no-cache");
}
parameters.getTags().get().forEach(tag -> spec.args("--tag", tag));
});
try {
parameters.getMarkerFile().getAsFile().get().createNewFile();
} catch (IOException e) {
throw new RuntimeException("Failed to create marker file", e);
}
}
}
interface Parameters extends WorkParameters {
DirectoryProperty getDockerContext();
RegularFileProperty getMarkerFile();
ListProperty getTags();
Property getPull();
Property getNoCache();
Property getBaseImages();
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy