@@ -38,6 +38,14 gradlePlugin { | |||||
38 | implementationClass = 'org.implab.gradle.containers.ContainerBasePlugin' |
|
38 | implementationClass = 'org.implab.gradle.containers.ContainerBasePlugin' | |
39 | tags.set(['containers', 'image', 'docker', 'podman']) |
|
39 | tags.set(['containers', 'image', 'docker', 'podman']) | |
40 | } |
|
40 | } | |
|
41 | ||||
|
42 | conmposePlugin { | |||
|
43 | id = 'org.implab.gradle-container-compose' | |||
|
44 | displayName = "Provdes tasks to start and stop compose" | |||
|
45 | description = 'Build and publish container images with docker or podman. Simple wrapper around cli.' | |||
|
46 | implementationClass = 'org.implab.gradle.containers.ComposePlugin' | |||
|
47 | tags.set(['containers', 'image', 'docker', 'podman']) | |||
|
48 | } | |||
41 | } |
|
49 | } | |
42 | } |
|
50 | } | |
43 |
|
51 |
@@ -12,7 +12,7 import org.implab.gradle.containers.task | |||||
12 |
public class ContainerBasePlugin implements Plugin<Project> |
|
12 | public class ContainerBasePlugin implements Plugin<Project> { | |
13 | public static final String CONTAINER_EXTENSION_NAME = "container"; |
|
13 | public static final String CONTAINER_EXTENSION_NAME = "container"; | |
14 |
|
14 | |||
15 | ContainerExtension containerExtension; |
|
15 | private ContainerExtension containerExtension; | |
16 |
|
16 | |||
17 | ContainerExtension getContainerExtension() { |
|
17 | ContainerExtension getContainerExtension() { | |
18 | if (containerExtension == null) |
|
18 | if (containerExtension == null) | |
@@ -37,13 +37,17 public class ContainerBasePlugin impleme | |||||
37 | containerExtension.getImageGroup() |
|
37 | containerExtension.getImageGroup() | |
38 | .convention(project.provider(() -> (String) project.getProperties().get("imagesGroup"))); |
|
38 | .convention(project.provider(() -> (String) project.getProperties().get("imagesGroup"))); | |
39 |
|
39 | |||
|
40 | containerExtension.getCliCmd() | |||
|
41 | .convention(project | |||
|
42 | .provider(() -> (String) project.getProperties().get("containerCli")) | |||
|
43 | .orElse("docker")); | |||
|
44 | ||||
40 | project.getExtensions().add(CONTAINER_EXTENSION_NAME, containerExtension); |
|
45 | project.getExtensions().add(CONTAINER_EXTENSION_NAME, containerExtension); | |
41 |
|
46 | |||
42 | exportClasses( |
|
47 | exportClasses( | |
43 | project, |
|
48 | project, | |
44 | BuildImage.class, PushImage.class, SaveImage.class, TagImage.class, RunImage.class); |
|
49 | BuildImage.class, PushImage.class, SaveImage.class, TagImage.class, RunImage.class); | |
45 |
|
50 | |||
46 |
|
||||
47 | } |
|
51 | } | |
48 |
|
52 | |||
49 | } |
|
53 | } |
@@ -10,21 +10,18 import javax.inject.Inject; | |||||
10 | import org.gradle.api.Project; |
|
10 | import org.gradle.api.Project; | |
11 | import org.gradle.api.file.DirectoryProperty; |
|
11 | import org.gradle.api.file.DirectoryProperty; | |
12 | import org.gradle.api.file.ProjectLayout; |
|
12 | import org.gradle.api.file.ProjectLayout; | |
13 | import org.gradle.api.file.RegularFileProperty; |
|
|||
14 | import org.gradle.api.provider.Property; |
|
13 | import org.gradle.api.provider.Property; | |
15 | import org.gradle.api.provider.Provider; |
|
14 | import org.gradle.api.provider.Provider; | |
16 | import org.implab.gradle.containers.cli.ImageName; |
|
15 | import org.implab.gradle.containers.cli.ImageName; | |
17 | import org.implab.gradle.containers.cli.ImageRef; |
|
16 | import org.implab.gradle.containers.cli.ImageRef; | |
18 | import org.implab.gradle.containers.cli.Utils; |
|
17 | import org.implab.gradle.containers.cli.Utils; | |
19 |
|
18 | |||
20 | public abstract class ContainerExtension { |
|
19 | public abstract class ContainerExtension implements PropertiesMixin { | |
21 |
|
20 | |||
22 | public abstract Property<String> getCliCmd(); |
|
21 | public abstract Property<String> getCliCmd(); | |
23 |
|
22 | |||
24 | public abstract DirectoryProperty getContextDirectory(); |
|
23 | public abstract DirectoryProperty getContextDirectory(); | |
25 |
|
24 | |||
26 | public abstract RegularFileProperty getImageIdFile(); |
|
|||
27 |
|
||||
28 | /** |
|
25 | /** | |
29 | * Specifies the name of the registry where the image is located |
|
26 | * Specifies the name of the registry where the image is located | |
30 | * {@code registry.my-company.org} |
|
27 | * {@code registry.my-company.org} | |
@@ -36,7 +33,9 public abstract class ContainerExtension | |||||
36 | */ |
|
33 | */ | |
37 | public abstract Property<String> getImageGroup(); |
|
34 | public abstract Property<String> getImageGroup(); | |
38 |
|
35 | |||
39 |
public |
|
36 | public Provider<ImageName> getImageName() { | |
|
37 | return provider(this::createImageName); | |||
|
38 | } | |||
40 |
|
39 | |||
41 | /** |
|
40 | /** | |
42 | * Specifies local image part like {@code httpd} |
|
41 | * Specifies local image part like {@code httpd} | |
@@ -57,25 +56,19 public abstract class ContainerExtension | |||||
57 | public ContainerExtension(ProjectLayout layout, Project project) { |
|
56 | public ContainerExtension(ProjectLayout layout, Project project) { | |
58 | getContextDirectory().convention(layout.getBuildDirectory().dir("context")); |
|
57 | getContextDirectory().convention(layout.getBuildDirectory().dir("context")); | |
59 |
|
58 | |||
60 | getImageIdFile().convention(layout.getBuildDirectory().file("iid.json")); |
|
|||
61 |
|
||||
62 | getCliCmd().set("docker"); |
|
|||
63 |
|
||||
64 | getImageLocalName().convention(project.getName()); |
|
59 | getImageLocalName().convention(project.getName()); | |
65 |
|
60 | |||
66 | getImageTag().set(project |
|
61 | getImageTag().set(provider(() -> Optional.ofNullable(project.getVersion()) | |
67 | .provider(() -> Optional.ofNullable(project.getVersion()).map(v -> v.toString()).orElse("latest"))); |
|
62 | .map(Object::toString) | |
68 |
|
63 | .orElse("latest"))); | ||
69 | Provider<String> imageRepository = getImageGroup().map(g -> g + "/" + getImageLocalName().get()) |
|
|||
70 | .orElse(getImageLocalName()); |
|
|||
71 |
|
||||
72 | getImageName().convention(project.provider( |
|
|||
73 | () -> new ImageName().authority(getImageAuthority().get()).name(imageRepository.get()) |
|
|||
74 | .tag(getImageTag().get()))); |
|
|||
75 | } |
|
64 | } | |
76 |
|
65 | |||
77 |
|
|
66 | ImageName createImageName() { | |
78 |
return new ImageName( |
|
67 | return new ImageName( | |
|
68 | getImageAuthority().getOrNull(), | |||
|
69 | getImageGroup().getOrNull(), | |||
|
70 | getImageLocalName().get(), | |||
|
71 | getImageTag().getOrNull()); | |||
79 | } |
|
72 | } | |
80 |
|
73 | |||
81 | public ImageRef readImageRef(File file) throws FileNotFoundException, IOException { |
|
74 | public ImageRef readImageRef(File file) throws FileNotFoundException, IOException { |
@@ -19,8 +19,6 public class ContainerPlugin implements | |||||
19 |
|
19 | |||
20 | public static final String ARCHIVE_CONFIGURATION = "archive"; |
|
20 | public static final String ARCHIVE_CONFIGURATION = "archive"; | |
21 |
|
21 | |||
22 | ContainerExtension containerExtension; |
|
|||
23 |
|
||||
24 | public void apply(Project project) { |
|
22 | public void apply(Project project) { | |
25 | ProjectLayout layout = project.getLayout(); |
|
23 | ProjectLayout layout = project.getLayout(); | |
26 |
|
24 | |||
@@ -53,9 +51,9 public class ContainerPlugin implements | |||||
53 | t.dependsOn(processResourcesTask); |
|
51 | t.dependsOn(processResourcesTask); | |
54 |
|
52 | |||
55 | t.getContextDirectory().set(containerExtension.getContextDirectory()); |
|
53 | t.getContextDirectory().set(containerExtension.getContextDirectory()); | |
56 |
t.getImageIdFile().set( |
|
54 | t.getImageIdFile().set(project.getLayout().getBuildDirectory().file("iid.json")); | |
57 |
|
55 | |||
58 | t.getImageName().set(containerExtension.getImageName()); |
|
56 | t.getImageName().set(containerExtension.getImageName().map(ImageName::toString)); | |
59 | }); |
|
57 | }); | |
60 |
|
58 | |||
61 | project.getTasks().register("clean", Delete.class, t -> { |
|
59 | project.getTasks().register("clean", Delete.class, t -> { | |
@@ -74,7 +72,7 public class ContainerPlugin implements | |||||
74 |
|
72 | |||
75 | project.getTasks().register("saveImage", SaveImage.class, t -> { |
|
73 | project.getTasks().register("saveImage", SaveImage.class, t -> { | |
76 | t.dependsOn(buildImageTask); |
|
74 | t.dependsOn(buildImageTask); | |
77 |
t.getExportImages().add(buildImageTask.flatMap(BuildImage::getImageName) |
|
75 | t.getExportImages().add(buildImageTask.flatMap(BuildImage::getImageName)); | |
78 | }); |
|
76 | }); | |
79 |
|
77 | |||
80 | project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask); |
|
78 | project.getArtifacts().add(Dependency.DEFAULT_CONFIGURATION, buildImageTask); |
@@ -2,7 +2,6 package org.implab.gradle.containers.cli | |||||
2 |
|
2 | |||
3 | import java.io.File; |
|
3 | import java.io.File; | |
4 | import java.io.IOException; |
|
4 | import java.io.IOException; | |
5 | import java.nio.file.Files; |
|
|||
6 | import java.util.ArrayList; |
|
5 | import java.util.ArrayList; | |
7 | import java.util.Arrays; |
|
6 | import java.util.Arrays; | |
8 | import java.util.List; |
|
7 | import java.util.List; |
@@ -1,6 +1,7 | |||||
1 | package org.implab.gradle.containers.cli; |
|
1 | package org.implab.gradle.containers.cli; | |
2 |
|
2 | |||
3 | import java.io.Serializable; |
|
3 | import java.io.Serializable; | |
|
4 | import java.util.ArrayList; | |||
4 | import java.util.Optional; |
|
5 | import java.util.Optional; | |
5 |
|
6 | |||
6 | import com.fasterxml.jackson.annotation.JsonCreator; |
|
7 | import com.fasterxml.jackson.annotation.JsonCreator; | |
@@ -12,60 +13,71 public class ImageName implements Serial | |||||
12 |
|
13 | |||
13 | final String authority; |
|
14 | final String authority; | |
14 |
|
15 | |||
15 |
final String |
|
16 | final String groupName; | |
|
17 | ||||
|
18 | final String localName; | |||
16 |
|
19 | |||
17 | final String tag; |
|
20 | final String tag; | |
18 |
|
21 | |||
19 | public ImageName() { |
|
22 | @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) | |
20 | name = null; |
|
23 | public ImageName( | |
21 | authority = null; |
|
24 | @JsonProperty("authority") String authority, | |
22 | tag = null; |
|
25 | @JsonProperty("groupName") String groupName, | |
23 | } |
|
26 | @JsonProperty("localName") String localName, | |
|
27 | @JsonProperty("tag") String tag) { | |||
|
28 | if (localName == null || localName.isBlank()) | |||
|
29 | throw new IllegalArgumentException("localName can't be null or blank string"); | |||
24 |
|
30 | |||
25 | @JsonCreator(mode = JsonCreator.Mode.PROPERTIES) |
|
|||
26 | private ImageName(@JsonProperty("authority") String authority, @JsonProperty("name") String name, |
|
|||
27 | @JsonProperty("tag") String tag) { |
|
|||
28 | this.authority = authority; |
|
31 | this.authority = authority; | |
29 |
this. |
|
32 | this.groupName = groupName; | |
|
33 | this.localName = localName; | |||
30 | this.tag = tag; |
|
34 | this.tag = tag; | |
31 | } |
|
35 | } | |
32 |
|
36 | |||
33 | public String getAuthority() { |
|
37 | public Optional<String> getAuthority() { | |
34 | return authority; |
|
38 | return Optional.ofNullable(authority); | |
35 | } |
|
39 | } | |
36 |
|
40 | |||
37 |
public ImageName |
|
41 | public ImageName withAuthority(String authority) { | |
38 |
return new ImageName(authority, |
|
42 | return new ImageName(authority, groupName, localName, tag); | |
39 | } |
|
43 | } | |
40 |
|
44 | |||
41 | public String getName() { |
|
45 | public Optional<String> getGroupName() { | |
42 | return name; |
|
46 | return Optional.ofNullable(groupName); | |
|
47 | } | |||
|
48 | ||||
|
49 | public ImageName withGroupName(String groupName) { | |||
|
50 | return new ImageName(authority, groupName, localName, tag); | |||
43 | } |
|
51 | } | |
44 |
|
52 | |||
45 |
public |
|
53 | public String getLocalName() { | |
46 | return new ImageName(authority, name, tag); |
|
54 | return localName; | |
47 | } |
|
55 | } | |
48 |
|
56 | |||
49 | public String getTag() { |
|
57 | public ImageName withLocalName(String localName) { | |
50 | return tag; |
|
58 | if (localName == null || localName.isBlank()) | |
|
59 | throw new IllegalArgumentException("localName can't be null or blank string"); | |||
|
60 | return new ImageName(authority, groupName, localName, tag); | |||
51 | } |
|
61 | } | |
52 |
|
62 | |||
53 |
public |
|
63 | public Optional<String> getTag() { | |
54 | return new ImageName(authority, name, tag); |
|
64 | return Optional.ofNullable(tag); | |
55 | } |
|
65 | } | |
56 |
|
66 | |||
57 |
public ImageName |
|
67 | public ImageName withTag(String tag) { | |
58 |
return new ImageName(authority, |
|
68 | return new ImageName(authority, groupName, localName, tag); | |
59 | } |
|
69 | } | |
60 |
|
70 | |||
61 | @Override |
|
71 | @Override | |
62 | public String toString() { |
|
72 | public String toString() { | |
63 | StringBuilder sb = new StringBuilder(); |
|
73 | var path = new ArrayList<String>(); | |
64 |
|
74 | |||
65 | Optional.ofNullable(authority).ifPresent(s -> sb.append(s).append("/")); |
|
75 | getAuthority().ifPresent(path::add); | |
66 | Optional.ofNullable(name).ifPresent(s -> sb.append(s)); |
|
76 | getGroupName().ifPresent(path::add); | |
67 | Optional.ofNullable(tag).ifPresent(s -> sb.append(":").append(s)); |
|
77 | path.add(getLocalName()); | |
68 |
|
78 | |||
69 | return sb.toString(); |
|
79 | var repo = String.join("/", path); | |
|
80 | ||||
|
81 | return getTag().map(tag -> String.join(":", repo, tag)).orElse(repo); | |||
70 | } |
|
82 | } | |
71 | } |
|
83 | } |
@@ -22,7 +22,6 import org.gradle.api.tasks.SkipWhenEmpt | |||||
22 | import org.gradle.api.tasks.TaskAction; |
|
22 | import org.gradle.api.tasks.TaskAction; | |
23 | import java.io.File; |
|
23 | import java.io.File; | |
24 |
|
24 | |||
25 | import org.implab.gradle.containers.cli.ImageName; |
|
|||
26 | import org.implab.gradle.containers.cli.ImageRef; |
|
25 | import org.implab.gradle.containers.cli.ImageRef; | |
27 | import org.implab.gradle.containers.cli.Utils; |
|
26 | import org.implab.gradle.containers.cli.Utils; | |
28 | import org.implab.gradle.containers.dsl.MapPropertyEntry; |
|
27 | import org.implab.gradle.containers.dsl.MapPropertyEntry; | |
@@ -31,6 +30,7 import org.implab.gradle.containers.dsl. | |||||
31 | import groovy.lang.Closure; |
|
30 | import groovy.lang.Closure; | |
32 |
|
31 | |||
33 | public abstract class BuildImage extends DockerCliTask implements OptionsMixin { |
|
32 | public abstract class BuildImage extends DockerCliTask implements OptionsMixin { | |
|
33 | ||||
34 | @InputDirectory |
|
34 | @InputDirectory | |
35 | @SkipWhenEmpty |
|
35 | @SkipWhenEmpty | |
36 | public abstract DirectoryProperty getContextDirectory(); |
|
36 | public abstract DirectoryProperty getContextDirectory(); | |
@@ -43,7 +43,7 public abstract class BuildImage extends | |||||
43 | public abstract Property<String> getBuildTarget(); |
|
43 | public abstract Property<String> getBuildTarget(); | |
44 |
|
44 | |||
45 | @Input |
|
45 | @Input | |
46 |
public abstract Property< |
|
46 | public abstract Property<String> getImageName(); | |
47 |
|
47 | |||
48 | @Internal |
|
48 | @Internal | |
49 | public abstract RegularFileProperty getImageIdFile(); |
|
49 | public abstract RegularFileProperty getImageIdFile(); | |
@@ -101,7 +101,7 public abstract class BuildImage extends | |||||
101 | // add extra parameters |
|
101 | // add extra parameters | |
102 | getOptions().get().forEach(args::add); |
|
102 | getOptions().get().forEach(args::add); | |
103 |
|
103 | |||
104 |
var imageTag = getImageName(). |
|
104 | var imageTag = getImageName().get(); | |
105 |
|
105 | |||
106 | // build image |
|
106 | // build image | |
107 | docker().buildImage( |
|
107 | docker().buildImage( | |
@@ -111,6 +111,6 public abstract class BuildImage extends | |||||
111 |
|
111 | |||
112 | // read the built image id and store image ref metadata |
|
112 | // read the built image id and store image ref metadata | |
113 | var imageRef = new ImageRef(imageTag, Utils.readAll(iidFile)); |
|
113 | var imageRef = new ImageRef(imageTag, Utils.readAll(iidFile)); | |
114 |
Utils.writeJson(getImageIdFile |
|
114 | Utils.writeJson(getImageIdFile().map(RegularFile::getAsFile).get(), imageRef); | |
115 | } |
|
115 | } | |
116 | } |
|
116 | } |
@@ -7,13 +7,12 import org.gradle.api.provider.Property; | |||||
7 | import org.gradle.api.tasks.Input; |
|
7 | import org.gradle.api.tasks.Input; | |
8 | import org.gradle.api.tasks.Optional; |
|
8 | import org.gradle.api.tasks.Optional; | |
9 | import org.gradle.api.tasks.TaskAction; |
|
9 | import org.gradle.api.tasks.TaskAction; | |
10 | import org.implab.gradle.containers.cli.ImageName; |
|
|||
11 | import org.implab.gradle.containers.dsl.OptionsMixin; |
|
10 | import org.implab.gradle.containers.dsl.OptionsMixin; | |
12 |
|
11 | |||
13 | public abstract class PushImage extends DockerCliTask implements OptionsMixin { |
|
12 | public abstract class PushImage extends DockerCliTask implements OptionsMixin { | |
14 |
|
13 | |||
15 | @Input |
|
14 | @Input | |
16 |
public abstract Property< |
|
15 | public abstract Property<String> getImageName(); | |
17 |
|
16 | |||
18 | @Input |
|
17 | @Input | |
19 | @Optional |
|
18 | @Optional | |
@@ -27,7 +26,7 public abstract class PushImage extends | |||||
27 | public void run() throws InterruptedException, IOException { |
|
26 | public void run() throws InterruptedException, IOException { | |
28 |
|
27 | |||
29 | docker().pushImage( |
|
28 | docker().pushImage( | |
30 |
getImageName().get() |
|
29 | getImageName().get(), | |
31 | getOptions().get()); |
|
30 | getOptions().get()); | |
32 | } |
|
31 | } | |
33 | } |
|
32 | } |
@@ -6,14 +6,13 import org.gradle.api.provider.ListPrope | |||||
6 | import org.gradle.api.provider.Property; |
|
6 | import org.gradle.api.provider.Property; | |
7 | import org.gradle.api.tasks.Input; |
|
7 | import org.gradle.api.tasks.Input; | |
8 | import org.gradle.api.tasks.Optional; |
|
8 | import org.gradle.api.tasks.Optional; | |
9 | import org.implab.gradle.containers.cli.ImageName; |
|
|||
10 | import org.implab.gradle.containers.dsl.OptionsMixin; |
|
9 | import org.implab.gradle.containers.dsl.OptionsMixin; | |
11 | import org.implab.gradle.containers.dsl.VolumeSpec; |
|
10 | import org.implab.gradle.containers.dsl.VolumeSpec; | |
12 |
|
11 | |||
13 | public abstract class RunImage extends DockerCliTask implements OptionsMixin { |
|
12 | public abstract class RunImage extends DockerCliTask implements OptionsMixin { | |
14 |
|
13 | |||
15 | @Input |
|
14 | @Input | |
16 |
public abstract Property< |
|
15 | public abstract Property<String> getImageName(); | |
17 |
|
16 | |||
18 | @Input |
|
17 | @Input | |
19 | @Optional |
|
18 | @Optional | |
@@ -35,7 +34,7 public abstract class RunImage extends D | |||||
35 |
|
34 | |||
36 | public void run() throws InterruptedException, IOException { |
|
35 | public void run() throws InterruptedException, IOException { | |
37 | docker().runImage( |
|
36 | docker().runImage( | |
38 |
getImageName().get() |
|
37 | getImageName().get(), | |
39 | getOptions().get(), |
|
38 | getOptions().get(), | |
40 | getCommandLine().get()); |
|
39 | getCommandLine().get()); | |
41 | } |
|
40 | } |
@@ -4,19 +4,18 import java.io.IOException; | |||||
4 | import org.gradle.api.provider.Property; |
|
4 | import org.gradle.api.provider.Property; | |
5 | import org.gradle.api.tasks.Input; |
|
5 | import org.gradle.api.tasks.Input; | |
6 | import org.gradle.api.tasks.TaskAction; |
|
6 | import org.gradle.api.tasks.TaskAction; | |
7 | import org.implab.gradle.containers.cli.ImageName; |
|
|||
8 |
|
7 | |||
9 | public abstract class TagImage extends DockerCliTask { |
|
8 | public abstract class TagImage extends DockerCliTask { | |
10 | @Input |
|
9 | @Input | |
11 |
public abstract Property< |
|
10 | public abstract Property<String> getSrcImage(); | |
12 |
|
11 | |||
13 | @Input |
|
12 | @Input | |
14 |
public abstract Property< |
|
13 | public abstract Property<String> getDestImage(); | |
15 |
|
14 | |||
16 | @TaskAction |
|
15 | @TaskAction | |
17 | public void run() throws InterruptedException, IOException { |
|
16 | public void run() throws InterruptedException, IOException { | |
18 | docker().tagImage( |
|
17 | docker().tagImage( | |
19 |
getSrcImage( |
|
18 | getSrcImage().get(), | |
20 |
getDestImage( |
|
19 | getDestImage().get()); | |
21 | } |
|
20 | } | |
22 | } |
|
21 | } |
General Comments 0
You need to be logged in to leave comments.
Login now