##// END OF EJS Templates
Reworked ImageName, added imageName property to the project extension, added TagImage task.
cin -
r4:00ef236c472b v1.1 default
parent child
Show More
@@ -0,0 +1,66
1 package org.implab.gradle.containers;
2
3 import java.io.Serializable;
4 import java.util.Optional;
5
6 public class ImageName implements Serializable {
7
8 private static final long serialVersionUID = -1990105923537254552L;
9
10 final String authority;
11
12 final String name;
13
14 final String tag;
15
16 public ImageName() {
17 name = null;
18 authority = null;
19 tag = null;
20 }
21
22 private ImageName(String authority, String name, String tag) {
23 this.authority = authority;
24 this.name = name;
25 this.tag = tag;
26 }
27
28 public String getAuthority() {
29 return authority;
30 }
31
32 public ImageName authority(String authority) {
33 return new ImageName(authority, name, tag);
34 }
35
36 public String getName() {
37 return name;
38 }
39
40 public ImageName name(String name) {
41 return new ImageName(authority, name, tag);
42 }
43
44 public String getTag() {
45 return tag;
46 }
47
48 public ImageName tag(String tag) {
49 return new ImageName(authority, name, tag);
50 }
51
52 public ImageName copy() {
53 return new ImageName(authority, name, tag);
54 }
55
56 @Override
57 public String toString() {
58 StringBuilder sb = new StringBuilder();
59
60 Optional.ofNullable(authority).ifPresent(s -> sb.append(s).append("/"));
61 Optional.ofNullable(name).ifPresent(s -> sb.append(s));
62 Optional.ofNullable(tag).ifPresent(s-> sb.append(":").append(s));
63
64 return sb.toString();
65 }
66 }
@@ -0,0 +1,42
1 package org.implab.gradle.containers.tasks;
2
3 import java.util.List;
4 import java.util.concurrent.Callable;
5
6 import org.gradle.api.provider.ListProperty;
7 import org.gradle.api.provider.Property;
8 import org.gradle.api.tasks.Input;
9 import org.gradle.api.tasks.Optional;
10 import org.implab.gradle.containers.ImageName;
11
12 public abstract class TagImage extends CliTask {
13
14 @Input
15 public abstract Property<ImageName> getSrcImage();
16
17 @Input
18 public abstract Property<ImageName> getDestImage();
19
20 @Input
21 @Optional
22 public abstract Property<String> getTransport();
23
24 @Input
25 @Optional
26 public abstract ListProperty<String> getOptions();
27
28 public TagImage option(Callable<String> provider) {
29 getOptions().add(getProject().provider(provider));
30 return this;
31 }
32
33 @Override
34 protected void preparingCommand(List<String> commandLine) {
35 super.preparingCommand(commandLine);
36
37 commandLine.add("tag");
38 commandLine.addAll(getOptions().get());
39 commandLine.add(getSrcImage().get().toString());
40 commandLine.add(getDestImage().get().toString());
41 }
42 }
@@ -1,34 +1,27
1 plugins {
1 plugins {
2 id "java-gradle-plugin"
2 id "java-gradle-plugin"
3 id "com.gradle.plugin-publish" version "0.15.0"
3 id "com.gradle.plugin-publish" version "0.16.0"
4 }
4 }
5
5
6
6
7 repositories {
7 repositories {
8 mavenCentral()
8 mavenCentral()
9 }
9 }
10
10
11 gradlePlugin {
11 gradlePlugin {
12 website = 'https://code.implab.org/implab/gradle-container-plugin'
13 vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin'
14
15 plugins {
12 plugins {
16 containerPlugin {
13 containerPlugin {
17 id = 'org.implab.gradle-container'
14 id = 'org.implab.gradle-container'
15 displayName = "Container building plugin"
16 description = 'Build and publish container images with docker or podman. Simple wrapper around cli.'
18 implementationClass = 'org.implab.gradle.containers.ContainerPlugin'
17 implementationClass = 'org.implab.gradle.containers.ContainerPlugin'
19 }
18 }
20 }
19 }
21 }
20 }
22
21
23 pluginBundle {
22 pluginBundle {
24 website = 'https://code.implab.org/implab/gradle-container-plugin'
23 website = 'https://code.implab.org/implab/gradle-container-plugin'
25 vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin'
24 vcsUrl = 'https://code.implab.org/implab/gradle-container-plugin'
26
25
27 tags = ['containers', 'image', 'docker', 'podman']
26 tags = ['containers', 'image', 'docker', 'podman']
28
29 plugins {
30 containerPlugin {
31 description = 'Build and publish container images with docker or podman'
32 }
27 }
33 }
34 }
@@ -1,2 +1,2
1 group=org.implab.gradle
1 group=org.implab.gradle
2 version=1.0 No newline at end of file
2 version=1.1 No newline at end of file
@@ -1,58 +1,94
1 package org.implab.gradle.containers;
1 package org.implab.gradle.containers;
2
2
3 import java.util.Optional;
4
5 import org.gradle.api.Project;
3 import org.gradle.api.file.DirectoryProperty;
6 import org.gradle.api.file.DirectoryProperty;
4 import org.gradle.api.file.ProjectLayout;
7 import org.gradle.api.file.ProjectLayout;
5 import org.gradle.api.file.RegularFileProperty;
8 import org.gradle.api.file.RegularFileProperty;
6 import org.gradle.api.model.ObjectFactory;
9 import org.gradle.api.model.ObjectFactory;
7 import org.gradle.api.provider.Property;
10 import org.gradle.api.provider.Property;
11 import org.gradle.api.provider.Provider;
8
12
9 public class ContainerExtension {
13 public class ContainerExtension {
10
14
11 private final Property<String> cliCmd;
15 private final Property<String> cliCmd;
12
16
13 private final Property<String> imageAuthority;
17 private final Property<String> imageAuthority;
14
18
15 private final Property<String> imageGroup;
19 private final Property<String> imageGroup;
16
20
21 private final Property<String> imageShortName;
22
23 private final Property<String> imageTag;
24
25 private final Property<ImageName> imageName;
26
17 private final DirectoryProperty contextDir;
27 private final DirectoryProperty contextDir;
18
28
19 private final RegularFileProperty imageIdFile;
29 private final RegularFileProperty imageIdFile;
20
30
21 public ContainerExtension(ObjectFactory factory, ProjectLayout layout) {
31 public ContainerExtension(ObjectFactory factory, ProjectLayout layout, Project project) {
22 contextDir = factory.directoryProperty();
32 contextDir = factory.directoryProperty();
23 contextDir.convention(layout.getBuildDirectory().dir("context"));
33 contextDir.convention(layout.getBuildDirectory().dir("context"));
24
34
25 imageIdFile = factory.fileProperty();
35 imageIdFile = factory.fileProperty();
26 imageIdFile.convention(layout.getBuildDirectory().file("imageId"));
36 imageIdFile.convention(layout.getBuildDirectory().file("imageId"));
27
37
28 cliCmd = factory.property(String.class);
38 cliCmd = factory.property(String.class);
29 cliCmd.set("docker");
39 cliCmd.set("docker");
30
40
31 imageAuthority = factory.property(String.class);
41 imageAuthority = factory.property(String.class);
32 imageGroup = factory.property(String.class);
42 imageGroup = factory.property(String.class);
43 imageShortName = factory.property(String.class);
44
45 imageShortName.convention(project.getName());
46
47 imageTag = factory.property(String.class);
48 imageTag.set(project
49 .provider(() -> Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest")));
50
51 Provider<String> imageRepository = imageGroup.map(g -> g + "/" + imageShortName.get()).orElse(imageShortName);
52
53 imageName = factory.property(ImageName.class);
54 imageName.convention(project.provider(
55 () -> new ImageName().authority(imageAuthority.get()).name(imageRepository.get()).tag(imageTag.get())));
33 }
56 }
34
57
35 public Property<String> getCliCmd() {
58 public Property<String> getCliCmd() {
36 return cliCmd;
59 return cliCmd;
37 }
60 }
38
61
39 public void setCliCmd(String cliCmd) {
62 public void setCliCmd(String cliCmd) {
40 this.cliCmd.set(cliCmd);
63 this.cliCmd.set(cliCmd);
41 }
64 }
42
65
43 public DirectoryProperty getContextDirectory() {
66 public DirectoryProperty getContextDirectory() {
44 return contextDir;
67 return contextDir;
45 }
68 }
46
69
47 public RegularFileProperty getImageIdFile() {
70 public RegularFileProperty getImageIdFile() {
48 return imageIdFile;
71 return imageIdFile;
49 }
72 }
50
73
51 public Property<String> getImageAuthority() {
74 public Property<String> getImageAuthority() {
52 return imageAuthority;
75 return imageAuthority;
53 }
76 }
54
77
55 public Property<String> getImageGroup() {
78 public Property<String> getImageGroup() {
56 return imageGroup;
79 return imageGroup;
57 }
80 }
81
82 public Property<ImageName> getImageName() {
83 return imageName;
84 }
85
86 public Property<String> getImageShortName() {
87 return imageShortName;
88 }
89
90 public ImageName createImageName() {
91 return new ImageName();
92 }
93
58 } No newline at end of file
94 }
@@ -1,102 +1,95
1 package org.implab.gradle.containers;
1 package org.implab.gradle.containers;
2
2
3 import java.util.Optional;
4
5 import org.gradle.api.Plugin;
3 import org.gradle.api.Plugin;
6 import org.gradle.api.Project;
4 import org.gradle.api.Project;
7 import org.gradle.api.artifacts.Dependency;
5 import org.gradle.api.artifacts.Dependency;
8 import org.gradle.api.file.ProjectLayout;
6 import org.gradle.api.file.ProjectLayout;
9 import org.gradle.api.model.ObjectFactory;
7 import org.gradle.api.model.ObjectFactory;
10 import org.gradle.api.plugins.ExtraPropertiesExtension;
8 import org.gradle.api.plugins.ExtraPropertiesExtension;
11 import org.gradle.api.provider.Provider;
12 import org.gradle.api.tasks.Copy;
9 import org.gradle.api.tasks.Copy;
13 import org.gradle.api.tasks.Delete;
10 import org.gradle.api.tasks.Delete;
14 import org.gradle.api.tasks.TaskProvider;
11 import org.gradle.api.tasks.TaskProvider;
15 import org.implab.gradle.containers.tasks.BuildImage;
12 import org.implab.gradle.containers.tasks.BuildImage;
16 import org.implab.gradle.containers.tasks.PushImage;
13 import org.implab.gradle.containers.tasks.PushImage;
17 import org.implab.gradle.containers.tasks.SaveImage;
14 import org.implab.gradle.containers.tasks.SaveImage;
15 import org.implab.gradle.containers.tasks.TagImage;
18
16
19 public class ContainerPlugin implements Plugin<Project> {
17 public class ContainerPlugin implements Plugin<Project> {
20
18
21 public static final String BUILD_GROUP = "build";
19 public static final String BUILD_GROUP = "build";
22
20
23 public static final String CONTAINER_EXTENSION_NAME = "container";
21 public static final String CONTAINER_EXTENSION_NAME = "container";
24
22
25 public static final String ARCHIVE_CONFIGURATION = "archive";
23 public static final String ARCHIVE_CONFIGURATION = "archive";
26
24
27 private ContainerExtension containerExtension;
25 private ContainerExtension containerExtension;
28
26
29 public void apply(Project project) {
27 public void apply(Project project) {
30 ObjectFactory factory = project.getObjects();
28 ObjectFactory factory = project.getObjects();
31 ProjectLayout layout = project.getLayout();
29 ProjectLayout layout = project.getLayout();
32 containerExtension = new ContainerExtension(factory, layout);
30 containerExtension = new ContainerExtension(factory, layout, project);
33
31
34 containerExtension.getImageAuthority()
32 containerExtension.getImageAuthority()
35 .convention(project.provider(() -> (String) project.getProperties().get("imagesAuthority")));
33 .convention(project.provider(() -> (String) project.getProperties().get("imagesAuthority")));
36
34
37 containerExtension.getImageGroup()
35 containerExtension.getImageGroup()
38 .convention(project.provider(() -> (String) project.getProperties().get("imagesGroup")));
36 .convention(project.provider(() -> (String) project.getProperties().get("imagesGroup")));
39
37
40 project.getExtensions().add(CONTAINER_EXTENSION_NAME, containerExtension);
38 project.getExtensions().add(CONTAINER_EXTENSION_NAME, containerExtension);
41
39
42 ExtraPropertiesExtension extras = project.getExtensions().getExtraProperties();
40 ExtraPropertiesExtension extras = project.getExtensions().getExtraProperties();
43 extras.set(BuildImage.class.getSimpleName(), BuildImage.class);
41 extras.set(BuildImage.class.getSimpleName(), BuildImage.class);
44 extras.set(PushImage.class.getSimpleName(), PushImage.class);
42 extras.set(PushImage.class.getSimpleName(), PushImage.class);
45 extras.set(SaveImage.class.getSimpleName(), SaveImage.class);
43 extras.set(SaveImage.class.getSimpleName(), SaveImage.class);
44 extras.set(TagImage.class.getSimpleName(), TagImage.class);
46
45
47 project.getConfigurations().create(Dependency.DEFAULT_CONFIGURATION, c -> {
46 project.getConfigurations().create(Dependency.DEFAULT_CONFIGURATION, c -> {
48 c.setCanBeConsumed(true);
47 c.setCanBeConsumed(true);
49 c.setCanBeResolved(false);
48 c.setCanBeResolved(false);
50 });
49 });
51
50
52 project.getConfigurations().create(ARCHIVE_CONFIGURATION, c -> {
51 project.getConfigurations().create(ARCHIVE_CONFIGURATION, c -> {
53 c.setCanBeConsumed(true);
52 c.setCanBeConsumed(true);
54 c.setCanBeResolved(false);
53 c.setCanBeResolved(false);
55 });
54 });
56
55
57 TaskProvider<Copy> processResourcesTask = project.getTasks().register("processResources", Copy.class, t -> {
56 TaskProvider<Copy> processResourcesTask = project.getTasks().register("processResources", Copy.class, t -> {
58 t.setGroup(BUILD_GROUP);
57 t.setGroup(BUILD_GROUP);
59 t.from(layout.getProjectDirectory().dir("src/main"));
58 t.from(layout.getProjectDirectory().dir("src/main"));
60 t.into(containerExtension.getContextDirectory());
59 t.into(containerExtension.getContextDirectory());
61 });
60 });
62
61
63 TaskProvider<BuildImage> buildImageTask = project.getTasks().register("buildImage", BuildImage.class, t -> {
62 TaskProvider<BuildImage> buildImageTask = project.getTasks().register("buildImage", BuildImage.class, t -> {
64 t.setGroup(BUILD_GROUP);
63 t.setGroup(BUILD_GROUP);
65 t.dependsOn(processResourcesTask);
64 t.dependsOn(processResourcesTask);
66
65
67 t.getContextDirectory().set(containerExtension.getContextDirectory());
66 t.getContextDirectory().set(containerExtension.getContextDirectory());
68 t.getImageIdFile().set(containerExtension.getImageIdFile());
67 t.getImageIdFile().set(containerExtension.getImageIdFile());
69
68
70 Provider<String> imageName = containerExtension.getImageGroup().map(g -> g + "/" + project.getName())
69 t.getImageName().set(containerExtension.getImageName());
71 .orElse(project.getName());
72
73 t.getImageAuthority().set(containerExtension.getImageAuthority());
74 t.getImageQName().convention(imageName);
75 t.getImageVersion()
76 .convention(Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest"));
77 });
70 });
78
71
79 project.getTasks().register("clean", Delete.class, t -> {
72 project.getTasks().register("clean", Delete.class, t -> {
80 t.delete(layout.getBuildDirectory());
73 t.delete(layout.getBuildDirectory());
81 });
74 });
82
75
83 project.getTasks().register("build", t -> {
76 project.getTasks().register("build", t -> {
84 t.setGroup(BUILD_GROUP);
77 t.setGroup(BUILD_GROUP);
85 t.dependsOn(buildImageTask);
78 t.dependsOn(buildImageTask);
86 });
79 });
87
80
88 project.getTasks().register("pushImage", PushImage.class, t -> {
81 project.getTasks().register("pushImage", PushImage.class, t -> {
89 t.dependsOn(buildImageTask);
82 t.dependsOn(buildImageTask);
90 t.getSrcImage().set(buildImageTask.flatMap(b -> b.getImageTag()));
83 t.getImageName().set(buildImageTask.flatMap(b -> b.getImageName()));
91 });
84 });
92
85
93 project.getTasks().register("saveImage", SaveImage.class, t -> {
86 project.getTasks().register("saveImage", SaveImage.class, t -> {
94 t.dependsOn(buildImageTask);
87 t.dependsOn(buildImageTask);
95 t.getImage().set(buildImageTask.flatMap(b -> b.getImageTag()));
88 t.getImage().set(buildImageTask.flatMap(b -> b.getImageName()));
96 });
89 });
97
90
98 project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask.flatMap(x -> x.getImageIdFile()), t -> {
91 project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask.flatMap(x -> x.getImageIdFile()), t -> {
99 t.builtBy(buildImageTask);
92 t.builtBy(buildImageTask);
100 });
93 });
101 }
94 }
102 }
95 }
@@ -1,62 +1,43
1 package org.implab.gradle.containers.tasks;
1 package org.implab.gradle.containers.tasks;
2
2
3 import java.util.List;
3 import java.util.List;
4
4
5 import org.gradle.api.file.DirectoryProperty;
5 import org.gradle.api.file.DirectoryProperty;
6 import org.gradle.api.file.RegularFileProperty;
6 import org.gradle.api.file.RegularFileProperty;
7 import org.gradle.api.provider.Property;
7 import org.gradle.api.provider.Property;
8 import org.gradle.api.provider.Provider;
9 import org.gradle.api.tasks.Input;
8 import org.gradle.api.tasks.Input;
10 import org.gradle.api.tasks.InputDirectory;
9 import org.gradle.api.tasks.InputDirectory;
11 import org.gradle.api.tasks.Internal;
12 import org.gradle.api.tasks.OutputFile;
10 import org.gradle.api.tasks.OutputFile;
13 import org.gradle.api.tasks.SkipWhenEmpty;
11 import org.gradle.api.tasks.SkipWhenEmpty;
14 import org.implab.gradle.Utils;
12 import org.implab.gradle.Utils;
15 import org.implab.gradle.containers.ImageTag;
13 import org.implab.gradle.containers.ImageName;
16
14
17 public abstract class BuildImage extends CliTask {
15 public abstract class BuildImage extends CliTask {
18 @InputDirectory
16 @InputDirectory
19 @SkipWhenEmpty
17 @SkipWhenEmpty
20 public abstract DirectoryProperty getContextDirectory();
18 public abstract DirectoryProperty getContextDirectory();
21
19
22 @Internal
23 public abstract Property<String> getImageQName();
24
25 @Internal
26 public abstract Property<String> getImageVersion();
27
28 @Internal
29 public abstract Property<String> getImageAuthority();
30
31 @Input
20 @Input
32 public Provider<ImageTag> getImageTag() {
21 public abstract Property<ImageName> getImageName();
33 return getProject().provider(() -> {
34 ImageTag tag = new ImageTag();
35 tag.setQName(getImageQName().getOrNull());
36 tag.setAuthority(getImageAuthority().getOrNull());
37 tag.setVersion(getImageVersion().getOrNull());
38 return tag;
39 });
40 }
41
22
42 @OutputFile
23 @OutputFile
43 public abstract RegularFileProperty getImageIdFile();
24 public abstract RegularFileProperty getImageIdFile();
44
25
45 public BuildImage() {
26 public BuildImage() {
46
27
47 setWorkingDir(getContextDirectory().getAsFile());
28 setWorkingDir(getContextDirectory().getAsFile());
48 }
29 }
49
30
50 @Override
31 @Override
51 protected void preparingCommand(List<String> commandLine) {
32 protected void preparingCommand(List<String> commandLine) {
52 super.preparingCommand(commandLine);
33 super.preparingCommand(commandLine);
53
34
54 commandLine.addAll(List.of("build", ".", "-q", "-t"));
35 commandLine.addAll(List.of("build", ".", "-q", "-t"));
55 commandLine.add(getImageTag().get().toString());
36 commandLine.add(getImageName().get().toString());
56 }
37 }
57
38
58 @Override
39 @Override
59 protected void processStarted(Process p) {
40 protected void processStarted(Process p) {
60 Utils.redirectIO(p.getInputStream(), getImageIdFile().get().getAsFile());
41 Utils.redirectIO(p.getInputStream(), getImageIdFile().get().getAsFile());
61 }
42 }
62 }
43 }
@@ -1,51 +1,38
1 package org.implab.gradle.containers.tasks;
1 package org.implab.gradle.containers.tasks;
2
2
3 import java.util.List;
3 import java.util.List;
4 import java.util.concurrent.Callable;
4 import java.util.concurrent.Callable;
5
5
6 import org.gradle.api.provider.ListProperty;
6 import org.gradle.api.provider.ListProperty;
7 import org.gradle.api.provider.Property;
7 import org.gradle.api.provider.Property;
8 import org.gradle.api.provider.Provider;
9 import org.gradle.api.tasks.Input;
8 import org.gradle.api.tasks.Input;
10 import org.gradle.api.tasks.Internal;
11 import org.gradle.api.tasks.Optional;
9 import org.gradle.api.tasks.Optional;
12 import org.implab.gradle.containers.ImageTag;
10 import org.implab.gradle.containers.ImageName;
13
11
14 public abstract class PushImage extends CliTask {
12 public abstract class PushImage extends CliTask {
15
13
16 @Input
14 @Input
17 public abstract Property<ImageTag> getSrcImage();
15 public abstract Property<ImageName> getImageName();
18
19 @Input
20 @Optional
21 public abstract Property<ImageTag> getDestImage();
22
16
23 @Input
17 @Input
24 @Optional
18 @Optional
25 public abstract Property<String> getTransport();
19 public abstract Property<String> getTransport();
26
20
27 @Input
21 @Input
28 @Optional
22 @Optional
29 public abstract ListProperty<String> getOptions();
23 public abstract ListProperty<String> getOptions();
30
24
31 public PushImage option(Callable<String> provider) {
25 public PushImage option(Callable<String> provider) {
32 getOptions().add(getProject().provider(provider));
26 getOptions().add(getProject().provider(provider));
33 return this;
27 return this;
34 }
28 }
35
29
36 @Internal
37 public Provider<String> getDestination() {
38 return getDestImage().flatMap(tag -> getTransport().orElse("").map(t -> t + tag.toString()));
39 }
40
41 @Override
30 @Override
42 protected void preparingCommand(List<String> commandLine) {
31 protected void preparingCommand(List<String> commandLine) {
43 super.preparingCommand(commandLine);
32 super.preparingCommand(commandLine);
44
33
45 commandLine.add("push");
34 commandLine.add("push");
46 commandLine.addAll(getOptions().get());
35 commandLine.addAll(getOptions().get());
47 commandLine.add(getSrcImage().get().toString());
36 commandLine.add(getImageName().get().toString());
48 if (getDestination().isPresent())
49 commandLine.add(getDestination().get());
50 }
37 }
51 }
38 }
@@ -1,91 +1,91
1 package org.implab.gradle.containers.tasks;
1 package org.implab.gradle.containers.tasks;
2
2
3 import java.util.ArrayList;
3 import java.util.ArrayList;
4 import java.util.List;
4 import java.util.List;
5 import java.util.Optional;
5 import java.util.Optional;
6
6
7 import org.gradle.api.file.DirectoryProperty;
7 import org.gradle.api.file.DirectoryProperty;
8 import org.gradle.api.file.RegularFile;
8 import org.gradle.api.file.RegularFile;
9 import org.gradle.api.provider.Property;
9 import org.gradle.api.provider.Property;
10 import org.gradle.api.provider.Provider;
10 import org.gradle.api.provider.Provider;
11 import org.gradle.api.tasks.Input;
11 import org.gradle.api.tasks.Input;
12 import org.gradle.api.tasks.Internal;
12 import org.gradle.api.tasks.Internal;
13 import org.gradle.api.tasks.OutputFile;
13 import org.gradle.api.tasks.OutputFile;
14 import org.gradle.api.tasks.TaskExecutionException;
14 import org.gradle.api.tasks.TaskExecutionException;
15 import org.implab.gradle.Utils;
15 import org.implab.gradle.Utils;
16 import org.implab.gradle.containers.ImageTag;
16 import org.implab.gradle.containers.ImageName;
17
17
18 public abstract class SaveImage extends CliTask {
18 public abstract class SaveImage extends CliTask {
19
19
20 @Input
20 @Input
21 public abstract Property<ImageTag> getImage();
21 public abstract Property<ImageName> getImage();
22
22
23 @OutputFile
23 @OutputFile
24 public Provider<RegularFile> getArchiveFile() {
24 public Provider<RegularFile> getArchiveFile() {
25 return getDestinationDirectory().file(getArchiveFileName());
25 return getDestinationDirectory().file(getArchiveFileName());
26 }
26 }
27
27
28 @Internal
28 @Internal
29 public abstract DirectoryProperty getDestinationDirectory();
29 public abstract DirectoryProperty getDestinationDirectory();
30
30
31 @Internal
31 @Internal
32 public abstract Property<String> getArchiveFileName();
32 public abstract Property<String> getArchiveFileName();
33
33
34 @Internal
34 @Internal
35 public abstract Property<String> getArchiveBaseName();
35 public abstract Property<String> getArchiveBaseName();
36
36
37 @Internal
37 @Internal
38 public abstract Property<String> getArchiveVersion();
38 public abstract Property<String> getArchiveVersion();
39
39
40 @Internal
40 @Internal
41 public abstract Property<String> getArchiveClassifier();
41 public abstract Property<String> getArchiveClassifier();
42
42
43 @Internal
43 @Internal
44 public abstract Property<String> getArchiveExtension();
44 public abstract Property<String> getArchiveExtension();
45
45
46 public SaveImage() {
46 public SaveImage() {
47 getArchiveFileName().convention(getProject().provider(this::conventionalArchiveFileName));
47 getArchiveFileName().convention(getProject().provider(this::conventionalArchiveFileName));
48 getArchiveBaseName().convention(getProject().provider(this::conventionalArchiveBaseName));
48 getArchiveBaseName().convention(getProject().provider(this::conventionalArchiveBaseName));
49 getArchiveVersion().convention(getProject().provider(() -> getProject().getVersion()).map(x -> x.toString()));
49 getArchiveVersion().convention(getProject().provider(() -> getProject().getVersion()).map(x -> x.toString()));
50 getDestinationDirectory().convention(getProject().getLayout().getBuildDirectory());
50 getDestinationDirectory().convention(getProject().getLayout().getBuildDirectory());
51 getArchiveExtension().convention("tar");
51 getArchiveExtension().convention("tar");
52 }
52 }
53
53
54 private String conventionalArchiveBaseName() {
54 private String conventionalArchiveBaseName() {
55 ArrayList<String> parts = new ArrayList<>();
55 ArrayList<String> parts = new ArrayList<>();
56 Optional.of(getProject().getGroup()).map(x -> x.toString()).ifPresent(parts::add);
56 Optional.of(getProject().getGroup()).map(x -> x.toString()).ifPresent(parts::add);
57 parts.add(getProject().getName());
57 parts.add(getProject().getName());
58 return String.join("-", parts);
58 return String.join("-", parts);
59 }
59 }
60
60
61 private String conventionalArchiveFileName() {
61 private String conventionalArchiveFileName() {
62 ArrayList<String> parts = new ArrayList<>();
62 ArrayList<String> parts = new ArrayList<>();
63
63
64 if (getArchiveBaseName().isPresent())
64 if (getArchiveBaseName().isPresent())
65 parts.add(getArchiveBaseName().get());
65 parts.add(getArchiveBaseName().get());
66
66
67 if (getArchiveVersion().isPresent())
67 if (getArchiveVersion().isPresent())
68 parts.add(getArchiveVersion().get());
68 parts.add(getArchiveVersion().get());
69
69
70 if (getArchiveClassifier().isPresent())
70 if (getArchiveClassifier().isPresent())
71 parts.add(getArchiveClassifier().get());
71 parts.add(getArchiveClassifier().get());
72
72
73 if (parts.size() == 0)
73 if (parts.size() == 0)
74 throw new TaskExecutionException(this, new Exception("The archiveFileName ism't specified"));
74 throw new TaskExecutionException(this, new Exception("The archiveFileName ism't specified"));
75
75
76 return String.join("-", parts) + "." + getArchiveExtension().get();
76 return String.join("-", parts) + "." + getArchiveExtension().get();
77 }
77 }
78
78
79 @Override
79 @Override
80 protected void preparingCommand(List<String> commandLine) {
80 protected void preparingCommand(List<String> commandLine) {
81 super.preparingCommand(commandLine);
81 super.preparingCommand(commandLine);
82
82
83 commandLine.add("save");
83 commandLine.add("save");
84 commandLine.add(getImage().get().toString());
84 commandLine.add(getImage().get().toString());
85 }
85 }
86
86
87 @Override
87 @Override
88 protected void processStarted(Process p) {
88 protected void processStarted(Process p) {
89 Utils.redirectIO(p.getInputStream(), getArchiveFile().get().getAsFile());
89 Utils.redirectIO(p.getInputStream(), getArchiveFile().get().getAsFile());
90 }
90 }
91 }
91 }
@@ -1,83 +1,110
1 # Build and publish images with docker/podman
1 # Build and publish images with docker/podman
2
2
3 ## SYNOPSIS
3 ## SYNOPSIS
4
4
5 ```gradle
5 ```gradle
6
6
7 plugins {
7 plugins {
8 id 'org.implab.gradle-container' version "1.0"
8 id 'org.implab.gradle-container' version '1.1'
9 }
9 }
10
10
11 container {
11 container {
12 // if you want to use podman
12 // if you want to use podman
13 cliCmd = "podman"
13 cliCmd = "podman"
14 }
14 }
15
15
16 configurations {
16 configurations {
17 app
17 app
18 }
18 }
19
19
20 dependencies {
20 dependencies {
21 // the application that needs to be built and packed
21 // the application that needs to be built and packed
22 app project(":server")
22 app project(":server")
23 }
23 }
24
24
25 // add custom task to copy application files
25 // add custom task to copy application files
26 // to the docker build context.
26 // to the docker build context.
27 task copyApp(type: Copy) {
27 task copyApp(type: Copy) {
28 processResources.dependsOn it
28 processResources.dependsOn it
29
29
30 into container.contextDirectory.dir("root/opt/myapp")
30 into container.contextDirectory.dir("root/opt/myapp")
31 from configurations.app
31 from configurations.app
32 }
32 }
33
33
34 task printVersion {
34 task printVersion {
35 doLast {
35 doLast {
36 println "tag: ${buildImage.imageTag.get()}"
36 println "tag: ${buildImage.imageTag.get()}"
37 println "archive: ${saveImage.archiveFileName.get()}"
37 println "archive: ${saveImage.archiveFileName.get()}"
38 }
38 }
39 }
39 }
40
40
41
41
42 ```
42 ```
43
43
44 ## Description
44 ## Description
45
45
46 This plugin is a simple wrapper around docker CLI. All the image
46 This plugin is a simple wrapper around docker CLI. All the image
47 building process is deligated to the `Dockerfile` which will run
47 building process is deligated to the `Dockerfile` which will run
48 in the prepeared build context.
48 in the prepeared build context.
49
49
50 ### Project structure
50 ### Project structure
51
51
52 * `build/`
52 * `build/`
53 * `context/` - the build context where `docker build` command will run.
53 * `context/` - the build context where `docker build` command will run.
54 * `imageid` - the file storing the id of the image has been built.
54 * `imageid` - the file storing the id of the image has been built.
55 * `image-name-1.2.3.tgz` - the exported image if `saveImage` has been executed.
55 * `image-name-1.2.3.tgz` - the exported image if `saveImage` has been executed.
56 * `src`
56 * `src`
57 * `main` - the source files which will be copied to the build context.
57 * `main` - the source files which will be copied to the build context.
58
58
59 ## Properties
59 ## Properties
60
60
61 `imagesAuthority` - the registry where the image should be published.
61 `imagesAuthority` - the registry where the image should be published.
62 for example `docker.io`
62 for example `docker.io`
63
63
64 `imagesGroup` - the path to the image in the repository.
64 `imagesGroup` - the path to the image in the repository.
65
65
66 ## Tasks
66 ## Tasks
67
67
68 ### buildImage
68 ### buildImage
69
69
70 The task builds the image. Wrapper around the `docker build` command.
70 The task builds the image. Wrapper around the `docker build` command.
71
71
72 ### saveImage
72 ### saveImage
73
73
74 The task exports image as the .tar archive.
74 The task exports image as the .tar archive.
75
75
76 ### pushImage
76 ### pushImage
77
77
78 The task pushes the image to the remote repository.
78 The task pushes the image to the remote repository.
79
79
80 ### processResources
80 ### processResources
81
81
82 The copy task, it prepares the build context. Use it to customize
82 The copy task, it prepares the build context. Use it to customize
83 the build context.
83 the build context.
84
85 ### tagImage
86
87 since: 1.1
88
89 ```gradle
90 task tagLatest(type: TagImage) {
91 srcImage = container.imageName
92 destImage = container.imageName.map { it.tag("latest") }
93 }
94
95 ```
96
97 ## Changes
98
99 ### 1.1
100
101 Warning! This version isn't fully backward compatible with 1.0 version.
102
103 * Added `TagImage` task type
104 * `ImageTag` class is replaced with `ImageName` class
105 * `BuildImage`, `PushImage` tasks are now accepting only `imageName` property
106 * Added `imageName`, `imageShortName`, `imageTag` properties to `container` extension
107
108 ### 1.0
109
110 Initial release. Default tasks to build and publish container images.
1 NO CONTENT: file was removed
NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now