# HG changeset patch # User cin # Date 2021-10-04 21:11:55 # Node ID 00ef236c472b0f7b5d6bf60715310f664084b4b1 # Parent 84a4389d01e9e66edad8c439ff9b0965c60d1f4a Reworked ImageName, added imageName property to the project extension, added TagImage task. diff --git a/container/build.gradle b/container/build.gradle --- a/container/build.gradle +++ b/container/build.gradle @@ -1,6 +1,6 @@ plugins { id "java-gradle-plugin" - id "com.gradle.plugin-publish" version "0.15.0" + id "com.gradle.plugin-publish" version "0.16.0" } @@ -9,12 +9,11 @@ repositories { } gradlePlugin { - website = 'https://code.implab.org/implab/gradle-container-plugin' - vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin' - plugins { containerPlugin { id = 'org.implab.gradle-container' + displayName = "Container building plugin" + description = 'Build and publish container images with docker or podman. Simple wrapper around cli.' implementationClass = 'org.implab.gradle.containers.ContainerPlugin' } } @@ -25,10 +24,4 @@ pluginBundle { vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin' tags = ['containers', 'image', 'docker', 'podman'] - - plugins { - containerPlugin { - description = 'Build and publish container images with docker or podman' - } - } } diff --git a/container/gradle.properties b/container/gradle.properties --- a/container/gradle.properties +++ b/container/gradle.properties @@ -1,2 +1,2 @@ group=org.implab.gradle -version=1.0 \ No newline at end of file +version=1.1 \ No newline at end of file diff --git a/container/src/main/java/org/implab/gradle/containers/ContainerExtension.java b/container/src/main/java/org/implab/gradle/containers/ContainerExtension.java --- a/container/src/main/java/org/implab/gradle/containers/ContainerExtension.java +++ b/container/src/main/java/org/implab/gradle/containers/ContainerExtension.java @@ -1,10 +1,14 @@ package org.implab.gradle.containers; +import java.util.Optional; + +import org.gradle.api.Project; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.ProjectLayout; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.Property; +import org.gradle.api.provider.Provider; public class ContainerExtension { @@ -14,11 +18,17 @@ public class ContainerExtension { private final Property imageGroup; + private final Property imageShortName; + + private final Property imageTag; + + private final Property imageName; + private final DirectoryProperty contextDir; private final RegularFileProperty imageIdFile; - public ContainerExtension(ObjectFactory factory, ProjectLayout layout) { + public ContainerExtension(ObjectFactory factory, ProjectLayout layout, Project project) { contextDir = factory.directoryProperty(); contextDir.convention(layout.getBuildDirectory().dir("context")); @@ -30,6 +40,19 @@ public class ContainerExtension { imageAuthority = factory.property(String.class); imageGroup = factory.property(String.class); + imageShortName = factory.property(String.class); + + imageShortName.convention(project.getName()); + + imageTag = factory.property(String.class); + imageTag.set(project + .provider(() -> Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest"))); + + Provider imageRepository = imageGroup.map(g -> g + "/" + imageShortName.get()).orElse(imageShortName); + + imageName = factory.property(ImageName.class); + imageName.convention(project.provider( + () -> new ImageName().authority(imageAuthority.get()).name(imageRepository.get()).tag(imageTag.get()))); } public Property getCliCmd() { @@ -55,4 +78,17 @@ public class ContainerExtension { public Property getImageGroup() { return imageGroup; } + + public Property getImageName() { + return imageName; + } + + public Property getImageShortName() { + return imageShortName; + } + + public ImageName createImageName() { + return new ImageName(); + } + } \ No newline at end of file diff --git a/container/src/main/java/org/implab/gradle/containers/ContainerPlugin.java b/container/src/main/java/org/implab/gradle/containers/ContainerPlugin.java --- a/container/src/main/java/org/implab/gradle/containers/ContainerPlugin.java +++ b/container/src/main/java/org/implab/gradle/containers/ContainerPlugin.java @@ -1,20 +1,18 @@ package org.implab.gradle.containers; -import java.util.Optional; - import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.Dependency; import org.gradle.api.file.ProjectLayout; import org.gradle.api.model.ObjectFactory; import org.gradle.api.plugins.ExtraPropertiesExtension; -import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Copy; import org.gradle.api.tasks.Delete; import org.gradle.api.tasks.TaskProvider; import org.implab.gradle.containers.tasks.BuildImage; import org.implab.gradle.containers.tasks.PushImage; import org.implab.gradle.containers.tasks.SaveImage; +import org.implab.gradle.containers.tasks.TagImage; public class ContainerPlugin implements Plugin { @@ -29,7 +27,7 @@ public class ContainerPlugin implements public void apply(Project project) { ObjectFactory factory = project.getObjects(); ProjectLayout layout = project.getLayout(); - containerExtension = new ContainerExtension(factory, layout); + containerExtension = new ContainerExtension(factory, layout, project); containerExtension.getImageAuthority() .convention(project.provider(() -> (String) project.getProperties().get("imagesAuthority"))); @@ -43,6 +41,7 @@ public class ContainerPlugin implements extras.set(BuildImage.class.getSimpleName(), BuildImage.class); extras.set(PushImage.class.getSimpleName(), PushImage.class); extras.set(SaveImage.class.getSimpleName(), SaveImage.class); + extras.set(TagImage.class.getSimpleName(), TagImage.class); project.getConfigurations().create(Dependency.DEFAULT_CONFIGURATION, c -> { c.setCanBeConsumed(true); @@ -67,13 +66,7 @@ public class ContainerPlugin implements t.getContextDirectory().set(containerExtension.getContextDirectory()); t.getImageIdFile().set(containerExtension.getImageIdFile()); - Provider imageName = containerExtension.getImageGroup().map(g -> g + "/" + project.getName()) - .orElse(project.getName()); - - t.getImageAuthority().set(containerExtension.getImageAuthority()); - t.getImageQName().convention(imageName); - t.getImageVersion() - .convention(Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest")); + t.getImageName().set(containerExtension.getImageName()); }); project.getTasks().register("clean", Delete.class, t -> { @@ -87,12 +80,12 @@ public class ContainerPlugin implements project.getTasks().register("pushImage", PushImage.class, t -> { t.dependsOn(buildImageTask); - t.getSrcImage().set(buildImageTask.flatMap(b -> b.getImageTag())); + t.getImageName().set(buildImageTask.flatMap(b -> b.getImageName())); }); project.getTasks().register("saveImage", SaveImage.class, t -> { t.dependsOn(buildImageTask); - t.getImage().set(buildImageTask.flatMap(b -> b.getImageTag())); + t.getImage().set(buildImageTask.flatMap(b -> b.getImageName())); }); project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask.flatMap(x -> x.getImageIdFile()), t -> { diff --git a/container/src/main/java/org/implab/gradle/containers/ImageName.java b/container/src/main/java/org/implab/gradle/containers/ImageName.java new file mode 100644 --- /dev/null +++ b/container/src/main/java/org/implab/gradle/containers/ImageName.java @@ -0,0 +1,66 @@ +package org.implab.gradle.containers; + +import java.io.Serializable; +import java.util.Optional; + +public class ImageName implements Serializable { + + private static final long serialVersionUID = -1990105923537254552L; + + final String authority; + + final String name; + + final String tag; + + public ImageName() { + name = null; + authority = null; + tag = null; + } + + private ImageName(String authority, String name, String tag) { + this.authority = authority; + this.name = name; + this.tag = tag; + } + + public String getAuthority() { + return authority; + } + + public ImageName authority(String authority) { + return new ImageName(authority, name, tag); + } + + public String getName() { + return name; + } + + public ImageName name(String name) { + return new ImageName(authority, name, tag); + } + + public String getTag() { + return tag; + } + + public ImageName tag(String tag) { + return new ImageName(authority, name, tag); + } + + public ImageName copy() { + return new ImageName(authority, name, tag); + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder(); + + Optional.ofNullable(authority).ifPresent(s -> sb.append(s).append("/")); + Optional.ofNullable(name).ifPresent(s -> sb.append(s)); + Optional.ofNullable(tag).ifPresent(s-> sb.append(":").append(s)); + + return sb.toString(); + } +} diff --git a/container/src/main/java/org/implab/gradle/containers/ImageTag.java b/container/src/main/java/org/implab/gradle/containers/ImageTag.java deleted file mode 100644 --- a/container/src/main/java/org/implab/gradle/containers/ImageTag.java +++ /dev/null @@ -1,74 +0,0 @@ -package org.implab.gradle.containers; - -import java.io.Serializable; -import java.util.Optional; - -public class ImageTag implements Serializable { - - private static final long serialVersionUID = -1990105923537254552L; - - String authority; - - String qName; - - String version; - - public ImageTag() { - } - - public ImageTag(ImageTag base) { - authority = base.authority; - qName = base.qName; - version = base.version; - } - - public String getAuthority() { - return authority; - } - - public void setAuthority(String authority) { - this.authority = authority; - } - - public ImageTag authority(String authority) { - this.authority = authority; - return this; - } - - public String getQName() { - return qName; - } - - public void setQName(String qName) { - this.qName = qName; - } - - public ImageTag qName(String qName) { - this.qName = qName; - return this; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public ImageTag version(String version) { - this.version = version; - return this; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - - Optional.ofNullable(authority).ifPresent(s -> sb.append(s).append("/")); - Optional.ofNullable(qName).ifPresent(s -> sb.append(s)); - Optional.ofNullable(version).ifPresent(s-> sb.append(":").append(s)); - - return sb.toString(); - } -} diff --git a/container/src/main/java/org/implab/gradle/containers/tasks/BuildImage.java b/container/src/main/java/org/implab/gradle/containers/tasks/BuildImage.java --- a/container/src/main/java/org/implab/gradle/containers/tasks/BuildImage.java +++ b/container/src/main/java/org/implab/gradle/containers/tasks/BuildImage.java @@ -5,39 +5,20 @@ import java.util.List; import org.gradle.api.file.DirectoryProperty; import org.gradle.api.file.RegularFileProperty; import org.gradle.api.provider.Property; -import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.InputDirectory; -import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.SkipWhenEmpty; import org.implab.gradle.Utils; -import org.implab.gradle.containers.ImageTag; +import org.implab.gradle.containers.ImageName; public abstract class BuildImage extends CliTask { @InputDirectory @SkipWhenEmpty public abstract DirectoryProperty getContextDirectory(); - @Internal - public abstract Property getImageQName(); - - @Internal - public abstract Property getImageVersion(); - - @Internal - public abstract Property getImageAuthority(); - @Input - public Provider getImageTag() { - return getProject().provider(() -> { - ImageTag tag = new ImageTag(); - tag.setQName(getImageQName().getOrNull()); - tag.setAuthority(getImageAuthority().getOrNull()); - tag.setVersion(getImageVersion().getOrNull()); - return tag; - }); - } + public abstract Property getImageName(); @OutputFile public abstract RegularFileProperty getImageIdFile(); @@ -52,7 +33,7 @@ public abstract class BuildImage extends super.preparingCommand(commandLine); commandLine.addAll(List.of("build", ".", "-q", "-t")); - commandLine.add(getImageTag().get().toString()); + commandLine.add(getImageName().get().toString()); } @Override diff --git a/container/src/main/java/org/implab/gradle/containers/tasks/PushImage.java b/container/src/main/java/org/implab/gradle/containers/tasks/PushImage.java --- a/container/src/main/java/org/implab/gradle/containers/tasks/PushImage.java +++ b/container/src/main/java/org/implab/gradle/containers/tasks/PushImage.java @@ -5,20 +5,14 @@ import java.util.concurrent.Callable; import org.gradle.api.provider.ListProperty; import org.gradle.api.provider.Property; -import org.gradle.api.provider.Provider; import org.gradle.api.tasks.Input; -import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.Optional; -import org.implab.gradle.containers.ImageTag; +import org.implab.gradle.containers.ImageName; public abstract class PushImage extends CliTask { @Input - public abstract Property getSrcImage(); - - @Input - @Optional - public abstract Property getDestImage(); + public abstract Property getImageName(); @Input @Optional @@ -33,19 +27,12 @@ public abstract class PushImage extends return this; } - @Internal - public Provider getDestination() { - return getDestImage().flatMap(tag -> getTransport().orElse("").map(t -> t + tag.toString())); - } - @Override protected void preparingCommand(List commandLine) { super.preparingCommand(commandLine); commandLine.add("push"); commandLine.addAll(getOptions().get()); - commandLine.add(getSrcImage().get().toString()); - if (getDestination().isPresent()) - commandLine.add(getDestination().get()); + commandLine.add(getImageName().get().toString()); } } diff --git a/container/src/main/java/org/implab/gradle/containers/tasks/SaveImage.java b/container/src/main/java/org/implab/gradle/containers/tasks/SaveImage.java --- a/container/src/main/java/org/implab/gradle/containers/tasks/SaveImage.java +++ b/container/src/main/java/org/implab/gradle/containers/tasks/SaveImage.java @@ -13,12 +13,12 @@ import org.gradle.api.tasks.Internal; import org.gradle.api.tasks.OutputFile; import org.gradle.api.tasks.TaskExecutionException; import org.implab.gradle.Utils; -import org.implab.gradle.containers.ImageTag; +import org.implab.gradle.containers.ImageName; public abstract class SaveImage extends CliTask { @Input - public abstract Property getImage(); + public abstract Property getImage(); @OutputFile public Provider getArchiveFile() { diff --git a/container/src/main/java/org/implab/gradle/containers/tasks/TagImage.java b/container/src/main/java/org/implab/gradle/containers/tasks/TagImage.java new file mode 100644 --- /dev/null +++ b/container/src/main/java/org/implab/gradle/containers/tasks/TagImage.java @@ -0,0 +1,42 @@ +package org.implab.gradle.containers.tasks; + +import java.util.List; +import java.util.concurrent.Callable; + +import org.gradle.api.provider.ListProperty; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Input; +import org.gradle.api.tasks.Optional; +import org.implab.gradle.containers.ImageName; + +public abstract class TagImage extends CliTask { + + @Input + public abstract Property getSrcImage(); + + @Input + public abstract Property getDestImage(); + + @Input + @Optional + public abstract Property getTransport(); + + @Input + @Optional + public abstract ListProperty getOptions(); + + public TagImage option(Callable provider) { + getOptions().add(getProject().provider(provider)); + return this; + } + + @Override + protected void preparingCommand(List commandLine) { + super.preparingCommand(commandLine); + + commandLine.add("tag"); + commandLine.addAll(getOptions().get()); + commandLine.add(getSrcImage().get().toString()); + commandLine.add(getDestImage().get().toString()); + } +} diff --git a/readme.md b/readme.md --- a/readme.md +++ b/readme.md @@ -5,7 +5,7 @@ ```gradle plugins { - id 'org.implab.gradle-container' version "1.0" + id 'org.implab.gradle-container' version '1.1' } container { @@ -81,3 +81,30 @@ The task pushes the image to the remote The copy task, it prepares the build context. Use it to customize the build context. + +### tagImage + +since: 1.1 + +```gradle +task tagLatest(type: TagImage) { + srcImage = container.imageName + destImage = container.imageName.map { it.tag("latest") } +} + +``` + +## Changes + +### 1.1 + +Warning! This version isn't fully backward compatible with 1.0 version. + +* Added `TagImage` task type +* `ImageTag` class is replaced with `ImageName` class +* `BuildImage`, `PushImage` tasks are now accepting only `imageName` property +* Added `imageName`, `imageShortName`, `imageTag` properties to `container` extension + +### 1.0 + +Initial release. Default tasks to build and publish container images.