diff --git a/docker-service-api-core/pom.xml b/docker-service-api-core/pom.xml index 7e0158a..8c7c213 100644 --- a/docker-service-api-core/pom.xml +++ b/docker-service-api-core/pom.xml @@ -9,10 +9,20 @@ org.hobbit docker-service-api-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT + + org.aksw.commons + aksw-commons-utils + + + + org.apache.jena + jena-arq + + com.google.guava guava diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerService.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerService.java index 2c19b75..feb0ec2 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerService.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerService.java @@ -17,6 +17,8 @@ public interface DockerService /** * The container id of a once started service * + * TODO This is usually NOT the docker Id, but an IP address, a host name, or some other form of handle + * * @return */ String getContainerId(); diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilder.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilder.java index ef61367..9655f91 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilder.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilder.java @@ -1,8 +1,13 @@ package org.hobbit.core.service.docker.api; -import java.util.Map; - /** + * Typically, + * a docker serviceBuilder internally bundles a DockerServiceFactory with a mutable configuration object. + * + * + * Note, {@link DockerServiceBuilderFactory} provides the mechanism to create new, + * possibly preconfigured, configurations. + * * Base implementation for creating docker services. * * Calling the .get() method will create a service object whose state is based on the factories current state but independent from it. @@ -10,41 +15,61 @@ * The factory does not do book keeping of created services. * * + * Note: Although DockerService builder extends DockerServiceSpec, it should never be used as such. + * The reason for this inheritance is simply to make method forwarding easier: We can just reuse + * DockerServiceSpecForwarding. + * * @author raven Sep 20, 2017 * */ public interface DockerServiceBuilder - extends ServiceBuilder + extends ServiceBuilder, DockerServiceSpecLike> { - String getImageName(); - DockerServiceBuilder setImageName(String imageName); - - - /** - * Get the local environment of the factory. - * - * - * Local means, that it should NOT return e.g. the system environment - * or anything else that is outside of control of this factory. - * - * - * We use the term local enviroment in order for subclasses to support spring's Environment object, - * which is at the core of dependency injenction, and it has a proper API - * for nesting of property sources - * - * Under this consideration, the local environment should be the treated as the first property source - * of an overall spring environment. - * - * - * @return - */ - Map getLocalEnvironment(); +// String getContainerName(); +// DockerServiceBuilder setContainerName(String containerName); +// +// String getImageName(); +// DockerServiceBuilder setImageName(String imageName); +// +// Map getLocalEnvironment(); +// DockerServiceBuilder setLocalEnvironment(Map localEnvironment); - /** - * - * @param environment - * @return - */ - DockerServiceBuilder setLocalEnvironment(Map environment); + // Yield the object that backs the service builder. + // May be null. + // DockerServiceSpec getSpec(); +// +// String getContainerName(); +// DockerServiceBuilder setContainerName(String containerName); +// +// String getImageName(); +// DockerServiceBuilder setImageName(String imageName); +// +// +// /** +// * Get the local environment of the factory. +// * +// * +// * Local means, that it should NOT return e.g. the system environment +// * or anything else that is outside of control of this factory. +// * +// * +// * We use the term local enviroment in order for subclasses to support spring's Environment object, +// * which is at the core of dependency injenction, and it has a proper API +// * for nesting of property sources +// * +// * Under this consideration, the local environment should be the treated as the first property source +// * of an overall spring environment. +// * +// * +// * @return +// */ +// Map getLocalEnvironment(); +// +// /** +// * +// * @param environment +// * @return +// */ +// DockerServiceBuilder setLocalEnvironment(Map environment); } diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilderFactory.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilderFactory.java new file mode 100644 index 0000000..1e54ab2 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceBuilderFactory.java @@ -0,0 +1,6 @@ +package org.hobbit.core.service.docker.api; + +public interface DockerServiceBuilderFactory +{ + DockerServiceBuilder newServiceBuilder(); +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceFactory.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceFactory.java index 6ac2e78..ed691ec 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceFactory.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceFactory.java @@ -2,6 +2,8 @@ import java.util.Map; +import org.hobbit.core.service.docker.impl.core.DockerServiceSpecImpl; + /** * In contrast to the builder, the service factory only provides a single create method. * @@ -11,5 +13,41 @@ public interface DockerServiceFactory extends AutoCloseable { - T create(String imageName, Map env); + /** + * Create a service object based on a specification + * + * @param serviceSpec + * @return + */ + T create(DockerServiceSpec serviceSpec); + + /** + * Method to obtain a new, possibly partially configured, service specification object. + * + * @return + */ +// default DockerServiceSpec newSpec() { +// return new DockerServiceSpecImpl(); +// } + + // TODO Due to dependence on the serviceSpec object, which might already be implementation dependnent, + // this implementation might better fit into an abstract class + default T create(String containerName, String imageName, Map env) { + //DockerServiceSpec r = ModelFactory.createDefaultModel().createResource().as(DockerServiceSpec.class); + +// DockerServiceSpec r = newSpec(); + DockerServiceSpec r = new DockerServiceSpecImpl(); + + r.setContainerName(containerName); + r.setImageName(imageName); + r.setLocalEnvironment(env); + + T result = create(r); + return result; + } + + default T create(String imageName, Map env) { + T result = create(null, imageName, env); + return result; + } } diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpec.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpec.java new file mode 100644 index 0000000..8412f56 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpec.java @@ -0,0 +1,24 @@ +package org.hobbit.core.service.docker.api; + +/** + * Simple mutable specification of a docker(-like) service. + * + * Note, that this is deliberately an interface so that implementations + * can choose to use different backing specification objects, + * such as JSON or RDF resources. + * + * @author Claus Stadler, Jan 9, 2019 + * + */ +public interface DockerServiceSpec + extends DockerServiceSpecLike +{ +// String getContainerName(); +// DockerServiceSpec setContainerName(String containerName); +// +// String getImageName(); +// DockerServiceSpec setImageName(String imageName); +// +// Map getLocalEnvironment(); +// DockerServiceSpec setLocalEnvironment(Map localEnvironment); +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpecLike.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpecLike.java new file mode 100644 index 0000000..6170d00 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSpecLike.java @@ -0,0 +1,14 @@ +package org.hobbit.core.service.docker.api; + +import java.util.Map; + +public interface DockerServiceSpecLike> { + String getContainerName(); + F setContainerName(String containerName); + + String getImageName(); + F setImageName(String imageName); + + Map getLocalEnvironment(); + F setLocalEnvironment(Map localEnvironment); +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSystem.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSystem.java new file mode 100644 index 0000000..8996d1a --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/DockerServiceSystem.java @@ -0,0 +1,20 @@ +package org.hobbit.core.service.docker.api; + + +/** + * A DockerServiceSystem combines both the factory and the builder APIs: + * - The builder API creates preconfigured configuration objects that can be modified using the + * DockerServiceSpec API. Internal config objects may be accessible by casting the + * DockerServiceSpec config object. + * - The factory API, which only takes a single service specification, and fills the rest up with + * default values based on the factory state. This approach does not give access to internal config objects. + * + * @author Claus Stadler, Jan 9, 2019 + * + * @param + */ +public interface DockerServiceSystem + extends DockerServiceFactory, DockerServiceBuilderFactory +{ + T findServiceByName(String id); +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/ResourceAware.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/ResourceAware.java new file mode 100644 index 0000000..761f78d --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/ResourceAware.java @@ -0,0 +1,13 @@ +package org.hobbit.core.service.docker.api; + +/** + * Interface for Java classes to expose whether they can make use of Jena's + * Resource infrastructure + * + * @author Claus Stadler, Jan 9, 2019 + * + */ +public interface ResourceAware { + boolean isResource(); + +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/SimpleServiceFactory.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/SimpleServiceFactory.java index ea8ac64..5bb0ba8 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/SimpleServiceFactory.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/api/SimpleServiceFactory.java @@ -1,17 +1,14 @@ package org.hobbit.core.service.docker.api; -import java.util.Map; - -import com.google.common.util.concurrent.Service; - /** * A simple service factory is configured via an environment * * @author raven * */ -public interface SimpleServiceFactory - extends ServiceBuilder -{ - Map getEnvironment(); -} +//Probably can be removed +//public interface SimpleServiceFactory +// extends ServiceBuilder +//{ +// Map getEnvironment(); +//} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/AbstractSimpleServiceFactory.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/AbstractSimpleServiceFactory.java index 7fda6e4..a514c2d 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/AbstractSimpleServiceFactory.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/AbstractSimpleServiceFactory.java @@ -1,18 +1,12 @@ package org.hobbit.core.service.docker.impl.core; -import java.util.LinkedHashMap; -import java.util.Map; - -import org.hobbit.core.service.docker.api.SimpleServiceFactory; - -import com.google.common.util.concurrent.Service; - -public abstract class AbstractSimpleServiceFactory - implements SimpleServiceFactory -{ - protected Map environment = new LinkedHashMap<>(); - - public Map getEnvironment() { - return environment; - } -} +// Probably can be removed +//public abstract class AbstractSimpleServiceFactory +// implements SimpleServiceFactory +//{ +// protected Map environment = new LinkedHashMap<>(); +// +// public Map getEnvironment() { +// return environment; +// } +//} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderFactory.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderFactory.java index 43208a5..1965aee 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderFactory.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderFactory.java @@ -4,6 +4,7 @@ import org.hobbit.core.service.docker.api.DockerService; import org.hobbit.core.service.docker.api.DockerServiceBuilder; +import org.hobbit.core.service.docker.api.DockerServiceFactory; /** * A convenience interface which can be used e.g. in dependency injection. @@ -16,8 +17,6 @@ public interface DockerServiceBuilderFactory> extends Supplier { - - /** * Creates a DockerServiceBuilderFactory from a Supplier. * A down cast is performed (instead of wrapping) if this supplier is already a DockerServiceBuilderFactory diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderImpl.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderImpl.java new file mode 100644 index 0000000..13ee766 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderImpl.java @@ -0,0 +1,42 @@ +package org.hobbit.core.service.docker.impl.core; + +import java.util.Map; + +import org.hobbit.core.service.docker.api.DockerService; +import org.hobbit.core.service.docker.api.DockerServiceBuilder; +import org.hobbit.core.service.docker.api.DockerServiceFactory; +import org.hobbit.core.service.docker.api.DockerServiceSpec; +import org.hobbit.core.service.docker.api.DockerServiceSpecLike; + +/** + * + * + * @author Claus Stadler, Jan 9, 2019 + * + * @param + */ +public class DockerServiceBuilderImpl + extends DockerServiceSpecLikeForwarding> + implements DockerServiceBuilder +{ + protected DockerServiceFactory dockerServiceFactory; + protected DockerServiceSpec serviceSpec; + + + public DockerServiceBuilderImpl(DockerServiceFactory dockerServiceFactory, DockerServiceSpec serviceSpec) { + super(); + this.dockerServiceFactory = dockerServiceFactory; + this.serviceSpec = serviceSpec; + } + + @Override + public DockerServiceSpecLike getDelegate() { + return serviceSpec; + } + + @Override + public T get() { + T result = dockerServiceFactory.create(serviceSpec); + return result; + } +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderJsonDelegate.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderJsonDelegate.java index 99a8fb7..fe0124c 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderJsonDelegate.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderJsonDelegate.java @@ -26,6 +26,7 @@ public class DockerServiceBuilderJsonDelegate implements DockerServiceBuilder//, Cloneable { + public static final String KEY_CONTAINER_NAME = "containerName"; public static final String KEY_IMAGE_NAME = "imageName"; public static final String KEY_ENV = "env"; public static final String KEY_BASE_ENV = "baseEnv"; @@ -46,6 +47,20 @@ public DockerServiceBuilderJsonDelegate(Function delegate, JsonOb this.config = config; } + @Override + public String getContainerName() { + String result = config.get(KEY_CONTAINER_NAME).getAsString(); + return result; + } + + @Override + public DockerServiceBuilder setContainerName(String containerName) { + config.remove(KEY_CONTAINER_NAME); + config.addProperty(KEY_CONTAINER_NAME, containerName); + + return this; + } + @Override public String getImageName() { String result = config.get(KEY_IMAGE_NAME).getAsString(); @@ -110,6 +125,7 @@ public T get() { public static Type mapStringStringType = new TypeToken>() {}.getType(); + // TODO The argument should be Function serviceFactory public static DockerServiceBuilderJsonDelegate create(BiFunction, T> serviceFactory) { Function wrapperFn = jsonObj -> { String imageName = jsonObj.get(KEY_IMAGE_NAME).getAsString(); diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderSimpleDelegation.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderSimpleDelegation.java index d545d3d..effa447 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderSimpleDelegation.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceBuilderSimpleDelegation.java @@ -26,6 +26,10 @@ public class DockerServiceBuilderSimpleDelegation implements DockerServiceBuilder//, Cloneable { + // FIXME The design we actually want is to use an Resource to hold the state, + // and then just delegate the resource to a function + // The consumer can then create any view of the resource it wants + protected String containerName; protected String imageName; protected Map localEnvironment; @@ -62,6 +66,17 @@ public DockerServiceBuilderSimpleDelegation( // return result; // } + @Override + public String getContainerName() { + return containerName; + } + + @Override + public DockerServiceBuilder setContainerName(String containerName) { + this.containerName = containerName; + return this; + } + @Override public String getImageName() { return imageName; diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceFactoryChain.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceFactoryChain.java index 8ba9312..7326f62 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceFactoryChain.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceFactoryChain.java @@ -3,10 +3,10 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import java.util.Map; import org.hobbit.core.service.docker.api.DockerService; import org.hobbit.core.service.docker.api.DockerServiceFactory; +import org.hobbit.core.service.docker.api.DockerServiceSpec; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -26,12 +26,14 @@ public DockerServiceFactoryChain(DockerServiceFactory ... _factories) { @Override - public DockerService create(String imageName, Map env) { + public DockerService create(DockerServiceSpec serviceSpec) { + + String imageName = serviceSpec.getImageName(); DockerService result = null; for(DockerServiceFactory factory : factories) { try { - result = factory.create(imageName, env); + result = factory.create(serviceSpec); break; } catch(UnsupportedOperationException e) { logger.info("Service factory did not support " + imageName + ", trying next one"); diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecImpl.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecImpl.java new file mode 100644 index 0000000..36cfcc6 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecImpl.java @@ -0,0 +1,98 @@ +package org.hobbit.core.service.docker.impl.core; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.hobbit.core.service.docker.api.DockerServiceSpec; + +/** + * Most simple implementation of a service specification as a Pojo. + * + * + * + * @author Claus Stadler, Jan 9, 2019 + * + */ +public class DockerServiceSpecImpl + implements DockerServiceSpec +{ + protected String containerName = null; + protected String imageName = null; + protected Map localEnvironment = new LinkedHashMap<>(); + + @Override + public String getContainerName() { + return containerName; + } + + @Override + public DockerServiceSpec setContainerName(String containerName) { + this.containerName = containerName; + return this; + } + + @Override + public String getImageName() { + return imageName; + } + + @Override + public DockerServiceSpec setImageName(String imageName) { + this.imageName = imageName; + return this; + } + + @Override + public Map getLocalEnvironment() { + return localEnvironment; + } + + @Override + public DockerServiceSpec setLocalEnvironment(Map localEnvironment) { + this.localEnvironment = localEnvironment; + return this; + } + + @Override + public String toString() { + return "DockerServiceSpecImpl [containerName=" + containerName + ", imageName=" + imageName + + ", localEnvironment=" + localEnvironment + "]"; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ((containerName == null) ? 0 : containerName.hashCode()); + result = prime * result + ((imageName == null) ? 0 : imageName.hashCode()); + result = prime * result + ((localEnvironment == null) ? 0 : localEnvironment.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) + return true; + if (obj == null) + return false; + if (getClass() != obj.getClass()) + return false; + DockerServiceSpecImpl other = (DockerServiceSpecImpl) obj; + if (containerName == null) { + if (other.containerName != null) + return false; + } else if (!containerName.equals(other.containerName)) + return false; + if (imageName == null) { + if (other.imageName != null) + return false; + } else if (!imageName.equals(other.imageName)) + return false; + if (localEnvironment == null) { + if (other.localEnvironment != null) + return false; + } else if (!localEnvironment.equals(other.localEnvironment)) + return false; + return true; + } +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecLikeForwarding.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecLikeForwarding.java new file mode 100644 index 0000000..c20ced2 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceSpecLikeForwarding.java @@ -0,0 +1,48 @@ +package org.hobbit.core.service.docker.impl.core; + +import java.util.Map; + +import org.hobbit.core.service.docker.api.DockerServiceSpecLike; + +public abstract class DockerServiceSpecLikeForwarding> + implements DockerServiceSpecLike +{ + public abstract DockerServiceSpecLike getDelegate(); + + @Override + public String getContainerName() { + return getDelegate().getContainerName(); + } + + @SuppressWarnings("unchecked") + @Override + public F setContainerName(String containerName) { + getDelegate().setContainerName(containerName); + return (F)this; + } + + @Override + public String getImageName() { + return getDelegate().getImageName(); + } + + @SuppressWarnings("unchecked") + @Override + public F setImageName(String imageName) { + getDelegate().setImageName(imageName); + return (F)this; + } + + @Override + public Map getLocalEnvironment() { + return getDelegate().getLocalEnvironment(); + } + + @SuppressWarnings("unchecked") + @Override + public F setLocalEnvironment(Map localEnvironment) { + getDelegate().setLocalEnvironment(localEnvironment); + return (F)this; + } + +} diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServicePseudoDelegate.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceWrapper.java similarity index 89% rename from docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServicePseudoDelegate.java rename to docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceWrapper.java index 9c6fb23..a57a9eb 100644 --- a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServicePseudoDelegate.java +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/impl/core/DockerServiceWrapper.java @@ -17,17 +17,17 @@ * * @param */ -public class DockerServicePseudoDelegate +public class DockerServiceWrapper extends ServiceDelegate implements DockerService { - private static final Logger logger = LoggerFactory.getLogger(DockerServicePseudoDelegate.class); + private static final Logger logger = LoggerFactory.getLogger(DockerServiceWrapper.class); protected String imageName; protected Supplier getContainerId; - public DockerServicePseudoDelegate(S service, String imageName, Supplier getContainerId) { + public DockerServiceWrapper(S service, String imageName, Supplier getContainerId) { super(service); this.imageName = imageName; this.getContainerId = getContainerId; diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractDockerServiceDelegate.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractDockerServiceDelegate.java new file mode 100644 index 0000000..ab5dd2c --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractDockerServiceDelegate.java @@ -0,0 +1,28 @@ +package org.hobbit.core.service.docker.util; + +import org.hobbit.core.service.docker.api.DockerService; + +public class AbstractDockerServiceDelegate + extends AbstractServiceDelegate + implements DockerService // TODO There could be default methods for delegation +{ + public AbstractDockerServiceDelegate(S delegate) { + super(delegate); + } + + @Override + public String getImageName() { + return delegate.getImageName(); + } + + @Override + public String getContainerId() { + return delegate.getContainerId(); + } + + @Override + public Integer getExitCode() { + return delegate.getExitCode(); + } + +} \ No newline at end of file diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractServiceDelegate.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractServiceDelegate.java new file mode 100644 index 0000000..74d4968 --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/AbstractServiceDelegate.java @@ -0,0 +1,70 @@ +package org.hobbit.core.service.docker.util; + +import com.google.common.util.concurrent.AbstractService; +import com.google.common.util.concurrent.MoreExecutors; +import com.google.common.util.concurrent.Service; + +/** + * Service wrapper that allows post start and post stop action to be appended + * to an existing service. + * The service wrapper is only considered started/stopped when the post + * action is completed. + * + * @author raven + * + * @param + */ +public class AbstractServiceDelegate + extends AbstractService +{ + protected S delegate; + + public AbstractServiceDelegate(S delegate) { + super(); + this.delegate = delegate; + } + + @Override + protected void doStart() { + delegate.addListener(new Listener() { + @Override + public void running() { + try { + afterStart(); + } catch(Exception e) { + delegate.stopAsync(); + notifyFailed(e); + } + + notifyStarted(); + } + @Override + public void failed(State priorState, Throwable t) { + notifyFailed(t); + } + + @Override + public void terminated(State priorState) { + try { + afterStop(); + } finally { + notifyStopped(); + } + } + }, MoreExecutors.directExecutor()); + + delegate.startAsync(); + } + + @Override + protected void doStop() { + delegate.stopAsync(); + } + + public void afterStart() { + } + + public void afterStop() { + } +} + diff --git a/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/ComponentUtils.java b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/ComponentUtils.java new file mode 100644 index 0000000..960b1ba --- /dev/null +++ b/docker-service-api-core/src/main/java/org/hobbit/core/service/docker/util/ComponentUtils.java @@ -0,0 +1,116 @@ +package org.hobbit.core.service.docker.util; + +import java.net.URL; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Map.Entry; +import java.util.concurrent.TimeUnit; +import java.util.function.Function; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.aksw.commons.util.healthcheck.HealthcheckRunner; +import org.aksw.commons.util.healthcheck.HealthcheckUtils; +import org.hobbit.core.service.docker.api.DockerService; +import org.hobbit.core.service.docker.api.DockerServiceFactory; +import org.hobbit.core.service.docker.api.DockerServiceSpec; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ComponentUtils { + private static final Logger logger = LoggerFactory.getLogger(ComponentUtils.class); + + public static final String COMPONENT_NAME_KEY = "componentName"; + public static final String DEFAULT_REQUESTED_CONTAINER_TYPE_KEY = "defaultRequstedContainerType"; + + + +// public static DockerServiceFactory createVirtualComponentDockerServiceFactory() { +// +// Map> virtualDockerComponentRegistry = getVirtualDockerComponentRegistry(); +// DockerServiceFactory result = new DockerServiceFactorySpringApplicationBuilder(virtualDockerComponentRegistry); +// +// return result; +// } + + + public static DockerService wrapSparqlServiceWithHealthCheck(S dockerService, Function healthCheckUrlFromServiceDelegate) { + + DockerService result = new AbstractDockerServiceDelegate(dockerService) { + // FIXME We want to enhance the startup method within the thread allocated by the guava service + @Override + public void afterStart() { + // The delegate has started, so we have a container id + //String host = delegate.getContainerId(); + String urlStr = healthCheckUrlFromServiceDelegate.apply(delegate); + + //String destination = "http://" + host + (port == null ? "" : ":" + port) + "/sparql"; + + URL url = HealthcheckUtils.createUrl(urlStr); + HealthcheckRunner.builder() + .setRetryCount(60) + .setInterval(1, TimeUnit.SECONDS) + .setAction(() -> HealthcheckUtils.checkUrl(url)) + .build() + .run(); + +// new HealthcheckRunner( +// 60, 1, TimeUnit.SECONDS, () -> { +// HealthcheckUtils.checkUrl(url); +// +// // This part seems to leak connections with jena 3.7.0 as long as the endpoint is not ready +//// try (RDFConnection conn = RDFConnectionFactory.connect(destination)) { +//// //conn.querySelect("SELECT * { a ?t }", qs -> {}); +//// ResultSetFormatter.consume(conn.query("SELECT * { a ?t }").execSelect()); +//// } +// }).run(); + } + }; + + return result; + } + + public static DockerService wrapSparqlServiceWithHealthCheck(DockerService dockerService, Integer port) { + return wrapSparqlServiceWithHealthCheck(dockerService, delegate -> "http://" + delegate.getContainerId() + (port == null ? "" : ":" + port) + "/sparql"); + } + + + public static DockerServiceFactory applyServiceWrappers(DockerServiceFactory delegate) { + + // Service wrappers which modifies startup/shutdown of other services; mostly healthchecks + // on startup + Map> serviceWrappers = new LinkedHashMap<>(); + serviceWrappers.put(Pattern.compile("virtuoso"), dockerService -> wrapSparqlServiceWithHealthCheck(dockerService, 8890)); + DockerServiceFactory result = new DockerServiceFactory() { + + @Override + public DockerService create(DockerServiceSpec serviceSpec) { + + String imageName = serviceSpec.getImageName(); + + DockerService r = delegate.create(serviceSpec); + + Map> cands = + serviceWrappers.entrySet().stream() + .filter(x -> x.getKey().matcher(imageName).find()) + .collect(Collectors.toMap(Entry::getKey, Entry::getValue)); + + + for(Entry> cand : cands.entrySet()) { + logger.info("Applying service decorator: " + cand.getKey() + " to docker image " + imageName); + r = cand.getValue().apply(r); + } + + return r; + } + + @Override + public void close() throws Exception { + delegate.close(); + } + }; + + return result; + } + +} \ No newline at end of file diff --git a/docker-service-api-docker-client/pom.xml b/docker-service-api-docker-client/pom.xml index 1740fae..9a4f50a 100644 --- a/docker-service-api-docker-client/pom.xml +++ b/docker-service-api-docker-client/pom.xml @@ -9,7 +9,7 @@ org.hobbit docker-service-api-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceBuilderDockerClient.java b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceBuilderDockerClient.java index a5c6f1d..a2106f9 100644 --- a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceBuilderDockerClient.java +++ b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceBuilderDockerClient.java @@ -1,123 +1,110 @@ package org.hobbit.core.service.docker.impl.docker_client; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Set; - -import org.hobbit.core.service.docker.api.DockerServiceBuilder; -import org.hobbit.core.service.docker.util.EnvironmentUtils; - -import com.spotify.docker.client.DockerClient; -import com.spotify.docker.client.messages.ContainerConfig; - /** * Implementation of DockerServiceFactory for docker containers backed by spotify's docker client * * @author raven Sep 20, 2017 * */ -@Deprecated -public class DockerServiceBuilderDockerClient - implements DockerServiceBuilder -{ - protected DockerClient dockerClient; - protected ContainerConfig.Builder containerConfigBuilder; - protected boolean hostMode; - protected Set networks; - - protected Map localEnv = new LinkedHashMap<>(); - -// public DockerServiceBuilderDockerClient() { +//@Deprecated +//public class DockerServiceBuilderDockerClient +// implements DockerServiceBuilder +//{ +// protected DockerClient dockerClient; +// protected ContainerConfig.Builder containerConfigBuilder; +// protected boolean hostMode; +// protected Set networks; +// +// protected Map localEnv = new LinkedHashMap<>(); +// +//// public DockerServiceBuilderDockerClient() { +//// super(); +//// } +// +//// public DockerServiceFactoryDockerClient(DockerClient dockerClient) { +//// this(null, null); //new ContainerCon +//// } +// +// public DockerServiceBuilderDockerClient(DockerClient dockerClient, ContainerConfig.Builder containerConfigBuilder, boolean hostMode, Set networks) { // super(); +// this.dockerClient = dockerClient; +// this.containerConfigBuilder = containerConfigBuilder; +// this.hostMode = hostMode; +// this.networks = networks; // } - -// public DockerServiceFactoryDockerClient(DockerClient dockerClient) { -// this(null, null); //new ContainerCon +// +// public DockerClient getDockerClient() { +// return dockerClient; // } - - public DockerServiceBuilderDockerClient(DockerClient dockerClient, ContainerConfig.Builder containerConfigBuilder, boolean hostMode, Set networks) { - super(); - this.dockerClient = dockerClient; - this.containerConfigBuilder = containerConfigBuilder; - this.hostMode = hostMode; - this.networks = networks; - } - - public DockerClient getDockerClient() { - return dockerClient; - } - - public DockerServiceBuilderDockerClient setDockerClient(DockerClient dockerClient) { - this.dockerClient = dockerClient; - return this; - } - - public ContainerConfig.Builder getContainerConfigBuilder() { - return containerConfigBuilder; - } - - public DockerServiceBuilderDockerClient setContainerConfigBuilder(ContainerConfig.Builder containerConfigBuilder) { - this.containerConfigBuilder = containerConfigBuilder; - return this; - } - - - public String getImageName() { - return containerConfigBuilder.build().image(); - } - - public DockerServiceBuilderDockerClient setImageName(String imageName) { - containerConfigBuilder.image(imageName); - return this; - } - - - @Override - public Map getLocalEnvironment() { - return localEnv; -// List env = containerConfigBuilder.build().env(); -// if(env == null) { -// env = Collections.emptyList(); -// } // -// Map result = EnvironmentUtils.listToMap("=", env); +// public DockerServiceBuilderDockerClient setDockerClient(DockerClient dockerClient) { +// this.dockerClient = dockerClient; +// return this; +// } // -// return result; - } - - @Override - public DockerServiceBuilder setLocalEnvironment(Map environment) { - this.localEnv = environment; - return this; -// List env = EnvironmentUtils.mapToList("=", environment); +// public ContainerConfig.Builder getContainerConfigBuilder() { +// return containerConfigBuilder; +// } // -// containerConfigBuilder.env(env); +// public DockerServiceBuilderDockerClient setContainerConfigBuilder(ContainerConfig.Builder containerConfigBuilder) { +// this.containerConfigBuilder = containerConfigBuilder; // return this; - } - - - @Override - public DockerServiceDockerClient get() { - Objects.requireNonNull(dockerClient); - Objects.requireNonNull(containerConfigBuilder); - - // Merge the local environment into that of the containerConfig - List rawEnv = containerConfigBuilder.build().env(); - if(rawEnv == null) { - rawEnv = Collections.emptyList(); - } - - Map env = EnvironmentUtils.listToMap(rawEnv); - env.putAll(localEnv); - - List envList = EnvironmentUtils.mapToList(env); - containerConfigBuilder.env(envList); - ContainerConfig containerConfig = containerConfigBuilder.build(); - - DockerServiceDockerClient result = new DockerServiceDockerClient(dockerClient, containerConfig, null, hostMode, networks); - return result; - } -} +// } +// +// +// public String getImageName() { +// return containerConfigBuilder.build().image(); +// } +// +// public DockerServiceBuilderDockerClient setImageName(String imageName) { +// containerConfigBuilder.image(imageName); +// return this; +// } +// +// +// @Override +// public Map getLocalEnvironment() { +// return localEnv; +//// List env = containerConfigBuilder.build().env(); +//// if(env == null) { +//// env = Collections.emptyList(); +//// } +//// +//// Map result = EnvironmentUtils.listToMap("=", env); +//// +//// return result; +// } +// +// @Override +// public DockerServiceBuilder setLocalEnvironment(Map environment) { +// this.localEnv = environment; +// return this; +//// List env = EnvironmentUtils.mapToList("=", environment); +//// +//// containerConfigBuilder.env(env); +//// return this; +// } +// +// +// @Override +// public DockerServiceDockerClient get() { +// Objects.requireNonNull(dockerClient); +// Objects.requireNonNull(containerConfigBuilder); +// +// // Merge the local environment into that of the containerConfig +// List rawEnv = containerConfigBuilder.build().env(); +// if(rawEnv == null) { +// rawEnv = Collections.emptyList(); +// } +// +// Map env = EnvironmentUtils.listToMap(rawEnv); +// env.putAll(localEnv); +// +// List envList = EnvironmentUtils.mapToList(env); +// containerConfigBuilder.env(envList); +// ContainerConfig containerConfig = containerConfigBuilder.build(); +// +// DockerServiceDockerClient result = new DockerServiceDockerClient(dockerClient, containerConfig, null, hostMode, networks); +// return result; +// } +//} diff --git a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceDockerClient.java b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceDockerClient.java index 89c3c17..5860c03 100644 --- a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceDockerClient.java +++ b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceDockerClient.java @@ -42,12 +42,15 @@ public class DockerServiceDockerClient // Status fields for running services // Container id (requires the service to be running) protected String containerId; - protected Integer exitCode; + protected Long exitCode; protected String containerName; protected boolean hostMode; + + protected String creationId; + public DockerServiceDockerClient(DockerClient dockerClient, ContainerConfig containerConfig, String name, boolean hostMode, Set networks) { super(); this.dockerClient = dockerClient; @@ -64,8 +67,8 @@ protected void startUp() throws Exception { logger.info("Attempting to start docker container: " + getImageName() + " env: " + containerConfig.env() + " hostMode: " + hostMode + " networks: " + networks); ContainerCreation creation = dockerClient.createContainer(containerConfig, name); - containerId = creation.id(); - + creationId = creation.id(); + containerId = creationId; ContainerInfo containerInfo = dockerClient.inspectContainer(containerId); @@ -203,6 +206,10 @@ public String getImageName() { return result; } + public String getCreationId() { + return creationId; + } + @Override public String getContainerId() { //return containerId; @@ -233,7 +240,7 @@ protected Scheduler scheduler() { @Override public Integer getExitCode() { //logger.warn("STUB! Exist code always returns 0"); - return exitCode; + return exitCode != null ? exitCode.intValue() : null; } } diff --git a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSpecDockerClient.java b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSpecDockerClient.java new file mode 100644 index 0000000..09f2603 --- /dev/null +++ b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSpecDockerClient.java @@ -0,0 +1,114 @@ +package org.hobbit.core.service.docker.impl.docker_client; + +import java.util.Collections; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.hobbit.core.service.docker.api.DockerServiceSpec; +import org.hobbit.core.service.docker.util.EnvironmentUtils; + +import com.spotify.docker.client.messages.ContainerConfig; + +/** + * DockerServceSpec implementation that is backed by + * DockerClient's containerConfig object + * + * @author Claus Stadler, Jan 9, 2019 + * + */ +public class DockerServiceSpecDockerClient + implements DockerServiceSpec +{ + protected ContainerConfig.Builder containerConfigBuilder; + protected boolean hostMode; + protected Set networks; + protected String containerName; + + protected Map localEnv = new LinkedHashMap<>(); + + + public static DockerServiceSpecDockerClient wrap(ContainerConfig.Builder containerConfigBuilder) { + DockerServiceSpecDockerClient result = new DockerServiceSpecDockerClient(); + result.setContainerConfigBuilder(containerConfigBuilder); + + return result; + } + + public ContainerConfig.Builder getContainerConfigBuilder() { + return containerConfigBuilder; + } + + public DockerServiceSpecDockerClient setContainerConfigBuilder(ContainerConfig.Builder containerConfigBuilder) { + this.containerConfigBuilder = containerConfigBuilder; + return this; + } + + @Override + public String getContainerName() { + return containerName; + } + + @Override + public DockerServiceSpec setContainerName(String containerName) { + this.containerName = containerName; + return this; + } + + + public String getImageName() { + return containerConfigBuilder.build().image(); + } + + public DockerServiceSpecDockerClient setImageName(String imageName) { + containerConfigBuilder.image(imageName); + return this; + } + + @Override + public Map getLocalEnvironment() { + return localEnv; + } + + @Override + public DockerServiceSpecDockerClient setLocalEnvironment(Map environment) { + this.localEnv = environment; + return this; + } + + public Set getNetworks() { + return networks; + } + + public boolean isHostMode() { + return hostMode; + } + + /** + * Specifically, merges the local environment into that of the containerConfig + * + * @return + */ + public static void finalizeContainerConfig(DockerServiceSpecDockerClient config) { + //Objects.requireNonNull(containerConfigBuilder); + ContainerConfig.Builder containerConfigBuilder = config.getContainerConfigBuilder(); + Map localEnv = config.getLocalEnvironment(); + + // Merge the local environment into that of the containerConfig + List rawEnv = containerConfigBuilder.build().env(); + if (rawEnv == null) { + rawEnv = Collections.emptyList(); + } + + Map env = EnvironmentUtils.listToMap(rawEnv); + env.putAll(localEnv); + + List envList = EnvironmentUtils.mapToList(env); + containerConfigBuilder.env(envList); + //ContainerConfig containerConfig = containerConfigBuilder.build(); + + //return containerConfig; + } + +} diff --git a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceFactoryDockerClient.java b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSystemDockerClient.java similarity index 55% rename from docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceFactoryDockerClient.java rename to docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSystemDockerClient.java index 5cbddd9..99e1500 100644 --- a/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceFactoryDockerClient.java +++ b/docker-service-api-docker-client/src/main/java/org/hobbit/core/service/docker/impl/docker_client/DockerServiceSystemDockerClient.java @@ -1,8 +1,8 @@ package org.hobbit.core.service.docker.impl.docker_client; import java.util.ArrayList; +import java.util.Collections; import java.util.HashMap; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -11,19 +11,26 @@ import java.util.function.Supplier; import org.hobbit.core.service.docker.api.DockerService; -import org.hobbit.core.service.docker.api.DockerServiceFactory; +import org.hobbit.core.service.docker.api.DockerServiceBuilder; +import org.hobbit.core.service.docker.api.DockerServiceSpec; +import org.hobbit.core.service.docker.api.DockerServiceSystem; +import org.hobbit.core.service.docker.impl.core.DockerServiceBuilderImpl; import org.hobbit.core.service.docker.util.EnvironmentUtils; import com.spotify.docker.client.DefaultDockerClient; import com.spotify.docker.client.DockerClient; +import com.spotify.docker.client.DockerClient.ListContainersParam; import com.spotify.docker.client.exceptions.DockerCertificateException; +import com.spotify.docker.client.exceptions.DockerException; +import com.spotify.docker.client.messages.Container; import com.spotify.docker.client.messages.ContainerConfig; import com.spotify.docker.client.messages.ContainerConfig.Builder; import com.spotify.docker.client.messages.HostConfig; import com.spotify.docker.client.messages.PortBinding; -public class DockerServiceFactoryDockerClient - implements DockerServiceFactory +public class DockerServiceSystemDockerClient + //implements DockerServiceFactory + implements DockerServiceSystem { protected DockerClient dockerClient; protected Supplier containerConfigBuilderSupplier; @@ -31,7 +38,7 @@ public class DockerServiceFactoryDockerClient protected Set networks; - public DockerServiceFactoryDockerClient( + public DockerServiceSystemDockerClient( DockerClient dockerClient, Supplier containerConfigBuilderSupplier, boolean hostMode, @@ -48,6 +55,13 @@ public DockerServiceFactoryDockerClient( this.networks = networks; } + /** + * + * @return the backing docker client instance + */ + public DockerClient getDockerClient() { + return dockerClient; + } // public static boolean containsVersionTag(String imageName) { // int pos = 0; @@ -92,14 +106,36 @@ public static String deriveHostname(String imageName) { } @Override - public DockerService create(String imageName, Map localEnv) { - Builder builder = containerConfigBuilderSupplier.get(); - Map env = new LinkedHashMap<>(); - env.putAll(EnvironmentUtils.listToMap(builder.build().env())); - env.putAll(localEnv); + public DockerServiceDockerClient create(DockerServiceSpec serviceSpec) { + + String containerName = serviceSpec.getContainerName(); + String imageName = serviceSpec.getImageName(); + Map localEnv = serviceSpec.getLocalEnvironment(); + + Builder builder = null; + if(serviceSpec instanceof DockerServiceSpecDockerClient) { + DockerServiceSpecDockerClient tmp = (DockerServiceSpecDockerClient)serviceSpec; + + //DockerServiceSpecContainerConfig.finalizeContainerConfig(tmp); + + builder = tmp.getContainerConfigBuilder(); + } + + if(builder == null) { + builder = containerConfigBuilderSupplier.get(); + } + - String containerName = null; - if(!hostMode) { + List rawEnv = builder.build().env(); + if(rawEnv == null) { + rawEnv = Collections.emptyList(); + } + + Map env = EnvironmentUtils.listToMap(rawEnv); + env.putAll(localEnv); + + //String containerName = null; + if(containerName == null && !hostMode) { String hostname = deriveHostname(imageName); builder.hostname(hostname); containerName = hostname; @@ -116,11 +152,10 @@ public DockerService create(String imageName, Map localEnv) { } - public static DockerServiceFactory create( + public static DockerServiceSystemDockerClient create( boolean hostMode, Map env, Set networks) throws DockerCertificateException { DockerClient dockerClient = DefaultDockerClient.fromEnv().build(); - // Bind container port 443 to an automatically allocated available host String[] ports = { }; //{ "80", "22" }; Map> portBindings = new HashMap<>(); @@ -148,13 +183,71 @@ public static DockerServiceFactory create( ; //Set networks = Collections.singleton("hobbit"); - DockerServiceFactoryDockerClient result = new DockerServiceFactoryDockerClient(dockerClient, containerConfigBuilderSupplier, hostMode, networks); + DockerServiceSystemDockerClient result = new DockerServiceSystemDockerClient(dockerClient, containerConfigBuilderSupplier, hostMode, networks); return result; } - @Override public void close() throws Exception { dockerClient.close(); - } + } + + + @Override + public DockerServiceBuilder newServiceBuilder() { + Builder containerConfigBuilder = containerConfigBuilderSupplier.get(); + + DockerServiceSpec serviceSpec = DockerServiceSpecDockerClient.wrap(containerConfigBuilder); + +// // // Merge the local environment into that of the containerConfig +// List rawEnv = containerConfigBuilder.build().env(); +// if(rawEnv == null) { +// rawEnv = Collections.emptyList(); +// } +// +// Map env = EnvironmentUtils.listToMap(rawEnv); +// env.putAll(localEnv); +// +// List envList = EnvironmentUtils.mapToList(env); +// containerConfigBuilder.env(envList); +// ContainerConfig containerConfig = containerConfigBuilder.build(); +// +// DockerServiceDockerClient result = new DockerServiceDockerClient(dockerClient, containerConfig, null, hostMode, networks); +// return result; +// + + return new DockerServiceBuilderImpl<>(this, serviceSpec); + } + + + @Override + public DockerServiceDockerClient findServiceByName(String name) { + List containers; + try { + containers = dockerClient.listContainers(ListContainersParam.allContainers()); + } catch (DockerException | InterruptedException e) { + throw new RuntimeException(e); + } + + for (Container container : containers) { + List names = container.names(); + if(names.contains(name)) { + System.out.println("Got container with name: " + name); + } +// String containerId = container.names(); +// if(containerId.equals(id)) { +// if (imageName.equals(container.image())) { +// ContainerInfo containerInfo = dockerClient.inspectContainer(container.id()); +// if (containerInfo.state().running()) { +// } +// } + } + // TODO Auto-generated method stub + return null; + } + +// @Override +// public DockerServiceSpec newSpec() { +// return new DockerServiceSpecImpl(); +// } } diff --git a/docker-service-api-examples/pom.xml b/docker-service-api-examples/pom.xml index 4539bc3..15603cc 100644 --- a/docker-service-api-examples/pom.xml +++ b/docker-service-api-examples/pom.xml @@ -9,7 +9,7 @@ org.hobbit docker-service-api-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT diff --git a/docker-service-api-examples/src/main/java/org/hobbit/core/service/docker/example/MainDockerServiceExampleVirtuoso.java b/docker-service-api-examples/src/main/java/org/hobbit/core/service/docker/example/MainDockerServiceExampleVirtuoso.java index 9d41ec4..546221c 100644 --- a/docker-service-api-examples/src/main/java/org/hobbit/core/service/docker/example/MainDockerServiceExampleVirtuoso.java +++ b/docker-service-api-examples/src/main/java/org/hobbit/core/service/docker/example/MainDockerServiceExampleVirtuoso.java @@ -15,8 +15,8 @@ import org.apache.jena.riot.WebContent; import org.apache.jena.sparql.engine.http.QueryEngineHTTP; import org.hobbit.core.service.docker.api.DockerService; -import org.hobbit.core.service.docker.api.DockerServiceFactory; -import org.hobbit.core.service.docker.impl.docker_client.DockerServiceFactoryDockerClient; +import org.hobbit.core.service.docker.api.DockerServiceSystem; +import org.hobbit.core.service.docker.impl.docker_client.DockerServiceSystemDockerClient; import com.google.common.collect.ImmutableMap; import com.spotify.docker.client.exceptions.DockerCertificateException; @@ -24,9 +24,9 @@ public class MainDockerServiceExampleVirtuoso { public static void main(String[] args) throws DockerCertificateException, Exception { - try (DockerServiceFactory dsf = DockerServiceFactoryDockerClient.create(true, Collections.emptyMap(), Collections.emptySet())) { + try (DockerServiceSystem dss = DockerServiceSystemDockerClient.create(true, Collections.emptyMap(), Collections.emptySet())) { - DockerService ds = dsf.create("tenforce/virtuoso", ImmutableMap.builder() + DockerService ds = dss.create("docker-service-example", "tenforce/virtuoso", ImmutableMap.builder() .put("SPARQL_UPDATE", "true") .put("DEFAULT_GRAPH", "http://www.example.org/") .build()); @@ -41,6 +41,7 @@ public static void main(String[] args) throws DockerCertificateException, Except String sparqlApiBase = "http://" + ds.getContainerId() + ":8890/"; String sparqlEndpoint = sparqlApiBase + "sparql"; + dss.findServiceByName("docker-service-example"); try(RDFConnection rawConn = RDFConnectionFactory.connect(sparqlEndpoint)) { diff --git a/docker-service-api-spring-boot/pom.xml b/docker-service-api-spring-boot/pom.xml index dad63b6..ff06259 100644 --- a/docker-service-api-spring-boot/pom.xml +++ b/docker-service-api-spring-boot/pom.xml @@ -9,10 +9,11 @@ org.hobbit docker-service-api-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT + org.hobbit docker-service-api-core @@ -23,6 +24,15 @@ spring-boot + + org.springframework.boot + spring-boot-loader + + + org.springframework.boot + spring-boot-autoconfigure + + diff --git a/docker-service-api-spring-boot/src/main/java/org/hobbit/core/service/docker/impl/spring_boot/DockerServiceFactorySpringApplicationBuilder.java b/docker-service-api-spring-boot/src/main/java/org/hobbit/core/service/docker/impl/spring_boot/DockerServiceFactorySpringApplicationBuilder.java index 3c86e83..dbb1def 100644 --- a/docker-service-api-spring-boot/src/main/java/org/hobbit/core/service/docker/impl/spring_boot/DockerServiceFactorySpringApplicationBuilder.java +++ b/docker-service-api-spring-boot/src/main/java/org/hobbit/core/service/docker/impl/spring_boot/DockerServiceFactorySpringApplicationBuilder.java @@ -11,7 +11,9 @@ import org.hobbit.core.service.docker.api.DockerService; import org.hobbit.core.service.docker.api.DockerServiceFactory; -import org.hobbit.core.service.docker.impl.core.DockerServicePseudoDelegate; +import org.hobbit.core.service.docker.api.DockerServiceSpec; +import org.hobbit.core.service.docker.impl.core.DockerServiceWrapper; +import org.hobbit.core.service.docker.impl.core.DockerServiceSpecImpl; import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.MapPropertySource; @@ -63,8 +65,17 @@ public static SpringApplicationBuilder getParent(SpringApplicationBuilder appBui } @Override - public DockerService create(String imageName, Map env) { + public void close() throws Exception { + } + + @Override + public DockerService create(DockerServiceSpec serviceSpec) { + + //String containerName = serviceSpec.getContainerName(); + String imageName = serviceSpec.getImageName(); + Map localEnv = serviceSpec.getLocalEnvironment(); + Supplier imageConfigSupplier = imageNameToConfigSupplier.get(imageName); if(imageConfigSupplier == null) { throw new UnsupportedOperationException("No image '" + imageName + "' registered with this docker service factory"); @@ -75,7 +86,7 @@ public DockerService create(String imageName, Map env) { SpringApplicationBuilder appBuilder = imageConfigSupplier.get(); SpringApplicationBuilder rootBuilder = getRoot(appBuilder, DockerServiceFactorySpringApplicationBuilder::getParent); - Map env2 = env.entrySet().stream().collect(Collectors.toMap(Entry::getKey, x -> (Object)x.getValue())); + Map env2 = localEnv.entrySet().stream().collect(Collectors.toMap(Entry::getKey, x -> (Object)x.getValue())); ConfigurableEnvironment cenv = new StandardEnvironment(); cenv.getPropertySources().addFirst(new MapPropertySource("myPropertySource", env2)); @@ -88,13 +99,14 @@ public DockerService create(String imageName, Map env) { Service service = new ServiceSpringApplicationBuilder(imageName, appBuilder); - DockerService result = new DockerServicePseudoDelegate<>(service, imageName, idStrSupplier); + DockerService result = new DockerServiceWrapper<>(service, imageName, idStrSupplier); return result; } - @Override - public void close() throws Exception { - } +// @Override +// public DockerServiceSpec newSpec() { +// return new DockerServiceSpecImpl(); +// } } diff --git a/pom.xml b/pom.xml index 371fcb7..5039d06 100644 --- a/pom.xml +++ b/pom.xml @@ -6,16 +6,18 @@ org.hobbit docker-service-api-parent - 1.0.0-SNAPSHOT + 1.1.0-SNAPSHOT pom - 3.8.0 + 3.15.0 ${jena.version}-1-SNAPSHOT - 4.3.11.RELEASE + 1.7.25 + 2.1.6.RELEASE + UTF-8 1.8 1.8 @@ -34,6 +36,11 @@ + + org.aksw.commons + aksw-commons-utils + 0.9.7-SNAPSHOT + org.hobbit @@ -53,12 +60,17 @@ ${project.version} + + org.apache.jena + jena-arq + ${jena.version} + com.spotify docker-client - 8.9.0 + 8.15.1 ch.qos.logback @@ -70,22 +82,22 @@ org.springframework.boot spring-boot - 1.5.7.RELEASE + ${spring-boot.version} org.springframework.boot spring-boot-autoconfigure - 1.5.7.RELEASE + ${spring-boot.version} org.springframework.boot spring-boot-loader - 1.5.7.RELEASE + ${spring-boot.version} - + com.google.guava guava - 23.0 + 27.0.1-jre @@ -346,6 +358,7 @@ University Leipzig, AKSW Maven2 Repository http://maven.aksw.org/repository/snapshots +