Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add optional 'command' to Docker compose service #1294

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,30 +16,47 @@

package io.spring.start.site.container;

import java.util.Arrays;
import java.util.Collection;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;

import io.spring.initializr.generator.container.docker.compose.ComposeService.Builder;
import io.spring.initializr.generator.container.docker.compose.ComposeService;

/**
* Description of a Docker service.
*
* @author Stephane Nicoll
* @author Chris Bono
*/
public class DockerService implements Consumer<Builder> {
public final class DockerService implements Consumer<ComposeService.Builder> {

private final String image;

private final String imageTag;

private final String website;

private final String command;

private final int[] ports;

DockerService(String image, String imageTag, String website, int... ports) {
this.image = image;
this.imageTag = imageTag;
this.website = website;
this.ports = ports;
private DockerService(DockerService.Builder builder) {
this.image = builder.image;
this.imageTag = builder.imageTag;
this.website = builder.website;
this.command = builder.command;
this.ports = builder.ports.stream().mapToInt(Number::intValue).toArray();
}

/**
* Return a new builder using the specified image and optional tag.
* @param imageAndTag the image (and optional tag) to use for the service
* @return the new builder instance.
*/
public static DockerService.Builder withImageAndTag(String imageAndTag) {
return new DockerService.Builder(imageAndTag);
}

/**
Expand Down Expand Up @@ -67,6 +84,14 @@ public String getWebsite() {
return this.website;
}

/**
* Return the command to use to override the default command (optional).
* @return the command
*/
public String getCommand() {
return this.command;
}

/**
* Return the ports that should be exposed by the service.
* @return the ports to expose
Expand All @@ -76,8 +101,72 @@ public int[] getPorts() {
}

@Override
public void accept(Builder builder) {
builder.image(this.image).imageTag(this.imageTag).imageWebsite(this.website).ports(this.ports);
public void accept(ComposeService.Builder builder) {
builder.image(this.image)
.imageTag(this.imageTag)
.imageWebsite(this.website)
.command(this.command)
.ports(this.ports);
}

/**
* Builder for {@link DockerService}.
*/
public static class Builder {

private String image;

private String imageTag = "latest";

private String website;

private String command;

private final Set<Integer> ports = new TreeSet<>();

protected Builder(String imageAndTag) {
String[] split = imageAndTag.split(":", 2);
String tag = (split.length == 1) ? "latest" : split[1];
image(split[0]).imageTag(tag);
}

public DockerService.Builder image(String image) {
this.image = image;
return this;
}

public DockerService.Builder imageTag(String imageTag) {
this.imageTag = imageTag;
return this;
}

public DockerService.Builder website(String website) {
this.website = website;
return this;
}

public DockerService.Builder command(String command) {
this.command = command;
return this;
}

public DockerService.Builder ports(Collection<Integer> ports) {
this.ports.addAll(ports);
return this;
}

public DockerService.Builder ports(int... ports) {
return ports(Arrays.stream(ports).boxed().toList());
}

/**
* Builds the {@link DockerService} instance.
* @return the built instance
*/
public DockerService build() {
return new DockerService(this);
}

}

}
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
*
* @author Stephane Nicoll
* @author Moritz Halbritter
* @author Chris Bono
*/
public class SimpleDockerServiceResolver implements DockerServiceResolver {

Expand All @@ -48,59 +49,83 @@ public SimpleDockerServiceResolver() {
}

private static DockerService activeMQ() {
return new DockerService("symptoma/activemq", "latest", "https://hub.docker.com/r/symptoma/activemq", 61616);
return DockerService.withImageAndTag("symptoma/activemq")
.website("https://hub.docker.com/r/symptoma/activemq")
.ports(61616)
.build();
}

private static DockerService cassandra() {
return new DockerService("cassandra", "latest", "https://hub.docker.com/_/cassandra", 9042);
return DockerService.withImageAndTag("cassandra")
.website("https://hub.docker.com/_/cassandra")
.ports(9042)
.build();
}

private static DockerService elasticsearch() {
// They don't provide a 'latest' tag
return new DockerService("docker.elastic.co/elasticsearch/elasticsearch", "7.17.10",
"https://www.docker.elastic.co/r/elasticsearch", 9200, 9300);
return DockerService.withImageAndTag("docker.elastic.co/elasticsearch/elasticsearch:7.17.10")
.website("https://www.docker.elastic.co/r/elasticsearch")
.ports(9200, 9300)
.build();
}

private static DockerService kafka() {
return new DockerService("confluentinc/cp-kafka", "latest", "https://hub.docker.com/r/confluentinc/cp-kafka",
9092);
return DockerService.withImageAndTag("confluentinc/cp-kafka")
.website("https://hub.docker.com/r/confluentinc/cp-kafka")
.ports(9092)
.build();
}

private static DockerService mariaDb() {
return new DockerService("mariadb", "latest", "https://hub.docker.com/_/mariadb", 3306);
return DockerService.withImageAndTag("mariadb").website("https://hub.docker.com/_/mariadb").ports(3306).build();
}

private static DockerService mongoDb() {
return new DockerService("mongo", "latest", "https://hub.docker.com/_/mongo", 27017);
return DockerService.withImageAndTag("mongo").website("https://hub.docker.com/_/mongo").ports(27017).build();
}

private static DockerService mysql() {
return new DockerService("mysql", "latest", "https://hub.docker.com/_/mysql", 3306);
return DockerService.withImageAndTag("mysql").website("https://hub.docker.com/_/mysql").ports(3306).build();
}

private static DockerService oracle() {
return new DockerService("gvenzl/oracle-xe", "latest", "https://hub.docker.com/r/gvenzl/oracle-xe", 1521);
return DockerService.withImageAndTag("gvenzl/oracle-xe")
.website("https://hub.docker.com/r/gvenzl/oracle-xe")
.ports(1521)
.build();
}

private static DockerService postgres() {
return new DockerService("postgres", "latest", "https://hub.docker.com/_/postgres", 5432);
return DockerService.withImageAndTag("postgres")
.website("https://hub.docker.com/_/postgres")
.ports(5432)
.build();
}

private static DockerService rabbit() {
return new DockerService("rabbitmq", "latest", "https://hub.docker.com/_/rabbitmq", 5672);
return DockerService.withImageAndTag("rabbitmq")
.website("https://hub.docker.com/_/rabbitmq")
.ports(5672)
.build();
}

private static DockerService redis() {
return new DockerService("redis", "latest", "https://hub.docker.com/_/redis", 6379);
return DockerService.withImageAndTag("redis").website("https://hub.docker.com/_/redis").ports(6379).build();
}

private static DockerService sqlServer() {
return new DockerService("mcr.microsoft.com/mssql/server", "latest",
"https://mcr.microsoft.com/en-us/product/mssql/server/about/", 1433);
return DockerService.withImageAndTag("mcr.microsoft.com/mssql/server")
.website("https://mcr.microsoft.com/en-us/product/mssql/server/about/")
.ports(1433)
.build();
}

private static DockerService zipkin() {
return new DockerService("openzipkin/zipkin", "latest", "https://hub.docker.com/r/openzipkin/zipkin/", 9411);
return DockerService.withImageAndTag("openzipkin/zipkin")
.website("https://hub.docker.com/r/openzipkin/zipkin/")
.ports(9411)
.build();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/*
* Copyright 2012-2023 the original author or authors.
*
* Licensed 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
*
* https://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.
*/

package io.spring.start.site.container;

import java.util.List;

import org.junit.jupiter.api.Test;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link DockerService}.
*
* @author Chris Bono
*/
class DockerServiceTests {

@Test
void builderWithMinimalOptions() {
DockerService service = DockerService.withImageAndTag("acme/toolbox").build();
assertThat(service.getImage()).isEqualTo("acme/toolbox");
assertThat(service.getImageTag()).isEqualTo("latest");
assertThat(service.getWebsite()).isNull();
assertThat(service.getCommand()).isNull();
assertThat(service.getPorts()).isEmpty();
}

@Test
void builderWithAllOptions() {
DockerService service = DockerService.withImageAndTag("acme/toolbox")
.imageTag("1.0")
.website("acme/toolbox-dot-com")
.command("bin/acme run")
.ports(8007, 8008)
.build();
assertThat(service.getImage()).isEqualTo("acme/toolbox");
assertThat(service.getImageTag()).isEqualTo("1.0");
assertThat(service.getWebsite()).isEqualTo("acme/toolbox-dot-com");
assertThat(service.getCommand()).isEqualTo("bin/acme run");
assertThat(service.getPorts()).containsExactly(8007, 8008);
}

@Test
void builderWithImageAndTagUsesTag() {
DockerService service = DockerService.withImageAndTag("acme/toolbox:1.0").build();
assertThat(service.getImage()).isEqualTo("acme/toolbox");
assertThat(service.getImageTag()).isEqualTo("1.0");
}

@Test
void builderWithImageAndTagIsOverriddenByImageTag() {
DockerService service = DockerService.withImageAndTag("acme/toolbox:1.0").imageTag("2.0").build();
assertThat(service.getImage()).isEqualTo("acme/toolbox");
assertThat(service.getImageTag()).isEqualTo("2.0");
}

@Test
void builderWithCollectionOfPorts() {
DockerService service = DockerService.withImageAndTag("acme/toolbox").ports(List.of(8007, 8008)).build();
assertThat(service.getPorts()).containsExactly(8007, 8008);
}

}
Loading