diff --git a/CHANGELOG.md b/CHANGELOG.md index 3d949acc86..f6c8c90df7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,6 +27,7 @@ Usage: * Fix #2444: Add support for Spring Boot application properties placeholders * Fix #2456: Add utility class to decompress archive files * Fix #2472: Support for Helm Chart.yaml appVersion field defaulting to project version +* Fix #2474: Remove Docker-related classes providing unused functionality ### 1.15.0 (2023-11-10) * Fix #2138: Support for Spring Boot Native Image diff --git a/gradle-plugin/doc/src/main/asciidoc/inc/_groovy-configuration.adoc b/gradle-plugin/doc/src/main/asciidoc/inc/_groovy-configuration.adoc index bb9f9b65b4..12cf55f1ab 100644 --- a/gradle-plugin/doc/src/main/asciidoc/inc/_groovy-configuration.adoc +++ b/gradle-plugin/doc/src/main/asciidoc/inc/_groovy-configuration.adoc @@ -410,12 +410,6 @@ Defaults to `false`. | Boolean attribute for switching on verbose output like the build steps when doing a Docker build. Default is `false`. | `jkube.docker.verbose` -| *watchAutoCreateCustomNetworks* -| Whether to create the customs networks (user-defined bridge networks) before starting automatically - -Defaults to `false`. -| `jkube.watch.autoCreateCustomNetworks` - | *watchMode* a| How to watch for image changes. @@ -436,44 +430,12 @@ Defaults to `both`. Defaults to `5000`. | `jkube.watch.interval` -| *watchKeepRunning* -| If set to true all containers will be kept running after {goal-prefix}:watch has been stopped. - - Defaults to `false`. -| `jkube.watch.keepRunning` - | *watchPostExec* | A command which is executed within the container after files are copied into this container when watchMode is copy. Note that this container must be running. | `jkube.watch.postExec` -| *watchKeepContainer* -| If this is set to `false` (and `watchKeepRunning` is disabled) then all containers will be removed after -they have been stopped. - - Defaults to `false`. -| `jkube.watch.keepContainer` - -| *watchRemoveVolumes* -| If set to `true` remove any volumes associated with the container as well. - - This option will be ignored if either `watchKeepContainer` or `watchKeepRunning` is `true`. - - Defaults to `false`. -| `jkube.watch.removeVolumes` - -| *watchShowLogs* -| If set to `true`, logs will be shown for watched container. -| `jkube.watch.showLogs` - -| *watchFollow* -| If `watchShowLogs` is set to `false`, and there is a run image configuration, logs are followed -if set to `true`. - - Defaults to `false`. -| `jkube.watch.follow` - | *workDirectory* | The JKube working directory. Defaults to `${project.build.directory}/jkube-temp`. | `jkube.workDir` diff --git a/gradle-plugin/it/src/it/extension-configuration/build.gradle b/gradle-plugin/it/src/it/extension-configuration/build.gradle index 69a7750db6..bdebb28504 100644 --- a/gradle-plugin/it/src/it/extension-configuration/build.gradle +++ b/gradle-plugin/it/src/it/extension-configuration/build.gradle @@ -61,14 +61,7 @@ kubernetes { kubernetesTemplate = file('build/META-INF/jkube/kubernetes') watchMode = 'copy' watchInterval = 1000 - watchKeepRunning = true watchPostExec = 'ls -lt' - watchAutoCreateCustomNetworks = true - watchKeepContainer = true - watchRemoveVolumes = true - watchContainerNamePattern = '%g-%l' - watchFollow = true - watchShowLogs = 'true' access { namespace = 'default' } diff --git a/gradle-plugin/it/src/it/extension-configuration/expected/expected-config.yml b/gradle-plugin/it/src/it/extension-configuration/expected/expected-config.yml index 532ec47db0..d0d943c1ca 100644 --- a/gradle-plugin/it/src/it/extension-configuration/expected/expected-config.yml +++ b/gradle-plugin/it/src/it/extension-configuration/expected/expected-config.yml @@ -33,14 +33,7 @@ pushretries: 5 kubernetestemplate: "@endsWith('extension-configuration/build/META-INF/jkube/kubernetes')@" watchMode: "copy" watchinterval: 1000 -watchkeeprunning: true watchpostexec: "ls -lt" -watchautocreatecustomnetworks: true -watchkeepcontainer: true -watchremovevolumes: true -watchcontainernamepattern: "%g-%l" -watchfollow: true -watchshowlogs: "true" access: namespace: "default" enricher: @@ -79,12 +72,6 @@ images: dockerFileFile: "@endsWith('extension-configuration/src/main/context-dir/Dockerfile')@" dockerFileMode: true contextDirRaw: "@endsWith('extension-configuration/src/main/context-dir')@" - runConfiguration: - restartPolicy: - retry: 0 - networkingConfig: - standardNetwork: false - default: true buildConfiguration: contextDir: "@endsWith('extension-configuration/src/main/context-dir')@" dockerFile: "@endsWith('extension-configuration/src/main/context-dir/Dockerfile')@" diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/KubernetesExtension.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/KubernetesExtension.java index b3571a485d..5e59f97917 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/KubernetesExtension.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/KubernetesExtension.java @@ -24,7 +24,6 @@ import java.util.stream.Collectors; import org.eclipse.jkube.kit.build.service.docker.config.DockerMachineConfiguration; -import org.eclipse.jkube.kit.build.service.docker.helper.ContainerNamingUtil; import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.KitLogger; import org.eclipse.jkube.kit.common.ResourceFileType; @@ -241,24 +240,10 @@ public abstract class KubernetesExtension { public abstract Property getSkipBuild(); - public abstract Property getWatchKeepRunning(); - public abstract Property getWatchInterval(); public abstract Property getWatchPostExec(); - public abstract Property getWatchAutoCreateCustomNetworks(); - - public abstract Property getWatchKeepContainer(); - - public abstract Property getWatchRemoveVolumes(); - - public abstract Property getWatchFollow(); - - public abstract Property getWatchShowLogs(); - - public abstract Property getWatchContainerNamePattern(); - public WatchMode watchMode; public JKubeBuildStrategy buildStrategy; @@ -692,38 +677,10 @@ public Integer getWatchIntervalOrDefault() { return getOrDefaultInteger("jkube.watch.interval", this::getWatchInterval, 5000); } - public boolean getWatchKeepRunningOrDefault() { - return getOrDefaultBoolean("jkube.watch.keepRunning", this::getWatchKeepRunning, false); - } - public String getWatchPostExecOrNull() { return getOrDefaultString("jkube.watch.postExec", this::getWatchPostExec, null); } - public boolean getWatchAutoCreateCustomNetworksOrDefault() { - return getOrDefaultBoolean("jkube.watch.autoCreateCustomNetworks", this::getWatchAutoCreateCustomNetworks, false); - } - - public boolean getWatchKeepContainerOrDefault() { - return getOrDefaultBoolean("jkube.watch.keepContainer", this::getWatchKeepContainer, false); - } - - public boolean getWatchRemoveVolumesOrDefault() { - return getOrDefaultBoolean("jkube.watch.removeVolumes", this::getWatchRemoveVolumes, false); - } - - public String getWatchContainerNamePatternOrDefault() { - return getOrDefaultString("jkube.watch.containerNamePattern", this::getWatchContainerNamePattern, ContainerNamingUtil.DEFAULT_CONTAINER_NAME_PATTERN); - } - - public boolean getWatchFollowOrDefault() { - return getOrDefaultBoolean("jkube.watch.follow", this::getWatchFollow, false); - } - - public String getWatchShowLogsOrNull() { - return getOrDefaultString("jkube.watch.showLogs", this::getWatchShowLogs, null); - } - protected boolean getOrDefaultBoolean(String property, Supplier> dslGetter, boolean defaultValue) { return getOrDefault(property, Boolean::parseBoolean, dslGetter, defaultValue); } diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/AbstractJKubeTask.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/AbstractJKubeTask.java index 25abd4a65d..c5b41861e7 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/AbstractJKubeTask.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/AbstractJKubeTask.java @@ -27,7 +27,6 @@ import org.eclipse.jkube.gradle.plugin.GradleLogger; import org.eclipse.jkube.gradle.plugin.GradleUtil; import org.eclipse.jkube.gradle.plugin.KubernetesExtension; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; import org.eclipse.jkube.kit.build.service.docker.config.handler.ImageConfigResolver; import org.eclipse.jkube.kit.common.JKubeConfiguration; import org.eclipse.jkube.kit.common.KitLogger; @@ -60,7 +59,6 @@ public abstract class AbstractJKubeTask extends DefaultTask implements Kubernete protected final KubernetesExtension kubernetesExtension; protected KitLogger kitLogger; - protected LogOutputSpecFactory logOutputSpecFactory; protected ClusterAccess clusterAccess; protected JKubeServiceHub jKubeServiceHub; protected static final String DOCKER_BUILD_TIMESTAMP = "docker/build.timestamp"; @@ -84,8 +82,6 @@ public final void runTask() { private void init() { kubernetesExtension.javaProject = GradleUtil.convertGradleProject(getProject()); kitLogger = createLogger(null); - logOutputSpecFactory = new LogOutputSpecFactory(isAnsiEnabled(), kubernetesExtension.getLogStdoutOrDefault(), - kubernetesExtension.getLogDateOrNull()); clusterAccess = new ClusterAccess(initClusterConfiguration()); jKubeServiceHub = initJKubeServiceHubBuilder().build(); kubernetesExtension.resources = updateResourceConfigNamespace(kubernetesExtension.getNamespaceOrNull(), kubernetesExtension.resources); diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesBuildTask.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesBuildTask.java index 88ed2d9c42..4e0258bcd8 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesBuildTask.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesBuildTask.java @@ -43,8 +43,7 @@ public KubernetesBuildTask(Class extensionClass) @Override protected JKubeServiceHub.JKubeServiceHubBuilder initJKubeServiceHubBuilder() { return super.initJKubeServiceHubBuilder() - .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger), - logOutputSpecFactory)) + .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger))) .buildServiceConfig(buildServiceConfigBuilder().build()); } diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesPushTask.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesPushTask.java index f429bed210..bac44b573c 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesPushTask.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesPushTask.java @@ -33,8 +33,7 @@ public KubernetesPushTask(Class extensionClass) { @Override protected JKubeServiceHub.JKubeServiceHubBuilder initJKubeServiceHubBuilder() { return super.initJKubeServiceHubBuilder() - .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger), - logOutputSpecFactory)) + .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger))) .buildServiceConfig(buildServiceConfigBuilder().build()); } diff --git a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesWatchTask.java b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesWatchTask.java index 7dc6686a87..a26f00cdcf 100644 --- a/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesWatchTask.java +++ b/gradle-plugin/kubernetes/src/main/java/org/eclipse/jkube/gradle/plugin/task/KubernetesWatchTask.java @@ -19,7 +19,6 @@ import org.eclipse.jkube.gradle.plugin.KubernetesExtension; import org.eclipse.jkube.kit.build.core.GavLabel; import org.eclipse.jkube.kit.build.service.docker.DockerServiceHub; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogDispatcher; import org.eclipse.jkube.kit.build.service.docker.watch.WatchContext; import org.eclipse.jkube.kit.common.util.KubernetesHelper; import org.eclipse.jkube.kit.common.util.ResourceUtil; @@ -48,8 +47,7 @@ public KubernetesWatchTask(Class extensionClass) @Override protected JKubeServiceHub.JKubeServiceHubBuilder initJKubeServiceHubBuilder() { return super.initJKubeServiceHubBuilder() - .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger), - logOutputSpecFactory)) + .dockerServiceHub(DockerServiceHub.newInstance(kitLogger, TaskUtil.initDockerAccess(kubernetesExtension, kitLogger))) .buildServiceConfig(TaskUtil.buildServiceConfigBuilder(kubernetesExtension).build()); } @@ -103,19 +101,10 @@ private WatchContext getWatchContext() throws IOException { .watchInterval(kubernetesExtension.getWatchIntervalOrDefault()) .watchMode(kubernetesExtension.getWatchModeOrDefault()) .watchPostExec(kubernetesExtension.getWatchPostExecOrNull()) - .autoCreateCustomNetworks(kubernetesExtension.getWatchAutoCreateCustomNetworksOrDefault()) - .keepContainer(kubernetesExtension.getWatchKeepContainerOrDefault()) - .keepRunning(kubernetesExtension.getWatchKeepRunningOrDefault()) - .removeVolumes(kubernetesExtension.getWatchRemoveVolumesOrDefault()) - .containerNamePattern(kubernetesExtension.getWatchContainerNamePatternOrDefault()) .buildTimestamp(getBuildTimestamp(null, null, kubernetesExtension.javaProject.getBuildDirectory().getAbsolutePath(), DOCKER_BUILD_TIMESTAMP)) .gavLabel(new GavLabel(kubernetesExtension.javaProject.getGroupId(), kubernetesExtension.javaProject.getArtifactId(), kubernetesExtension.javaProject.getVersion())) .buildContext(jKubeServiceHub.getConfiguration()) - .follow(kubernetesExtension.getWatchFollowOrDefault()) - .showLogs(kubernetesExtension.getWatchShowLogsOrNull()) - .logOutputSpecFactory(logOutputSpecFactory) .hub(hub) - .dispatcher(new LogDispatcher(hub.getDockerAccess())) .build(); } } diff --git a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/KubernetesExtensionPropertyTest.java b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/KubernetesExtensionPropertyTest.java index 862b17b7dd..3c5c293cdd 100644 --- a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/KubernetesExtensionPropertyTest.java +++ b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/KubernetesExtensionPropertyTest.java @@ -17,7 +17,6 @@ import java.nio.file.Paths; import java.util.stream.Stream; -import org.eclipse.jkube.kit.build.service.docker.helper.ContainerNamingUtil; import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.ResourceFileType; @@ -117,14 +116,7 @@ static Stream defaultValues() { arguments("getKubernetesTemplateOrDefault", new File(BASE, "build").toPath().resolve(Paths.get("META-INF", "jkube", "kubernetes")).toFile()), arguments("getWatchModeOrDefault", WatchMode.both), arguments("getWatchIntervalOrDefault", 5000), - arguments("getWatchKeepRunningOrDefault", false), - arguments("getWatchPostExecOrNull", null), - arguments("getWatchAutoCreateCustomNetworksOrDefault", false), - arguments("getWatchKeepContainerOrDefault", false), - arguments("getWatchRemoveVolumesOrDefault", false), - arguments("getWatchContainerNamePatternOrDefault", ContainerNamingUtil.DEFAULT_CONTAINER_NAME_PATTERN), - arguments("getWatchFollowOrDefault", false), - arguments("getWatchShowLogsOrNull", null)); + arguments("getWatchPostExecOrNull", null)); } @ParameterizedTest(name = "{index}: {0} with property ''{1}={2}'' returns ''{3}''") @@ -213,13 +205,6 @@ static Stream propertiesAndValues() { Paths.get("META-INF", "jkube", "other").toFile()), arguments("getWatchModeOrDefault", "jkube.watch.mode", "copy", WatchMode.copy), arguments("getWatchIntervalOrDefault", "jkube.watch.interval", "10000", 10000), - arguments("getWatchKeepRunningOrDefault", "jkube.watch.keepRunning", "true", true), - arguments("getWatchPostExecOrNull", "jkube.watch.postExec", "ls -lt", "ls -lt"), - arguments("getWatchAutoCreateCustomNetworksOrDefault", "jkube.watch.autoCreateCustomNetworks", "true", true), - arguments("getWatchKeepContainerOrDefault", "jkube.watch.keepContainer", "true", true), - arguments("getWatchRemoveVolumesOrDefault", "jkube.watch.removeVolumes", "true", true), - arguments("getWatchContainerNamePatternOrDefault", "jkube.watch.containerNamePattern", "%n-%g", "%n-%g"), - arguments("getWatchFollowOrDefault", "jkube.watch.follow", "true", true), - arguments("getWatchShowLogsOrNull", "jkube.watch.showLogs", "true", "true")); + arguments("getWatchPostExecOrNull", "jkube.watch.postExec", "ls -lt", "ls -lt")); } } diff --git a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/TestKubernetesExtension.java b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/TestKubernetesExtension.java index 051bd8fbcb..5e562cf084 100644 --- a/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/TestKubernetesExtension.java +++ b/gradle-plugin/kubernetes/src/test/java/org/eclipse/jkube/gradle/plugin/TestKubernetesExtension.java @@ -338,11 +338,6 @@ public Property getSkipResource() { return property(Boolean.class); } - @Override - public Property getWatchKeepRunning() { - return property(Boolean.class); - } - @Override public Property getSkipBuild() { return property(Boolean.class); @@ -358,36 +353,6 @@ public Property getWatchPostExec() { return property(String.class); } - @Override - public Property getWatchAutoCreateCustomNetworks() { - return property(Boolean.class); - } - - @Override - public Property getWatchKeepContainer() { - return property(Boolean.class); - } - - @Override - public Property getWatchRemoveVolumes() { - return property(Boolean.class); - } - - @Override - public Property getWatchFollow() { - return property(Boolean.class); - } - - @Override - public Property getWatchShowLogs() { - return property(String.class); - } - - @Override - public Property getWatchContainerNamePattern() { - return property(String.class); - } - public static Property property(Class type) { return new DefaultProperty<>(PropertyHost.NO_OP, type); } diff --git a/gradle-plugin/openshift/src/test/java/org/eclipse/jkube/gradle/plugin/TestOpenShiftExtension.java b/gradle-plugin/openshift/src/test/java/org/eclipse/jkube/gradle/plugin/TestOpenShiftExtension.java index 5592b12aa2..ead89f8c75 100644 --- a/gradle-plugin/openshift/src/test/java/org/eclipse/jkube/gradle/plugin/TestOpenShiftExtension.java +++ b/gradle-plugin/openshift/src/test/java/org/eclipse/jkube/gradle/plugin/TestOpenShiftExtension.java @@ -365,11 +365,6 @@ public Property getSkipResource() { return property(Boolean.class); } - @Override - public Property getWatchKeepRunning() { - return property(Boolean.class); - } - @Override public Property getSkipBuild() { return property(Boolean.class); @@ -385,36 +380,6 @@ public Property getWatchPostExec() { return property(String.class); } - @Override - public Property getWatchAutoCreateCustomNetworks() { - return property(Boolean.class); - } - - @Override - public Property getWatchKeepContainer() { - return property(Boolean.class); - } - - @Override - public Property getWatchRemoveVolumes() { - return property(Boolean.class); - } - - @Override - public Property getWatchFollow() { - return property(Boolean.class); - } - - @Override - public Property getWatchShowLogs() { - return property(String.class); - } - - @Override - public Property getWatchContainerNamePattern() { - return property(String.class); - } - public static Property property(Class type) { return new DefaultProperty<>(PropertyHost.NO_OP, type); } diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/RegistryContext.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/RegistryContext.java deleted file mode 100644 index 52895837c7..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/RegistryContext.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api; - -import java.io.IOException; - -import org.eclipse.jkube.kit.build.api.auth.AuthConfig; -import org.eclipse.jkube.kit.build.api.auth.RegistryAuthConfig; -import org.eclipse.jkube.kit.config.image.build.ImagePullPolicy; - -/** - * @author roland - * @since 17.10.18 - */ -public interface RegistryContext { - - ImagePullPolicy getDefaultImagePullPolicy(); - - String getRegistry(RegistryAuthConfig.Kind kind); - - AuthConfig getAuthConfig(RegistryAuthConfig.Kind kind, String user, String registry) throws IOException; - -} diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Container.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Container.java deleted file mode 100644 index c8d8ce1726..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Container.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import java.util.Map; - -/** - * Interface representing a container - * - * @author roland - * @since 16/07/15 - */ -public interface Container { - - long getCreated(); - - String getId(); - - String getImage(); - - Map getLabels(); - - String getName(); - - String getNetworkMode(); - - Map getPortBindings(); - - boolean isRunning(); - - /** - * IP Address of the container if provided - * - * @return the IP address of the container or null if not provided. - */ - String getIPAddress(); - - /** - * Return IP Addresses of custom networks, mapped to the network name as the key. - * @return The mapping of network names to IP addresses, or null if none provided. - */ - Map getCustomNetworkIpAddresses(); - - /** - * Exit code of the container if it already has excited - * - * @return exit code if the container has excited, null if it is still running. Also null, - * if the implementation doesn't support an exit code. - */ - Integer getExitCode(); - - class PortBinding { - private final String hostIp; - private final Integer hostPort; - - public PortBinding(Integer hostPort, String hostIp) { - this.hostPort = hostPort; - this.hostIp = hostIp; - } - - public String getHostIp() { - return hostIp; - } - - public Integer getHostPort() { - return hostPort; - } - } -} - - diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainerDetails.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainerDetails.java deleted file mode 100644 index 421393bb2f..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainerDetails.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import java.time.Instant; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; - -import com.google.common.base.Joiner; -import com.google.gson.JsonObject; - - -public class ContainerDetails implements Container { - - static final String CONFIG = "Config"; - static final String CREATED = "Created"; - static final String HOST_IP = "HostIp"; - static final String HOST_PORT = "HostPort"; - static final String ID = "Id"; - static final String IMAGE = "Image"; - static final String LABELS = "Labels"; - static final String NAME = "Name"; - static final String IP = "IPAddress"; - static final String HOST_CONFIG = "HostConfig"; - static final String NETWORK_MODE = "NetworkMode"; - static final String NETWORK_SETTINGS = "NetworkSettings"; - static final String NETWORKS = "Networks"; - static final String PORTS = "Ports"; - static final String SLASH = "/"; - static final String STATE = "State"; - static final String HEALTH = "Health"; - static final String STATUS = "Status"; - static final String HEALTH_STATUS_HEALTHY = "healthy"; - static final String HEALTHCHECK = "Healthcheck"; - static final String TEST = "Test"; - - private static final String EXIT_CODE = "ExitCode"; - private static final String RUNNING = "Running"; - - private final JsonObject json; - - public ContainerDetails(JsonObject json) { - this.json = json; - } - - @Override - public long getCreated() { - String date = json.get(CREATED).getAsString(); - Instant instant = Instant.parse(date); - return instant.toEpochMilli(); - } - - @Override - public String getId() { - // only need first 12 to id a container - return json.get(ID).getAsString().substring(0, 12); - } - - @Override - public String getImage() { - // ID: json.getString("Image"); - return json.getAsJsonObject(CONFIG).get(IMAGE).getAsString(); - } - - @Override - public Map getLabels() { - JsonObject config = json.getAsJsonObject(CONFIG); - return config.has(LABELS) ? - mapLabels(config.getAsJsonObject(LABELS)) : - Collections.emptyMap(); - } - - @Override - public String getName() { - String name = json.get(NAME).getAsString(); - - if (name.startsWith(SLASH)) { - name = name.substring(1); - } - return name; - } - - @Override - public String getIPAddress() { - if (json.has(NETWORK_SETTINGS) && !json.get(NETWORK_SETTINGS).isJsonNull()) { - JsonObject networkSettings = json.getAsJsonObject(NETWORK_SETTINGS); - if (!networkSettings.get(IP).isJsonNull()) { - return networkSettings.get(IP).getAsString(); - } - } - return null; - } - - @Override - public String getNetworkMode() { - if (json.has(HOST_CONFIG) && !json.get(HOST_CONFIG).isJsonNull()) { - final JsonObject hostConfig = json.getAsJsonObject(HOST_CONFIG); - if (!hostConfig.get(NETWORK_MODE).isJsonNull()) { - return hostConfig.get(NETWORK_MODE).getAsString(); - } - } - return null; - } - - @Override - public Map getCustomNetworkIpAddresses() { - if (json.has(NETWORK_SETTINGS) && !json.get(NETWORK_SETTINGS).isJsonNull()) { - JsonObject networkSettings = json.getAsJsonObject(NETWORK_SETTINGS); - if (networkSettings.has(NETWORKS) && !networkSettings.get(NETWORKS).isJsonNull()) { - return extractNetworks(networkSettings); - } - } - return null; - } - - private Map extractNetworks(JsonObject networkSettings) { - JsonObject networks = networkSettings.getAsJsonObject(NETWORKS); - Set keys = networks.keySet(); - if (keys == null || keys.isEmpty()) { - return null; - } - Map results = new HashMap<>(); - for (String key : keys) { - JsonObject net = networks.getAsJsonObject(key); - if (net.has(IP) && !net.get(IP).isJsonNull()) { - results.put(key, net.get(IP).getAsString()); - } - } - - return results; - } - - @Override - public Map getPortBindings() { - if (json.has(NETWORK_SETTINGS) && !json.get(NETWORK_SETTINGS).isJsonNull()) { - JsonObject networkSettings = json.getAsJsonObject(NETWORK_SETTINGS); - if (networkSettings.has(PORTS) && !networkSettings.get(PORTS).isJsonNull()) { - return createPortBindings(networkSettings.getAsJsonObject(PORTS)); - } - } - - return new HashMap<>(); - } - - @Override - public boolean isRunning() { - JsonObject state = json.getAsJsonObject(STATE); - return state.get(RUNNING).getAsBoolean(); - } - - @Override - public Integer getExitCode() { - if (isRunning()) { - return null; - } - JsonObject state = json.getAsJsonObject(STATE); - return state.get(EXIT_CODE).getAsInt(); - } - - public boolean isHealthy() { - final JsonObject state = json.getAsJsonObject(STATE); - // always indicate healthy for docker hosts that do not support health checks. - return !state.has(HEALTH) || HEALTH_STATUS_HEALTHY.equals(state.getAsJsonObject(HEALTH).get(STATUS).getAsString()); - } - - public String getHealthcheck() { - if (!json.getAsJsonObject(CONFIG).has(HEALTHCHECK) || - !json.getAsJsonObject(CONFIG).getAsJsonObject(HEALTHCHECK).has(TEST)) { - return null; - } - - return Joiner.on(", ").join(json.getAsJsonObject(CONFIG).getAsJsonObject(HEALTHCHECK).getAsJsonArray(TEST)); - } - - private void addPortMapping(String port, JsonObject hostConfig, Map portBindings) { - String hostIp = hostConfig.get(HOST_IP).getAsString(); - Integer hostPort = Integer.valueOf(hostConfig.get(HOST_PORT).getAsInt()); - - addPortMapping(port, new PortBinding(hostPort, hostIp), portBindings); - } - - private void addPortMapping(String port, PortBinding binding, Map portBindings) { - if (port.indexOf('/') == -1) { - port = port + "/tcp"; - } - - portBindings.put(port, binding); - } - - private Map createPortBindings(JsonObject ports) { - Map portBindings = new HashMap<>(); - - for (Object obj : ports.keySet()) { - String port = obj.toString(); - if (ports.get(port).isJsonNull()) { - addPortMapping(port, (PortBinding) null, portBindings); - } else { - // use the first entry in the array - JsonObject hostConfig = ports.getAsJsonArray(port).get(0).getAsJsonObject(); - addPortMapping(port, hostConfig, portBindings); - } - } - - return portBindings; - } - - private Map mapLabels(JsonObject labels) { - int length = labels.size(); - Map mapped = new HashMap<>(length); - - Iterator iterator = labels.keySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - mapped.put(key, labels.get(key).getAsString()); - } - - return mapped; - } -} - diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainersListElement.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainersListElement.java deleted file mode 100644 index 485b349fbb..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ContainersListElement.java +++ /dev/null @@ -1,169 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; - -public class ContainersListElement implements Container { - - static final String CREATED = "Created"; - static final String ID = "Id"; - static final String IMAGE = "Image"; - static final String IP = "IP"; - static final String LABELS = "Labels"; - static final String PORTS = "Ports"; - static final String PUBLIC_PORT = "PublicPort"; - static final String STATUS = "Status"; - static final String TYPE = "Type"; - - private static final String NAMES = "Names"; - private static final String PRIVATE_PORT = "PrivatePort"; - private static final String SLASH = "/"; - private static final String UP = "up"; - - private final JsonObject json; - - public ContainersListElement(JsonObject json) { - this.json = json; - } - - @Override - public long getCreated() { - return json.get(CREATED).getAsLong(); - } - - @Override - public String getId() { - // only need first 12 to id a container - return json.get(ID).getAsString().substring(0, 12); - } - - @Override - public String getImage() { - return json.get(IMAGE).getAsString(); - } - - @Override - public Map getLabels() { - if (!json.has(LABELS) || json.get(LABELS).isJsonNull()) { - return Collections.emptyMap(); - } - - return mapLabels(json.getAsJsonObject(LABELS)); - } - - @Override - public String getName() { - if (json.has(NAMES)) { - JsonArray names = json.getAsJsonArray(NAMES); - for (int i = 0; i < names.size(); i++) { - String name = names.get(i).getAsString(); - if (name.startsWith(SLASH)) { - name = name.substring(1); - } - if (!name.contains(SLASH)) { - return name; - } - } - // this should never happen - throw new IllegalStateException("Unable to determine container name from 'Names' " + names); - } else { - throw new UnsupportedOperationException("Missing 'Names' attribute from a container list element " + json); - } - } - - @Override - public String getNetworkMode() { - // HostConfig.NetworkMode is not provided by container list action. - return null; - } - - @Override - public Map getPortBindings() { - if (json.get(PORTS).isJsonNull()) { - return Collections.emptyMap(); - } - - return mapPortBindings(json.getAsJsonArray(PORTS)); - } - - @Override - public String getIPAddress() { - // IP address is not provided by container list action. - return null; - } - - @Override - public Map getCustomNetworkIpAddresses() { - // IP address is not provided by container list action. - return null; - } - - @Override - public boolean isRunning() { - String status = json.get(STATUS).getAsString(); - return status.toLowerCase().contains(UP); - } - - @Override - public Integer getExitCode() { - // exit code is not provided by container list action. - return null; - } - - private PortBinding createPortBinding(JsonObject object) { - PortBinding binding = null; - - if (object.has(PUBLIC_PORT) && object.has(IP)) { - binding = new PortBinding(object.get(PUBLIC_PORT).getAsInt(), object.get(IP).getAsString()); - } - - return binding; - } - - private String createPortKey(JsonObject object) { - return String.format("%s/%s", object.get(PRIVATE_PORT).getAsInt(), object.get(TYPE).getAsString()); - } - - private Map mapLabels(JsonObject labels) { - int length = labels.size(); - Map mapped = new HashMap<>(length); - - Iterator iterator = labels.keySet().iterator(); - while (iterator.hasNext()) { - String key = iterator.next(); - mapped.put(key, labels.get(key).getAsString()); - } - - return mapped; - } - - private Map mapPortBindings(JsonArray ports) { - int length = ports.size(); - Map portBindings = new HashMap<>(length); - - for (int i = 0; i < length; i++) { - JsonObject object = ports.get(i).getAsJsonObject(); - portBindings.put(createPortKey(object), createPortBinding(object)); - } - - return portBindings; - } -} diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ExecDetails.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ExecDetails.java deleted file mode 100644 index 471c083d65..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/ExecDetails.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; - -/** - * Model class holding details of the result of an exec command on a running container. - */ -public class ExecDetails { - private static final String EXIT_CODE = "ExitCode"; - private static final String RUNNING = "Running"; - private static final String ENTRY_POINT = "entrypoint"; - private static final String ARGUMENTS = "arguments"; - - private static final String PROCESS_CONFIG = "ProcessConfig"; - - private final JsonObject json; - - public ExecDetails(JsonObject json) { - this.json = json; - } - - public boolean isRunning() { - return json.get(RUNNING).getAsBoolean(); - } - - public Integer getExitCode() { - if (isRunning()) { - return null; - } - return json.get(EXIT_CODE).getAsInt(); - } - - public String getEntryPoint() { - if (!json.has(PROCESS_CONFIG)) { - return null; - } - - JsonObject processConfig = json.getAsJsonObject(PROCESS_CONFIG); - if (!processConfig.has(ENTRY_POINT)) { - return null; - } - - return processConfig.get(ENTRY_POINT).getAsString(); - } - - public String[] getArguments() { - if (!json.has(PROCESS_CONFIG)) { - return null; - } - JsonObject processConfig = json.getAsJsonObject(PROCESS_CONFIG); - if (!processConfig.has(ARGUMENTS)) { - return null; - } - JsonArray arguments = processConfig.getAsJsonArray(ARGUMENTS); - String[] result = new String[arguments.size()]; - for (int i = 0; i < arguments.size(); i++) { - result[i] = arguments.get(i).getAsString(); - } - return result; - } -} - diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Network.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Network.java deleted file mode 100644 index 08151d72d3..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/Network.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -public interface Network { - - String getName(); - - String getId(); - - String getScope(); - - String getDriver(); - -} - diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworkCreateConfig.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworkCreateConfig.java deleted file mode 100644 index 4fd8123dbd..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworkCreateConfig.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import com.google.gson.JsonObject; - -public class NetworkCreateConfig { - final JsonObject createConfig = new JsonObject(); - final String name; - - public NetworkCreateConfig(String name) { - this.name = name; - createConfig.addProperty("Name", name); - } - - public String getName() { - return name; - } - - /** - * Get JSON which is used for creating a network - * - * @return string representation for JSON representing creating a network - */ - public String toJson() { - return createConfig.toString(); - } -} - diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworksListElement.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworksListElement.java deleted file mode 100644 index b53eded5e1..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/NetworksListElement.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import com.google.gson.JsonObject; - -public class NetworksListElement implements Network { - - static final String NAME = "Name"; - static final String ID = "Id"; - static final String SCOPE = "Scope"; - static final String DRIVER = "Driver"; - - private final JsonObject json; - - public NetworksListElement(JsonObject json) { - this.json = json; - } - - @Override - public String getName() { - return json.get(NAME).getAsString(); - } - - @Override - public String getDriver() { - return json.get(DRIVER).getAsString(); - } - - @Override - public String getScope() { - return json.get(SCOPE).getAsString(); - } - - @Override - public String getId() { - // only need first 12 to id a network - return json.get(ID).getAsString().substring(0, 12); - } - -} diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/PortMapping.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/PortMapping.java index 93f7e77ca3..0dbe308256 100644 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/PortMapping.java +++ b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/PortMapping.java @@ -17,17 +17,12 @@ import com.google.gson.JsonObject; import org.eclipse.jkube.kit.common.util.EnvUtil; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStream; import java.net.InetAddress; import java.net.UnknownHostException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.Set; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,12 +44,6 @@ public class PortMapping { // ports map (container port -> host port) private final Map containerPortToHostPort = new HashMap<>(); - // resolved dynamic properties - private final Properties dynamicProperties = new Properties(); - - // Mapping between property name and host ip (ip filled in after container creation) - private final Map hostIpVariableMap = new HashMap<>(); - // Mapping between property name and host port (port filled in after container creation) private final Map hostPortVariableMap = new HashMap<>(); @@ -74,7 +63,7 @@ public class PortMapping { *
  • The "host_ip" part is optional. If not given, the all interfaces are used
  • *
  • If "host_port" is non numeric it is taken as a variable name. If this variable is given as value in * variables, this number is used as host port. If no numeric value is given, it is considered to be filled with the - * real, dynamically created port value when {@link #updateProperties(Map)} is called
  • + * real, dynamically created port value when #updateProperties(Map) is called * * * @param portMappings a list of configuration strings where each string hast the format @@ -90,85 +79,6 @@ public PortMapping(List portMappings, Properties projProperties) { } } - /** - * Check whether property needs updates for dynamically obtained host ports and ip adresses. - * - * @return true if any property are used which need to be filled in, false otherwise - */ - public boolean needsPropertiesUpdate() { - return !specToHostPortVariableMap.isEmpty() || !specToHostIpVariableMap.isEmpty(); - } - - /** - * @return Set of all mapped container ports - */ - public Set getContainerPorts() { - return containerPortToHostPort.keySet(); - } - - /** - * Update variable-to-port mappings with dynamically obtained ports and host ips. - * This should only be called once after this dynamically allocated parts has been be obtained. - * - * @param dockerObtainedDynamicBindings keys are the container ports, values are the dynamically mapped host ports and host ips. - */ - public void updateProperties(Map dockerObtainedDynamicBindings) { - for (Map.Entry entry : dockerObtainedDynamicBindings.entrySet()) { - String variable = entry.getKey(); - Container.PortBinding portBinding = entry.getValue(); - - if (portBinding != null) { - update(hostPortVariableMap, specToHostPortVariableMap.get(variable), portBinding.getHostPort()); - - String hostIp = portBinding.getHostIp(); - - // Use the docker host if binding is on all interfaces - if ("0.0.0.0".equals(hostIp)) { - hostIp = projProperties.getProperty("docker.host.address"); - } - - update(hostIpVariableMap, specToHostIpVariableMap.get(variable), hostIp); - } - } - - updateDynamicProperties(hostPortVariableMap); - updateDynamicProperties(hostIpVariableMap); - } - - /** - * Create a JSON specification which can be used to in a Docker API request as the 'PortBindings' part - * for creating container. - * - * @return 'PortBindings' object or null if no port mappings are used. - */ - public JsonObject toDockerPortBindingsJson() { - Map portMap = getContainerPortToHostPortMap(); - if (!portMap.isEmpty()) { - JsonObject portBindings = new JsonObject(); - Map bindToMap = getBindToHostMap(); - - for (Map.Entry entry : portMap.entrySet()) { - String containerPortSpec = entry.getKey(); - Integer hostPort = entry.getValue(); - - JsonObject o = new JsonObject(); - o.addProperty("HostPort", hostPort != null ? hostPort.toString() : ""); - - if (bindToMap.containsKey(containerPortSpec)) { - o.addProperty("HostIp", bindToMap.get(containerPortSpec)); - } - - JsonArray array = new JsonArray(); - array.add(o); - - portBindings.add(containerPortSpec, array); - } - return portBindings; - } else { - return null; - } - } - /** * Return the content of the mapping as an array with all specifications as given * @@ -225,20 +135,6 @@ Map getContainerPortToHostPortMap() { return containerPortToHostPort; } - // visible for testing - Map getHostIpVariableMap() { - return hostIpVariableMap; - } - - // visible for testing - Map getHostPortVariableMap() { - return hostPortVariableMap; - } - - // visible for testing - Map getPortsMap() { - return containerPortToHostPort; - } private IllegalArgumentException createInvalidMappingError(String mapping, Exception exp) { return new IllegalArgumentException("\nInvalid port mapping '" + mapping + "'\n" + @@ -361,65 +257,5 @@ private String resolveHostname(String bindToHost) { } } - private void update(Map map, String key, T value) { - if (key != null) { - map.put(key, value); - } - } - - private void updateDynamicProperties(Map dynamicPorts) { - for (Map.Entry entry : dynamicPorts.entrySet()) { - String entryKey = entry.getKey(); - String val = entry.getValue().toString(); - - projProperties.setProperty(entryKey, val); - dynamicProperties.setProperty(entryKey, val); - } - } - - - public static class PropertyWriteHelper { - - private final Properties globalExport; - - private final String globalFile; - private final Map toExport; - - public PropertyWriteHelper(String globalFile) { - this.globalFile = globalFile; - - this.toExport = new HashMap<>(); - this.globalExport = new Properties(); - } - - public void add(PortMapping portMapping, String portPropertyFile) { - if (portPropertyFile != null) { - toExport.put(portPropertyFile, portMapping.dynamicProperties); - } else if (globalFile != null) { - globalExport.putAll(portMapping.dynamicProperties); - } - } - - public void write() throws IOException { - for (Map.Entry entry : toExport.entrySet()) { - Properties props = entry.getValue(); - writeProperties(props, entry.getKey()); - globalExport.putAll(props); - } - - if (globalFile != null && !globalExport.isEmpty()) { - writeProperties(globalExport, globalFile); - } - } - - private void writeProperties(Properties props, String file) throws IOException { - File propFile = new File(file); - try (OutputStream os = new FileOutputStream(propFile)) { - props.store(os, "Docker ports"); - } catch (IOException e) { - throw new IOException("Cannot write properties to " + file + ": " + e, e); - } - } - } } diff --git a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/VolumeCreateConfig.java b/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/VolumeCreateConfig.java deleted file mode 100644 index 3c487064b9..0000000000 --- a/jkube-kit/build/api/src/main/java/org/eclipse/jkube/kit/build/api/model/VolumeCreateConfig.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.api.model; - -import com.google.gson.JsonObject; -import org.eclipse.jkube.kit.common.JsonFactory; - -import java.util.Map; - - -public class VolumeCreateConfig -{ - private final JsonObject createConfig = new JsonObject(); - - public VolumeCreateConfig(String name) { - add("Name", name); - } - - public VolumeCreateConfig driver(String driver) { - return add("Driver", driver); - } - - public VolumeCreateConfig opts(Map opts) { - if (opts != null && opts.size() > 0) { - add("DriverOpts", JsonFactory.newJsonObject(opts)); - } - return this; - } - - public VolumeCreateConfig labels(Map labels) { - if (labels != null && labels.size() > 0) { - add("Labels", JsonFactory.newJsonObject(labels)); - } - return this; - } - - public String getName() { - return createConfig.get("Name").getAsString(); - } - - /** - * Get JSON which is used for creating a volume - * - * @return string representation for JSON representing creating a volume - */ - public String toJson() { - return createConfig.toString(); - } - - // ======================================================================= - - private VolumeCreateConfig add(String name, JsonObject value) { - if (value != null) { - createConfig.add(name, value); - } - return this; - } - - private VolumeCreateConfig add(String name, String value) { - if (value != null) { - createConfig.addProperty(name, value); - } - return this; - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ArchiveService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ArchiveService.java index 6c1d0bce0e..bea150d6fb 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ArchiveService.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ArchiveService.java @@ -39,20 +39,6 @@ public ArchiveService(AssemblyManager assemblyManager, KitLogger log) { this.assemblyManager = assemblyManager; } - /** - * Create the tar file container the source for building an image. This tar can be used directly for - * uploading to a Docker daemon for creating the image - * - * @param imageConfig the image configuration - * @param params mojo params for the project - * @return file for holding the sources - * @throws IOException if during creation of the tar an error occurs. - */ - public File createDockerBuildArchive(ImageConfiguration imageConfig, JKubeConfiguration params) - throws IOException { - return createDockerBuildArchive(imageConfig, params, null); - } - /** * Create the tar file container the source for building an image. This tar can be used directly for * uploading to a Docker daemon for creating the image diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ContainerTracker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ContainerTracker.java deleted file mode 100644 index 5c3da2be12..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ContainerTracker.java +++ /dev/null @@ -1,275 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker; - -import java.util.*; - -import org.eclipse.jkube.kit.build.core.GavLabel; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.WaitConfiguration; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; - -/** - * Tracker class for tracking started containers so that they can be shut down at the end when - * docker:start and docker:stop are used in the same run - */ -public class ContainerTracker { - - private static class ContainerTrackerHolder { - public static final ContainerTracker INSTANCE = new ContainerTracker(); - } - - public static ContainerTracker getInstance() { - return ContainerTracker.ContainerTrackerHolder.INSTANCE; - } - - // Map holding associations between started containers and their images via name and aliases - // Key: Image, Value: Container - private final Map imageToContainerMap = new HashMap<>(); - - // Key: Alias, Value: container - private final Map aliasToContainerMap = new HashMap<>(); - - // Maps holding actions to be used when doing a shutdown - private final Map shutdownDescriptorPerContainerMap = new LinkedHashMap<>(); - private final Map> shutdownDescriptorPerPomLabelMap = new HashMap<>(); - - /** - * Register a started container to this tracker - * - * @param containerId container id to register - * @param imageConfig configuration of associated image - * @param gavLabel pom label to identifying the reactor project where the container was created - */ - public synchronized void registerContainer(String containerId, - ImageConfiguration imageConfig, - GavLabel gavLabel) { - ContainerShutdownDescriptor descriptor = new ContainerShutdownDescriptor(imageConfig, containerId); - shutdownDescriptorPerContainerMap.put(containerId, descriptor); - updatePomLabelMap(gavLabel, descriptor); - updateImageToContainerMapping(imageConfig, containerId); - } - - /** - * Remove a container from this container (if stored) and return its descriptor - * - * @param containerId id to remove - * @return descriptor of the container removed or null - */ - public synchronized ContainerShutdownDescriptor removeContainer(String containerId) { - ContainerShutdownDescriptor descriptor = shutdownDescriptorPerContainerMap.remove(containerId); - if (descriptor != null) { - removeContainerIdFromLookupMaps(containerId); - removeDescriptorFromPomLabelMap(descriptor); - } - return descriptor; - } - - /** - * Lookup a container by name or alias from the tracked containers - * - * @param lookup name or alias of the container to lookup - * @return container id found or null - */ - public synchronized String lookupContainer(String lookup) { - if (aliasToContainerMap.containsKey(lookup)) { - return aliasToContainerMap.get(lookup); - } - return imageToContainerMap.get(lookup); - } - - /** - * Get all shutdown descriptors for a given pom label and remove it from the tracker. The descriptors - * are returned in reverse order of their registration. - * - * If no pom label is given, then all descriptors are returned. - * - * @param gavLabel the label for which to get the descriptors or null for all descriptors - * @return the descriptors for the given label or an empty collection - */ - public synchronized Collection removeShutdownDescriptors(GavLabel gavLabel) { - List descriptors; - if (gavLabel != null) { - descriptors = removeFromPomLabelMap(gavLabel); - removeFromPerContainerMap(descriptors); - } else { - // All entries are requested - descriptors = new ArrayList<>(shutdownDescriptorPerContainerMap.values()); - clearAllMaps(); - } - - Collections.reverse(descriptors); - return descriptors; - } - - // ======================================================== - - private void updatePomLabelMap(GavLabel gavLabel, ContainerShutdownDescriptor descriptor) { - if (gavLabel != null) { - List descList = shutdownDescriptorPerPomLabelMap.computeIfAbsent(gavLabel, k -> new ArrayList<>()); - descList.add(descriptor); - } - } - - private void removeDescriptorFromPomLabelMap(ContainerShutdownDescriptor descriptor) { - Iterator>> mapIt = shutdownDescriptorPerPomLabelMap.entrySet().iterator(); - while(mapIt.hasNext()) { - Map.Entry> mapEntry = mapIt.next(); - List descs = mapEntry.getValue(); - Iterator it = descs.iterator(); - while (it.hasNext()) { - ContainerShutdownDescriptor desc = it.next(); - if (descriptor.equals(desc)) { - it.remove(); - } - } - if (descs.isEmpty()) { - mapIt.remove(); - } - } - } - - private void removeContainerIdFromLookupMaps(String containerId) { - removeValueFromMap(imageToContainerMap,containerId); - removeValueFromMap(aliasToContainerMap,containerId); - } - - private void removeValueFromMap(Map map, String value) { - Iterator> it = map.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (entry.getValue().equals(value)) { - it.remove(); - } - } - } - - private void updateImageToContainerMapping(ImageConfiguration imageConfig, String id) { - // Register name -> containerId and alias -> name - imageToContainerMap.put(imageConfig.getName(), id); - if (imageConfig.getAlias() != null) { - aliasToContainerMap.put(imageConfig.getAlias(), id); - } - } - - private void removeFromPerContainerMap(List descriptors) { - Iterator> it = shutdownDescriptorPerContainerMap.entrySet().iterator(); - while (it.hasNext()) { - Map.Entry entry = it.next(); - if (descriptors.contains(entry.getValue())) { - removeContainerIdFromLookupMaps(entry.getKey()); - it.remove(); - } - } - } - - private List removeFromPomLabelMap(GavLabel gavLabel) { - List descriptors; - descriptors = shutdownDescriptorPerPomLabelMap.remove(gavLabel); - if (descriptors == null) { - descriptors = new ArrayList<>(); - } return descriptors; - } - - private void clearAllMaps() { - shutdownDescriptorPerContainerMap.clear(); - shutdownDescriptorPerPomLabelMap.clear(); - imageToContainerMap.clear(); - aliasToContainerMap.clear(); - } - - // ======================================================= - - static class ContainerShutdownDescriptor { - - // The image's configuration - private final ImageConfiguration imageConfig; - - // Alias of the image - private final String containerId; - - // How long to wait after shutdown (in milliseconds) - private final int shutdownGracePeriod; - - // How long to wait after stop to kill container (in seconds) - private final int killGracePeriod; - - - // Command to call before stopping container and whether to stop the build - private String preStop; - private boolean breakOnError = false; - - ContainerShutdownDescriptor(ImageConfiguration imageConfig, String containerId) { - this.imageConfig = imageConfig; - this.containerId = containerId; - - RunImageConfiguration runConfig = imageConfig.getRunConfiguration(); - WaitConfiguration waitConfig = runConfig != null ? runConfig.getWait() : null; - this.shutdownGracePeriod = waitConfig != null && waitConfig.getShutdown() != null ? waitConfig.getShutdown() : 0; - this.killGracePeriod = waitConfig != null && waitConfig.getKill() != null ? waitConfig.getKill() : 0; - if (waitConfig != null && waitConfig.getExec() != null) { - this.preStop = waitConfig.getExec().getPreStop(); - this.breakOnError = waitConfig.getExec().isBreakOnError(); - } - } - - public ImageConfiguration getImageConfiguration() { - return imageConfig; - } - - public String getImage() { - return imageConfig.getName(); - } - - public String getContainerId() { - return containerId; - } - - public String getDescription() { - return imageConfig.getDescription(); - } - - public int getShutdownGracePeriod() { - return shutdownGracePeriod; - } - - public int getKillGracePeriod() { - return killGracePeriod; - } - - public String getPreStop() { - return preStop; - } - - public boolean isBreakOnError() { - return breakOnError; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - ContainerShutdownDescriptor that = (ContainerShutdownDescriptor) o; - - return containerId.equals(that.containerId); - - } - - @Override - public int hashCode() { - return containerId.hashCode(); - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/DockerServiceHub.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/DockerServiceHub.java index 928edd3504..0d1c163acc 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/DockerServiceHub.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/DockerServiceHub.java @@ -15,7 +15,6 @@ import org.eclipse.jkube.kit.build.api.assembly.AssemblyManager; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; import org.eclipse.jkube.kit.common.KitLogger; /** @@ -23,57 +22,42 @@ * Mojos for calling to the docker backend. The docker backend (DAO) is injected from the outside. * * @author roland - * @since 01/12/15 */ public class DockerServiceHub { private final DockerAccess dockerAccess; - - private final QueryService queryService; - private final RunService runService; private final RegistryService registryService; private final BuildService buildService; private final ArchiveService archiveService; - private final VolumeService volumeService; private final WatchService watchService; - private final WaitService waitService; public static DockerServiceHub newInstance(KitLogger kitLogger) { return newInstance(kitLogger, - new DockerAccessFactory().createDockerAccess(DockerAccessFactory.DockerAccessContext.getDefault(kitLogger)), - new LogOutputSpecFactory(true, true) + new DockerAccessFactory().createDockerAccess(DockerAccessFactory.DockerAccessContext.getDefault(kitLogger)) ); } - public static DockerServiceHub newInstance(KitLogger kitLogger, DockerAccess dockerAccess, LogOutputSpecFactory logOutputSpecFactory) { - return new DockerServiceHub(dockerAccess, ContainerTracker.getInstance(), AssemblyManager.getInstance(), kitLogger, - logOutputSpecFactory); + public static DockerServiceHub newInstance(KitLogger kitLogger, DockerAccess dockerAccess) { + return new DockerServiceHub(dockerAccess, AssemblyManager.getInstance(), kitLogger); } - DockerServiceHub(DockerAccess dockerAccess, ContainerTracker containerTracker, + DockerServiceHub(DockerAccess dockerAccess, AssemblyManager assemblyManager, - KitLogger logger, LogOutputSpecFactory logSpecFactory) { + KitLogger logger) { this.dockerAccess = dockerAccess; archiveService = new ArchiveService(assemblyManager, logger); if (dockerAccess != null) { - queryService = new QueryService(dockerAccess); + final QueryService queryService = new QueryService(dockerAccess); registryService = new RegistryService(dockerAccess, queryService, logger); - runService = new RunService(dockerAccess, queryService, containerTracker, logSpecFactory, logger); buildService = new BuildService(dockerAccess, queryService, registryService, archiveService, logger); - volumeService = new VolumeService(dockerAccess); - watchService = new WatchService(archiveService, buildService, queryService, runService, logger); - waitService = new WaitService(dockerAccess, queryService, logger); + watchService = new WatchService(archiveService, buildService, logger); } else { - queryService = null; registryService = null; - runService = null; buildService = null; - volumeService = null; watchService = null; - waitService = null; } } @@ -96,47 +80,16 @@ public BuildService getBuildService() { return buildService; } - /** - * Get the query service for obtaining information about containers and images - * - * @return query service - */ - public QueryService getQueryService() { - checkDockerAccessInitialization(); - return queryService; - } - /** * Get the registry service to push/pull images * - * @return query service + * @return registry service */ public RegistryService getRegistryService() { checkDockerAccessInitialization(); return registryService; } - - /** - * The run service is responsible for creating and starting up containers - * - * @return the run service - */ - public RunService getRunService() { - checkDockerAccessInitialization(); - return runService; - } - - /** - * The volume service is responsible for creating volumes - * - * @return the run service - */ - public VolumeService getVolumeService() { - checkDockerAccessInitialization(); - return volumeService; - } - /** * The watch service is responsible for watching container status and rebuilding * @@ -148,18 +101,7 @@ public WatchService getWatchService() { } /** - * The wait service is responsible on waiting on container based on several - * conditions - * - * @return the wait service - */ - public WaitService getWaitService() { - checkDockerAccessInitialization(); - return waitService; - } - - /** - * Serivce for creating archives + * Service for creating archives * * @return the archive service */ diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ImagePullCache.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ImagePullCache.java deleted file mode 100644 index 922f730c1c..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/ImagePullCache.java +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker; - -import com.google.gson.JsonObject; -import org.eclipse.jkube.kit.common.JsonFactory; - -/** - * Simple interface for a ImagePullCache manager, to load and persist the cache. - */ -public class ImagePullCache { - - // Key for the previously used image cache - private static final String CONTEXT_KEY_PREVIOUSLY_PULLED = "CONTEXT_KEY_PREVIOUSLY_PULLED"; - - private final Backend backend; - - public ImagePullCache(Backend backend) { - this.backend = backend; - } - - public boolean hasAlreadyPulled(String image) { - return load().has(image); - } - - public void pulled(String image) { - save(load().add(image)); - } - - // Store to use for the cached - public interface Backend { - String get(String key); - void put(String key, String value); - } - - // ====================================================================================== - - private ImagePullCacheStore load() { - - String pullCacheJson = backend.get(CONTEXT_KEY_PREVIOUSLY_PULLED); - - ImagePullCacheStore cache = new ImagePullCacheStore(pullCacheJson); - - if (pullCacheJson == null) { - save(cache); - } - return cache; - } - - private void save(ImagePullCacheStore cache) { - backend.put(CONTEXT_KEY_PREVIOUSLY_PULLED, cache.toString()); - } - - /** - * Simple serializable cache for holding image names - * - * @author roland - * @since 20/07/16 - */ - class ImagePullCacheStore { - - private JsonObject cache; - - - ImagePullCacheStore(String json) { - cache = json != null ? JsonFactory.newJsonObject(json) : new JsonObject(); - } - - public boolean has(String imageName) { - return cache.has(imageName); - } - - public ImagePullCacheStore add(String image) { - cache.addProperty(image, Boolean.TRUE); - return this; - } - - @Override - public String toString() { - return cache.toString(); - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/QueryService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/QueryService.java index 72831add79..f1430cd1fa 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/QueryService.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/QueryService.java @@ -13,12 +13,6 @@ */ package org.eclipse.jkube.kit.build.service.docker; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.api.model.Network; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; @@ -39,79 +33,6 @@ public QueryService(DockerAccess docker) { this.docker = docker; } - /** - * Get container by id - * - * @param containerIdOrName container id or name - * @return container found - * @throws DockerAccessException if an error occurs or no container with this id or name exists - */ - public Container getMandatoryContainer(String containerIdOrName) throws DockerAccessException { - Container container = getContainer(containerIdOrName); - if (container == null) { - throw new DockerAccessException("Cannot find container %s", containerIdOrName); - } - return container; - } - - /** - * Get a container running for a given container name. - * @param containerIdOrName name of container to lookup - * @return the container found or null if no container is available. - * @throws DockerAccessException in case of an remote error - */ - public Container getContainer(final String containerIdOrName) throws DockerAccessException { - return docker.getContainer(containerIdOrName); - } - - /** - * Get a network for a given network name. - * @param networkName name of network to lookup - * @return the network found or null if no network is available. - * @throws DockerAccessException in case of an remote error - */ - public Network getNetworkByName(final String networkName) throws DockerAccessException { - for (Network el : docker.listNetworks()) { - if (networkName.equals(el.getName())) { - return el; - } - } - return null; - } - - /** - * Get all networks. - * @return the network found or null if no network is available. - * @throws DockerAccessException in case of an remote error - */ - public Set getNetworks() throws DockerAccessException { - return new HashSet<>(docker.listNetworks()); - } - - /** - * Get name for single container when the id is given - * - * @param containerId id of container to lookup - * @return the name of the container - * @throws DockerAccessException if access to the docker daemon fails - */ - public String getContainerName(String containerId) throws DockerAccessException { - return getMandatoryContainer(containerId).getName(); - } - - /** - * Get all containers which are build from an image. By default only the last containers are considered but this - * can be tuned with a global parameters. - * - * @param image for which its container are looked up - * @param all whether to fetch all containers - * @return list of Container objects - * @throws DockerAccessException if the request fails - */ - public List getContainersForImage(final String image, final boolean all) throws DockerAccessException { - return docker.getContainersForImage(image, all); - } - /** * Finds the id of an image. * @@ -123,53 +44,6 @@ public String getImageId(String imageName) throws DockerAccessException { return docker.getImageId(imageName); } - /** - * Get the id of the latest container started for an image - * - * @param image for which its container are looked up - * @return container or null if no container has been started for this image. - * @throws DockerAccessException if the request fails - */ - public Container getLatestContainerForImage(String image) throws DockerAccessException { - long newest = 0; - Container result = null; - - for (Container container : getContainersForImage(image, false)) { - long timestamp = container.getCreated(); - - if (timestamp < newest) { - continue; - } - - newest = timestamp; - result = container; - } - - return result; - } - - /** - * Check whether a container with the given name exists - * - * @param containerName container name - * @return true if a container with this name exists, false otherwise. - * @throws DockerAccessException docker access exception - */ - public boolean hasContainer(String containerName) throws DockerAccessException { - return getContainer(containerName) != null; - } - - /** - * Check whether a network with the given name exists - * - * @param networkName network name - * @return true if a network with this name exists, false otherwise. - * @throws DockerAccessException docker access exception - */ - public boolean hasNetwork(String networkName) throws DockerAccessException { - return getNetworkByName(networkName) != null; - } - /** * Check whether the given Image is locally available. * diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/RunService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/RunService.java deleted file mode 100644 index dce684bee4..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/RunService.java +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker; - -import org.eclipse.jkube.kit.build.api.model.ExecDetails; -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.api.model.ContainerDetails; -import org.eclipse.jkube.kit.build.api.model.Network; -import org.eclipse.jkube.kit.build.api.model.NetworkCreateConfig; -import org.eclipse.jkube.kit.build.core.GavLabel; -import org.eclipse.jkube.kit.build.service.docker.access.ContainerCreateConfig; -import org.eclipse.jkube.kit.build.service.docker.access.ContainerHostConfig; -import org.eclipse.jkube.kit.build.service.docker.access.ContainerNetworkingConfig; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.build.service.docker.access.ExecException; -import org.eclipse.jkube.kit.build.api.model.PortMapping; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; -import org.eclipse.jkube.kit.config.image.NetworkConfig; -import org.eclipse.jkube.kit.config.image.RestartPolicy; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.RunVolumeConfiguration; -import org.eclipse.jkube.kit.build.service.docker.config.VolumeConfiguration; -import org.eclipse.jkube.kit.build.service.docker.helper.ContainerNamingUtil; -import org.eclipse.jkube.kit.build.service.docker.helper.StartOrderResolver; -import org.eclipse.jkube.kit.build.service.docker.wait.WaitTimeoutException; -import org.eclipse.jkube.kit.build.service.docker.wait.WaitUtil; -import org.eclipse.jkube.kit.common.KitLogger; -import org.eclipse.jkube.kit.common.util.EnvUtil; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.common.Arguments; - -import java.io.File; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; - -import static org.eclipse.jkube.kit.build.service.docker.helper.VolumeBindingUtil.resolveRelativeVolumeBindings; - - -/** - * Service class for helping in running containers. - * - * @author roland - * @since 16/06/15 - */ -public class RunService { - - // logger delegated from top - private final KitLogger log; - - // Action to be used when doing a shutdown - private final ContainerTracker tracker; - - // DAO for accessing the docker daemon - private final DockerAccess docker; - - private final QueryService queryService; - - private final LogOutputSpecFactory logConfig; - - public RunService(DockerAccess docker, - QueryService queryService, - ContainerTracker tracker, - LogOutputSpecFactory logConfig, - KitLogger log) { - this.docker = docker; - this.queryService = queryService; - this.tracker = tracker; - this.log = log; - this.logConfig = logConfig; - } - - /** - * Create and start a Exec container with the given image configuration. - * @param containerId container id to run exec command against - * @param command command to execute - * @param imageConfiguration configuration of the container's image - * @return the exec container id - * - * @throws DockerAccessException if access to the docker backend fails - * @throws ExecException if any problem faced during exec - */ - public String execInContainer(String containerId, String command, ImageConfiguration imageConfiguration) - throws DockerAccessException, ExecException { - Arguments arguments = new Arguments(); - arguments.setExec(Arrays.asList(EnvUtil.splitOnSpaceWithEscape(command))); - String execContainerId = docker.createExecContainer(containerId, arguments); - docker.startExecContainer(execContainerId, logConfig.createSpec(containerId, imageConfiguration)); - - ExecDetails execContainer = docker.getExecContainer(execContainerId); - Integer exitCode = execContainer.getExitCode(); - if (exitCode != null && exitCode != 0) { - ContainerDetails container = docker.getContainer(containerId); - throw new ExecException(execContainer, container); - } - return execContainerId; - } - - /** - * Create and start a container with the given image configuration. - * @param imageConfig image configuration holding the run information and the image name - * @param portMapping container port mapping - * @param gavLabel label to tag the started container with - * @param baseDir base directory - * @param properties properties to fill in with dynamically assigned ports - * @param defaultContainerNamePattern pattern to use for naming containers. Can be null in which case a default pattern is used - * @param buildTimestamp date which should be used as the timestamp when calculating container names - * @return the container id - * - * @throws DockerAccessException if access to the docker backend fails - */ - public String createAndStartContainer(ImageConfiguration imageConfig, - PortMapping portMapping, - GavLabel gavLabel, - Properties properties, - File baseDir, - String defaultContainerNamePattern, - Date buildTimestamp) throws DockerAccessException { - RunImageConfiguration runConfig = imageConfig.getRunConfiguration(); - String imageName = imageConfig.getName(); - - Collection existingContainers = queryService.getContainersForImage(imageName, true); - String containerName = ContainerNamingUtil.formatContainerName(imageConfig, defaultContainerNamePattern, buildTimestamp, existingContainers); - - ContainerCreateConfig config = createContainerConfig(imageName, runConfig, portMapping, gavLabel, properties, baseDir); - - String id = docker.createContainer(config, containerName); - startContainer(imageConfig, id, gavLabel); - - if (portMapping.needsPropertiesUpdate()) { - updateMappedPortsAndAddresses(id, portMapping); - } - - return id; - } - - /** - * Stop a container immediately by id. - * @param containerId the container to stop - * @param imageConfig image configuration for this container - * @param keepContainer whether to keep container or to remove them after stopping - * @param removeVolumes whether to remove volumes after stopping - * @throws DockerAccessException docker access exception - * @throws ExecException exec exception - */ - public void stopContainer(String containerId, - ImageConfiguration imageConfig, - boolean keepContainer, - boolean removeVolumes) - throws DockerAccessException, ExecException { - ContainerTracker.ContainerShutdownDescriptor descriptor = - new ContainerTracker.ContainerShutdownDescriptor(imageConfig, containerId); - shutdown(descriptor, keepContainer, removeVolumes); - } - - /** - * Lookup up whether a certain has been already started and registered. If so, stop it - * - * @param containerId the container to stop - * @param keepContainer whether to keep container or to remove them after stoppings - * @param removeVolumes whether to remove volumes after stopping - * - * @throws DockerAccessException docker access exception - * @throws ExecException exec exception - */ - public void stopPreviouslyStartedContainer(String containerId, - boolean keepContainer, - boolean removeVolumes) - throws DockerAccessException, ExecException { - ContainerTracker.ContainerShutdownDescriptor descriptor = tracker.removeContainer(containerId); - if (descriptor != null) { - shutdown(descriptor, keepContainer, removeVolumes); - } - } - - /** - * Stop all registered container - * - * @param keepContainer whether to keep container or to remove them after stopping - * @param removeVolumes whether to remove volumes after stopping - * @param removeCustomNetworks whether to remove custom networks - * @param gavLabel group artifact version label - * @throws DockerAccessException if during stopping of a container sth fails - * @throws ExecException if any problem during exec - */ - public void stopStartedContainers(boolean keepContainer, - boolean removeVolumes, - boolean removeCustomNetworks, - GavLabel gavLabel) - throws DockerAccessException, ExecException { - Set networksToRemove = new HashSet<>(); - for (ContainerTracker.ContainerShutdownDescriptor descriptor : tracker.removeShutdownDescriptors(gavLabel)) { - collectCustomNetworks(networksToRemove, descriptor, removeCustomNetworks); - shutdown(descriptor, keepContainer, removeVolumes); - } - removeCustomNetworks(networksToRemove); - } - - private void collectCustomNetworks(Set networksToRemove, ContainerTracker.ContainerShutdownDescriptor descriptor, boolean removeCustomNetworks) throws DockerAccessException { - final NetworkConfig config = descriptor.getImageConfiguration().getRunConfiguration().getNetworkingConfig(); - if (removeCustomNetworks && config.isCustomNetwork()) { - networksToRemove.add(queryService.getNetworkByName(config.getCustomNetwork())); - } - } - - /** - * Lookup a container that has been started - * - * @param lookup a container by id or alias - * @return the container id if the container exists, null otherwise. - */ - public String lookupContainer(String lookup) { - return tracker.lookupContainer(lookup); - } - - /** - * Get the proper order for images to start - * - * @param queryService query service - * @param images list of images for which the order should be created - * @return list of images in the right startup order - */ - public List getImagesConfigsInOrder(QueryService queryService, List images) { - return StartOrderResolver.resolve(queryService, convertToResolvables(images)); - } - - /** - * Create port mapping for a specific configuration as it can be used when creating containers - * - * @param runConfig the cun configuration - * @param properties properties to lookup variables - * @return the portmapping - */ - public PortMapping createPortMapping(RunImageConfiguration runConfig, Properties properties) { - try { - return new PortMapping(runConfig.getPorts(), properties); - } catch (IllegalArgumentException exp) { - throw new IllegalArgumentException("Cannot parse port mapping", exp); - } - } - - /** - * Add a shutdown hook in order to stop all registered containers - * - * @param keepContainer whether to keep container or not - * @param removeVolumes whether to remove volumes or not - * @param removeCustomNetworks whether to remove custom networks or not - */ - public void addShutdownHookForStoppingContainers(final boolean keepContainer, final boolean removeVolumes, final boolean removeCustomNetworks) { - Runtime.getRuntime().addShutdownHook(new Thread() { - @Override - public void run() { - try { - stopStartedContainers(keepContainer, removeVolumes, removeCustomNetworks, null); - } catch (DockerAccessException | ExecException e) { - log.error("Error while stopping containers: %s", e.getMessage()); - } - } - }); - } - - private List convertToResolvables(List images) { - List ret = new ArrayList<>(); - for (ImageConfiguration config : images) { - if (config.getRunConfiguration().skip()) { - log.info("%s: Skipped running", config.getDescription()); - } else { - ret.add(config); - } - } - return ret; - } - - // visible for testing - ContainerCreateConfig createContainerConfig(String imageName, RunImageConfiguration runConfig, PortMapping mappedPorts, - GavLabel gavLabel, Properties mavenProps, File baseDir) - throws DockerAccessException { - try { - ContainerCreateConfig config = new ContainerCreateConfig(imageName) - .hostname(runConfig.getHostname()) - .domainname(runConfig.getDomainname()) - .user(runConfig.getUser()) - .workingDir(runConfig.getWorkingDir()) - .entrypoint(runConfig.getEntrypoint()) - .exposedPorts(mappedPorts.getContainerPorts()) - .environment(runConfig.getEnvPropertyFile(), runConfig.getEnv(), mavenProps) - .labels(mergeLabels(runConfig.getLabels(), gavLabel)) - .command(runConfig.getCmd()) - .hostConfig(createContainerHostConfig(runConfig, mappedPorts, baseDir)); - RunVolumeConfiguration volumeConfig = runConfig.getVolumeConfiguration(); - if (volumeConfig != null) { - resolveRelativeVolumeBindings(baseDir, volumeConfig); - config.binds(volumeConfig.getBind()); - } - - NetworkConfig networkConfig = runConfig.getNetworkingConfig(); - if(networkConfig.isCustomNetwork() && networkConfig.hasAliases()) { - ContainerNetworkingConfig networkingConfig = - new ContainerNetworkingConfig() - .aliases(networkConfig); - config.networkingConfig(networkingConfig); - } - - return config; - } catch (IllegalArgumentException e) { - throw new IllegalArgumentException(String.format("Failed to create contained configuration for [%s]", imageName), e); - } - } - - private Map mergeLabels(Map labels, GavLabel runIdLabel) { - Map ret = new HashMap<>(); - if (labels != null) { - ret.putAll(labels); - } - if (runIdLabel != null) { - ret.put(GavLabel.KEY, runIdLabel.getValue()); - } - return ret; - } - - ContainerHostConfig createContainerHostConfig(RunImageConfiguration runConfig, PortMapping mappedPorts, File baseDir) - throws DockerAccessException { - RestartPolicy restartPolicy = runConfig.getRestartPolicy(); - - - List links = findContainerIdsForLinks(runConfig.getLinks(), - runConfig.getNetworkingConfig().isCustomNetwork()); - - ContainerHostConfig config = new ContainerHostConfig() - .extraHosts(runConfig.getExtraHosts()) - .links(links) - .portBindings(mappedPorts) - .privileged(runConfig.getPrivileged()) - .shmSize(runConfig.getShmSize()) - .dns(runConfig.getDns()) - .dnsSearch(runConfig.getDnsSearch()) - .capAdd(runConfig.getCapAdd()) - .capDrop(runConfig.getCapDrop()) - .securityOpts(runConfig.getSecurityOpts()) - .memory(runConfig.getMemory()) - .memorySwap(runConfig.getMemorySwap()) - .restartPolicy(restartPolicy.getName(), restartPolicy.getRetry()) - .logConfig(runConfig.getLog()) - .tmpfs(runConfig.getTmpfs()) - .ulimits(runConfig.getUlimits()) - .cpuShares(runConfig.getCpuShares()) - .cpus(runConfig.getCpus()) - .cpuSet(runConfig.getCpuSet()) - .readonlyRootfs(runConfig.getReadOnly()) - .autoRemove(runConfig.getAutoRemove()); - - addVolumeConfig(config, runConfig, baseDir); - addNetworkingConfig(config, runConfig); - - return config; - } - - private void addNetworkingConfig(ContainerHostConfig config, RunImageConfiguration runConfig) throws DockerAccessException { - NetworkConfig networkConfig = runConfig.getNetworkingConfig(); - if (networkConfig.isStandardNetwork()) { - String alias = networkConfig.getContainerAlias(); - String containerId = alias != null ? findContainerId(alias, false) : null; - config.networkMode(networkConfig.getStandardMode(containerId)); - } else if (networkConfig.isCustomNetwork()) { - config.networkMode(networkConfig.getCustomNetwork()); - } - } - - private void addVolumeConfig(ContainerHostConfig config, RunImageConfiguration runConfig, File baseDir) throws DockerAccessException { - RunVolumeConfiguration volConfig = runConfig.getVolumeConfiguration(); - if (volConfig != null) { - resolveRelativeVolumeBindings(baseDir, volConfig); - config.binds(volConfig.getBind()) - .volumesFrom(findVolumesFromContainers(volConfig.getFrom())); - } - } - - private List findContainerIdsForLinks(List links, boolean leaveUnresolvedIfNotFound) throws DockerAccessException { - List ret = new ArrayList<>(); - for (String[] link : EnvUtil.splitOnLastColon(links)) { - String id = findContainerId(link[0], false); - if (id != null) { - ret.add(queryService.getContainerName(id) + ":" + link[1]); - } else if (leaveUnresolvedIfNotFound) { - ret.add(link[0] + ":" + link[1]); - } else { - throw new DockerAccessException("No container found for image/alias '%s', unable to link", link[0]); - } - } - return !ret.isEmpty() ? ret : null; - } - - // visible for testing - private List findVolumesFromContainers(List images) throws DockerAccessException { - List list = new ArrayList<>(); - if (images != null) { - for (String image : images) { - String id = findContainerId(image, true); - if (id == null) { - throw new DockerAccessException("No container found for image/alias '%s', unable to mount volumes", image); - } - - list.add(queryService.getContainerName(id)); - } - } - return list; - } - - - // checkAllContainers: false = only running containers are considered - private String findContainerId(String imageNameOrAlias, boolean checkAllContainers) throws DockerAccessException { - String id = lookupContainer(imageNameOrAlias); - - // check for external container. The image name is interpreted as a *container name* for that case ... - if (id == null) { - Container container = queryService.getContainer(imageNameOrAlias); - if (container != null && (checkAllContainers || container.isRunning())) { - id = container.getId(); - } - } - return id; - } - - private void startContainer(ImageConfiguration imageConfig, String id, GavLabel gavLabel) throws DockerAccessException { - log.info("%s: Start container %s",imageConfig.getDescription(), id); - docker.startContainer(id); - tracker.registerContainer(id, imageConfig, gavLabel); - } - - private void updateMappedPortsAndAddresses(String containerId, PortMapping mappedPorts) throws DockerAccessException { - Container container = queryService.getMandatoryContainer(containerId); - if (container.isRunning()) { - mappedPorts.updateProperties(container.getPortBindings()); - } else { - log.warn("Container %s is not running anymore, can not extract dynamic ports",containerId); - } - } - - private void shutdown(ContainerTracker.ContainerShutdownDescriptor descriptor, boolean keepContainer, boolean removeVolumes) - throws DockerAccessException, ExecException { - - String containerId = descriptor.getContainerId(); - if (descriptor.getPreStop() != null) { - try { - execInContainer(containerId, descriptor.getPreStop(), descriptor.getImageConfiguration()); - } catch (DockerAccessException e) { - log.error("%s", e.getMessage()); - } catch (ExecException e) { - if (descriptor.isBreakOnError()) { - throw e; - } else { - log.warn("Cannot run preStop: %s", e.getMessage()); - } - } - } - - int killGracePeriod = adjustGracePeriod(descriptor.getKillGracePeriod()); - log.debug("shutdown will wait max of %d seconds before removing container", killGracePeriod); - - long waited; - if (killGracePeriod == 0) { - docker.stopContainer(containerId, 0); - waited = 0; - } else { - waited = shutdownAndWait(containerId, killGracePeriod); - } - if (!keepContainer) { - removeContainer(descriptor, removeVolumes, containerId); - } - - log.info("%s: Stop%s container %s after %s ms", - descriptor.getDescription(), - (keepContainer ? "" : " and removed"), - containerId.substring(0, 12), waited); - } - - public void createCustomNetworkIfNotExistant(String customNetwork) throws DockerAccessException { - if (!queryService.hasNetwork(customNetwork)) { - docker.createNetwork(new NetworkCreateConfig(customNetwork)); - } else { - log.debug("Custom Network " + customNetwork + " found"); - } - } - - public void removeCustomNetworks(Collection networks) throws DockerAccessException { - for (Network network : networks) { - docker.removeNetwork(network.getId()); - } - } - - private int adjustGracePeriod(int gracePeriod) { - int killGracePeriodInSeconds = (gracePeriod + 500) / 1000; - if (gracePeriod != 0 && killGracePeriodInSeconds == 0) { - log.warn("A kill grace period of %d ms leads to no wait at all since its rounded to seconds. " + - "Please use at least 500 as value for wait.kill", gracePeriod); - } - - return killGracePeriodInSeconds; - } - - private void removeContainer(ContainerTracker.ContainerShutdownDescriptor descriptor, boolean removeVolumes, String containerId) - throws DockerAccessException { - int shutdownGracePeriod = descriptor.getShutdownGracePeriod(); - if (shutdownGracePeriod != 0) { - log.debug("Shutdown: Wait %d ms before removing container", shutdownGracePeriod); - WaitUtil.sleep(shutdownGracePeriod); - } - // Remove the container - docker.removeContainer(containerId, removeVolumes); - } - - private long shutdownAndWait(final String containerId, final int killGracePeriodInSeconds) throws DockerAccessException { - long waited; - try { - waited = WaitUtil.wait(killGracePeriodInSeconds, new Callable() { - @Override - public Void call() throws Exception { - docker.stopContainer(containerId, killGracePeriodInSeconds); - return null; - } - }); - } catch (ExecutionException e) { - if (e.getCause() instanceof DockerAccessException) { - throw (DockerAccessException) e.getCause(); - } else { - throw new DockerAccessException(e, "failed to stop container id [%s]", containerId); - } - } catch (WaitTimeoutException e) { - waited = e.getWaited(); - log.warn("Stop container id [%s] timed out after %s ms", containerId, waited); - } - - return waited; - } - - /** - * Creates a Volume if a volume is referred to during startup in bind mount mapping and - * a VolumeConfiguration exists - * - * @param hub Service hub - * @param binds volume binds present in ImageConfiguration - * @param volumes VolumeConfigs present - * @return List of volumes created - * @throws DockerAccessException docker access exception - */ - public List createVolumesAsPerVolumeBinds(DockerServiceHub hub, List binds, List volumes) - throws DockerAccessException { - - Map indexMap = new HashMap<>(); - List volumesCreated = new ArrayList<>(); - - for (int index = 0; index < volumes.size(); index++) { - indexMap.put(volumes.get(index).getName(), index); - } - - for (String bind : binds) { - if (bind.contains(":")) { - String name = bind.substring(0, bind.indexOf(':')); - Integer volumeConfigIndex = indexMap.get(name); - if (volumeConfigIndex != null) { - VolumeConfiguration volumeConfig = volumes.get(volumeConfigIndex); - hub.getVolumeService().createVolume(volumeConfig); - volumesCreated.add(volumeConfig.getName()); - } - } - } - - return volumesCreated; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/VolumeService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/VolumeService.java deleted file mode 100644 index 1063d22c24..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/VolumeService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker; - -import org.eclipse.jkube.kit.build.api.model.VolumeCreateConfig; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.build.service.docker.config.VolumeConfiguration; - -/** - * Service Class for helping control Volumes - * - * @author Tom Burton - * @version Dec 15, 2016 - */ -public class VolumeService { - // DAO for accessing the docker daemon - private DockerAccess docker; - - VolumeService(DockerAccess dockerAccess) { - this.docker = dockerAccess; - } - - public String createVolume(VolumeConfiguration vc) throws DockerAccessException { - VolumeCreateConfig config = - new VolumeCreateConfig(vc.getName()) - .driver(vc.getDriver()) - .opts(vc.getOpts()) - .labels(vc.getLabels()); - - return docker.createVolume(config); - } - - public void removeVolume(String volumeName) throws DockerAccessException { - docker.removeVolume(volumeName); - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WaitService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WaitService.java deleted file mode 100644 index be876b210f..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WaitService.java +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Properties; - -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.build.service.docker.access.log.DefaultLogCallback; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogDispatcher; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpec; -import org.eclipse.jkube.kit.build.service.docker.wait.ExitCodeChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.HealthCheckChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.HttpPingChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.LogWaitChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.PreconditionFailedException; -import org.eclipse.jkube.kit.build.service.docker.wait.TcpPortChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.WaitChecker; -import org.eclipse.jkube.kit.build.service.docker.wait.WaitTimeoutException; -import org.eclipse.jkube.kit.build.service.docker.wait.WaitUtil; -import org.eclipse.jkube.kit.common.KitLogger; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.WaitConfiguration; - -import org.apache.commons.text.StringSubstitutor; - -/** - * @author roland - */ -public class WaitService { - - private final QueryService queryService; - private DockerAccess dockerAccess; - private KitLogger log; - - public WaitService(DockerAccess dockerAccess, QueryService queryService, KitLogger log) { - this.dockerAccess = dockerAccess; - this.log = log; - this.queryService = queryService; - } - - // ======================================================================================================== - - public void wait(ImageConfiguration imageConfig, Properties projectProperties, String containerId) throws IOException { - List checkers = prepareWaitCheckers(imageConfig, projectProperties, containerId); - int timeout = getTimeOut(imageConfig); - - if (checkers.isEmpty()) { - if (timeout > 0) { - log.info("%s: Pausing for %d ms", imageConfig.getDescription(), timeout); - WaitUtil.sleep(timeout); - } - return; - } - - String logLine = extractCheckerLog(checkers); - ContainerRunningPrecondition precondition = new ContainerRunningPrecondition(dockerAccess, containerId); - try { - long waited = WaitUtil.wait(precondition, timeout, checkers); - log.info("%s: Waited %s %d ms", imageConfig.getDescription(), logLine, waited); - } catch (WaitTimeoutException exp) { - String desc = String.format("%s: Timeout after %d ms while waiting %s", - imageConfig.getDescription(), exp.getWaited(), - logLine); - log.error(desc); - throw new IOException(desc); - } catch (PreconditionFailedException exp) { - String desc = String.format("%s: Container stopped with exit code %d unexpectedly after %d ms while waiting %s", - imageConfig.getDescription(), precondition.getExitCode(), exp.getWaited(), - logLine); - log.error(desc); - throw new IOException(desc); - } - } - - private int getTimeOut(ImageConfiguration imageConfig) { - WaitConfiguration wait = getWaitConfiguration(imageConfig); - return wait != null && wait.getTime() != null ? wait.getTime() : 0; - } - - private String extractCheckerLog(List checkers) { - List logOut = new ArrayList<>(); - for (WaitChecker checker : checkers) { - logOut.add(checker.getLogLabel()); - } - return String.join(" and ", logOut); - } - - private List prepareWaitCheckers(ImageConfiguration imageConfig, Properties projectProperties, String containerId) throws IOException { - WaitConfiguration wait = getWaitConfiguration(imageConfig); - - if (wait == null) { - return Collections.emptyList(); - } - - List checkers = new ArrayList<>(); - - if (wait.getUrl() != null) { - checkers.add(getUrlWaitChecker(imageConfig.getDescription(), projectProperties, wait)); - } - - if (wait.getLog() != null) { - log.debug("LogWaitChecker: Waiting on %s", wait.getLog()); - checkers.add(new LogWaitChecker(wait.getLog(), dockerAccess, containerId, log)); - } - - if (wait.getTcp() != null) { - try { - Container container = queryService.getMandatoryContainer(containerId); - checkers.add(getTcpWaitChecker(container, imageConfig.getDescription(), projectProperties, wait.getTcp())); - } catch (DockerAccessException e) { - throw new IOException("Unable to access container " + containerId, e); - } - } - - if (wait.getHealthy() == Boolean.TRUE) { - checkers.add(new HealthCheckChecker(dockerAccess, containerId, imageConfig.getDescription(), log)); - } - - if (wait.getExit() != null) { - checkers.add(new ExitCodeChecker(wait.getExit(), queryService, containerId)); - } - return checkers; - } - - private WaitConfiguration getWaitConfiguration(ImageConfiguration imageConfig) { - return imageConfig.getRunConfiguration().getWait(); - } - - // ================================================================================================================= - - private WaitChecker getUrlWaitChecker(String imageConfigDesc, - Properties projectProperties, - WaitConfiguration wait) { - String waitUrl = StringSubstitutor.replace(wait.getUrl(), projectProperties); - WaitConfiguration.HttpConfiguration httpConfig = wait.getHttp(); - HttpPingChecker checker; - if (httpConfig != null) { - checker = new HttpPingChecker(waitUrl, httpConfig.getMethod(), httpConfig.getStatus(), httpConfig.isAllowAllHosts()); - log.info("%s: Waiting on url %s with method %s for status %s.", - imageConfigDesc, waitUrl, httpConfig.getMethod(), httpConfig.getStatus()); - } else { - checker = new HttpPingChecker(waitUrl); - log.info("%s: Waiting on url %s.", imageConfigDesc, waitUrl); - } - return checker; - } - - private WaitChecker getTcpWaitChecker(Container container, - String imageConfigDesc, - Properties projectProperties, - WaitConfiguration.TcpConfiguration tcpConfig) { - List ports = new ArrayList<>(); - - List portsConfigured = getTcpPorts(tcpConfig); - String host = getTcpHost(tcpConfig, projectProperties); - WaitConfiguration.TcpConfigMode mode = getTcpMode(tcpConfig, host); - - if (mode == WaitConfiguration.TcpConfigMode.mapped) { - for (int port : portsConfigured) { - Container.PortBinding binding = container.getPortBindings().get(port + "/tcp"); - if (binding == null) { - throw new IllegalArgumentException( - String.format("Cannot watch on port %d, since there is no network binding", port)); - } - ports.add(binding.getHostPort()); - } - log.info("%s: Waiting for mapped ports %s on host %s", imageConfigDesc, ports, host); - } else { - final String networkMode = container.getNetworkMode(); - log.info("%s: Network mode: %s", imageConfigDesc, networkMode); - if (networkMode == null || networkMode.isEmpty() || "bridge".equals(networkMode)) { - // Safe mode when network mode is not present - host = container.getIPAddress(); - } else if (!"host".equals(networkMode)) { - // Custom network - host = container.getCustomNetworkIpAddresses().get(networkMode); - } - ports = portsConfigured; - log.info("%s: Waiting for ports %s directly on container with IP (%s).", - imageConfigDesc, ports, host); - } - return new TcpPortChecker(host, ports); - } - - private List getTcpPorts(WaitConfiguration.TcpConfiguration tcpConfig) { - List portsConfigured = tcpConfig.getPorts(); - if (portsConfigured == null || portsConfigured.isEmpty()) { - throw new IllegalArgumentException("TCP wait config given but no ports to wait on"); - } - return portsConfigured; - } - - private WaitConfiguration.TcpConfigMode getTcpMode(WaitConfiguration.TcpConfiguration tcpConfig, String host) { - WaitConfiguration.TcpConfigMode mode = tcpConfig.getMode(); - if (mode == null) { - return "localhost".equals(host) ? WaitConfiguration.TcpConfigMode.direct : WaitConfiguration.TcpConfigMode.mapped; - } else { - return mode; - } - } - - private String getTcpHost(WaitConfiguration.TcpConfiguration tcpConfig, Properties projectProperties) { - String host = tcpConfig.getHost(); - if (host == null) { - // Host defaults to ${docker.host.address}. - host = projectProperties.getProperty("docker.host.address"); - } - return host; - } - - private class ContainerRunningPrecondition implements WaitUtil.Precondition { - private final String containerId; - private final DockerAccess dockerAccess; - private Integer exitCode; - - ContainerRunningPrecondition(DockerAccess dockerAccess, String containerId) { - this.dockerAccess = dockerAccess; - this.containerId = containerId; - } - - @Override - public boolean isOk() { - try { - exitCode = dockerAccess.getContainer(containerId).getExitCode(); - return exitCode == null; - } catch (DockerAccessException e) { - return false; - } - } - - @Override - public void cleanup() { - if (exitCode != null && log.isVerboseEnabled()) { - // if not running, probably something went wrong during startup: spit out logs - new LogDispatcher(dockerAccess).fetchContainerLog(containerId, LogOutputSpec.DEFAULT); - dockerAccess.getLogSync(containerId, new DefaultLogCallback( - LogOutputSpec.builder() - .colorString("black", true) - .prefix(containerId.substring(0, 6)) - .useColor(true) - .logStdout(true) - .build() - )); - - } - } - - Integer getExitCode() { - return exitCode; - } - } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WatchService.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WatchService.java index 999d4965f1..7282332e3b 100755 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WatchService.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/WatchService.java @@ -21,12 +21,8 @@ import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; import org.eclipse.jkube.kit.build.api.assembly.AssemblyFiles; -import org.eclipse.jkube.kit.build.api.model.PortMapping; -import org.eclipse.jkube.kit.build.service.docker.helper.StartContainerExecutor; -import org.eclipse.jkube.kit.build.service.docker.helper.Task; import org.eclipse.jkube.kit.build.service.docker.watch.CopyFilesTask; import org.eclipse.jkube.kit.build.service.docker.watch.ExecTask; import org.eclipse.jkube.kit.build.service.docker.watch.WatchContext; @@ -34,8 +30,6 @@ import org.eclipse.jkube.kit.common.AssemblyFileEntry; import org.eclipse.jkube.kit.common.KitLogger; import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.WaitConfiguration; import org.eclipse.jkube.kit.config.image.WatchImageConfiguration; import org.eclipse.jkube.kit.config.image.WatchMode; import org.eclipse.jkube.kit.common.JKubeConfiguration; @@ -49,33 +43,23 @@ public class WatchService { private final ArchiveService archiveService; private final BuildService buildService; - private final QueryService queryService; - private final RunService runService; private final KitLogger log; - public WatchService(ArchiveService archiveService, BuildService buildService, QueryService queryService, RunService - runService, KitLogger log) { + public WatchService(ArchiveService archiveService, BuildService buildService, KitLogger log) { this.archiveService = archiveService; this.buildService = buildService; - this.queryService = queryService; - this.runService = runService; this.log = log; } - public synchronized void watch(WatchContext context, JKubeConfiguration buildContext, List images) - throws IOException { - - // Important to be be a single threaded scheduler since watch jobs must run serialized + public synchronized void watch(WatchContext context, List images) throws IOException { + // Important to be a single threaded scheduler since watch jobs must run serialized ScheduledExecutorService executor = null; try { executor = Executors.newSingleThreadScheduledExecutor(); - for (ImageConfiguration imageConfig : runService.getImagesConfigsInOrder(queryService, images)) { - - String imageId = queryService.getImageId(imageConfig.getName()); - String containerId = runService.lookupContainer(imageConfig.getName()); + for (ImageConfiguration imageConfig : images) { - ImageWatcher watcher = new ImageWatcher(imageConfig, context, imageId, containerId); + ImageWatcher watcher = new ImageWatcher(imageConfig, context); long interval = watcher.getInterval(); WatchMode watchMode = watcher.getWatchMode(imageConfig); @@ -91,24 +75,16 @@ public synchronized void watch(WatchContext context, JKubeConfiguration buildCon } if (watcher.isBuild()) { - schedule(executor, createBuildWatchTask(watcher, context.getBuildContext(), watchMode == WatchMode.both, buildContext), interval); + schedule(executor, createBuildWatchTask(watcher, context.getBuildContext()), interval); tasks.add("rebuilding"); } } - if (watcher.isRun() && watcher.getContainerId() != null) { - schedule(executor, createRestartWatchTask(watcher), interval); - tasks.add("restarting"); - } - if (!tasks.isEmpty()) { log.info("%s: Watch for %s", imageConfig.getDescription(), String.join(" and ", tasks)); } } log.info("Waiting ..."); - if (!context.isKeepRunning()) { - runService.addShutdownHookForStoppingContainers(context.isKeepContainer(), context.isRemoveVolumes(), context.isAutoCreateCustomNetworks()); - } wait(); } catch (InterruptedException e) { log.warn("Interrupted"); @@ -127,29 +103,25 @@ private void schedule(ScheduledExecutorService executor, Runnable runnable, long private Runnable createCopyWatchTask(final ImageWatcher watcher, final JKubeConfiguration jKubeConfiguration) throws IOException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); - final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, jKubeConfiguration); - return () -> { List entries = files.getUpdatedEntriesAndRefresh(); - if (!entries.isEmpty()) { - try { - log.info("%s: Assembly changed. Copying changed files to container...", imageConfig.getDescription()); - File changedFilesArchive = archiveService.createChangedFilesArchive(entries, files.getAssemblyDirectory(), - imageConfig.getName(), jKubeConfiguration); - copyFilesToContainer(changedFilesArchive, watcher); - callPostExec(watcher); - } catch (IOException | WatchException e) { - log.error("%s: Error when copying files to container %s: %s", - imageConfig.getDescription(), watcher.getContainerId(), e.getMessage()); - - + if (!entries.isEmpty()) { + try { + log.info("%s: Assembly changed. Copying changed files to container...", imageConfig.getDescription()); + File changedFilesArchive = archiveService.createChangedFilesArchive(entries, files.getAssemblyDirectory(), + imageConfig.getName(), jKubeConfiguration); + copyFilesToContainer(changedFilesArchive, watcher); + callPostExec(watcher); + } catch (IOException | WatchException e) { + log.error("%s: Error when copying files: %s", + imageConfig.getDescription(), e.getMessage()); } } }; } - void copyFilesToContainer(File changedFilesArchive, ImageWatcher watcher) throws IOException, WatchException { + private void copyFilesToContainer(File changedFilesArchive, ImageWatcher watcher) throws IOException, WatchException { final CopyFilesTask cft = watcher.getWatchContext().getContainerCopyTask(); if (cft != null) { cft.copy(changedFilesArchive); @@ -166,11 +138,10 @@ void callPostExec(ImageWatcher watcher) throws IOException, WatchException { } } - Runnable createBuildWatchTask(final ImageWatcher watcher, - final JKubeConfiguration mojoParameters, final boolean doRestart, final JKubeConfiguration buildContext) + Runnable createBuildWatchTask(final ImageWatcher watcher, final JKubeConfiguration jKubeConfiguration) throws IOException { final ImageConfiguration imageConfig = watcher.getImageConfiguration(); - final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, mojoParameters); + final AssemblyFiles files = archiveService.getAssemblyFiles(imageConfig, jKubeConfiguration); if (files.isEmpty()) { log.error("No assembly files for %s. Are you sure you invoked together with the `package` goal?", imageConfig.getDescription()); throw new IOException("No files to watch found for " + imageConfig); @@ -186,103 +157,19 @@ Runnable createBuildWatchTask(final ImageWatcher watcher, log.info("%s: Customizing the image ...", imageConfig.getDescription()); watcher.getWatchContext().getImageCustomizer().execute(imageConfig); } - buildService.buildImage(imageConfig, null, buildContext); - - String name = imageConfig.getName(); - watcher.setImageId(queryService.getImageId(name)); - restartContainerAndCallPostGoal(watcher, doRestart); - } catch (Exception e) { - log.error("%s: Error when rebuilding - %s", imageConfig.getDescription(), e); - } - } - }; - } - - - private void callPostGoal(ImageWatcher watcher) { - Optional.ofNullable(watcher.getWatchContext().getPostGoalTask()).ifPresent(Runnable::run); - } - - private Runnable createRestartWatchTask(final ImageWatcher watcher) { - - final String imageName = watcher.getImageName(); - - return () -> { + buildService.buildImage(imageConfig, null, jKubeConfiguration); - try { - String currentImageId = queryService.getImageId(imageName); - String oldValue = watcher.getAndSetImageId(currentImageId); - if (!currentImageId.equals(oldValue)) { - restartContainerAndCallPostGoal(watcher, true); + if (watcher.isRun()) { + watcher.getWatchContext().getContainerRestarter().execute(watcher); } + Optional.ofNullable(watcher.getWatchContext().getPostGoalTask()).ifPresent(Runnable::run); } catch (Exception e) { - log.warn("%s: Error when restarting image - %s", watcher.getImageConfiguration().getDescription(), e); + log.error("%s: Error when rebuilding - %s", imageConfig.getDescription(), e); } - }; - } - - - void restartContainerAndCallPostGoal(ImageWatcher watcher, boolean isRestartRequired) throws Exception { - if (isRestartRequired) { - restartContainer(watcher); - } - callPostGoal(watcher); - } - - private void restartContainer(ImageWatcher watcher) throws Exception { - Task restarter = watcher.getWatchContext().getContainerRestarter(); - if (restarter == null) { - restarter = defaultContainerRestartTask(); - } - - // Restart - restarter.execute(watcher); - } - - private Task defaultContainerRestartTask() { - return watcher -> { - // Stop old one - ImageConfiguration imageConfig = watcher.getImageConfiguration(); - PortMapping mappedPorts = runService.createPortMapping(imageConfig.getRunConfiguration(), watcher.getWatchContext().getBuildContext().getProject().getProperties()); - String id = watcher.getContainerId(); - - String optionalPreStop = getPreStopCommand(imageConfig); - if (optionalPreStop != null) { - runService.execInContainer(id, optionalPreStop, watcher.getImageConfiguration()); } - runService.stopPreviouslyStartedContainer(id, false, false); - - // Start new one - StartContainerExecutor helper = StartContainerExecutor.builder() - .dispatcher(watcher.watchContext.getDispatcher()) - .follow(watcher.watchContext.isFollow()) - .log(log) - .portMapping(mappedPorts) - .gavLabel(watcher.watchContext.getGavLabel()) - .projectProperties(watcher.watchContext.getBuildContext().getProject().getProperties()) - .basedir(watcher.watchContext.getBuildContext().getProject().getBaseDirectory()) - .imageConfig(imageConfig) - .hub(watcher.watchContext.getHub()) - .logOutputSpecFactory(watcher.watchContext.getLogOutputSpecFactory()) - .showLogs(watcher.watchContext.getShowLogs()) - .containerNamePattern(watcher.watchContext.getContainerNamePattern()) - .buildDate(watcher.watchContext.getBuildTimestamp()) - .build(); - - String containerId = helper.startContainers(); - - watcher.setContainerId(containerId); }; } - private String getPreStopCommand(ImageConfiguration imageConfig) { - return Optional.ofNullable(imageConfig.getRunConfiguration()) - .map(RunImageConfiguration::getWait) - .map(WaitConfiguration::getExec) - .map(WaitConfiguration.ExecConfiguration::getPreStop) - .orElse(null); - } - // =============================================================================================================== // Helper class for holding state and parameter when watching images @@ -291,17 +178,13 @@ public static class ImageWatcher { private final ImageConfiguration imageConfig; private final WatchContext watchContext; private final WatchMode mode; - private final AtomicReference imageIdRef; - private final AtomicReference containerIdRef; private final long interval; private final String postGoal; private final String postExec; - public ImageWatcher(ImageConfiguration imageConfig, WatchContext watchContext, String imageId, String containerIdRef) { + public ImageWatcher(ImageConfiguration imageConfig, WatchContext watchContext) { this.imageConfig = imageConfig; this.watchContext = watchContext; - this.imageIdRef = new AtomicReference<>(imageId); - this.containerIdRef = new AtomicReference<>(containerIdRef); this.interval = getWatchInterval(imageConfig); this.mode = getWatchMode(imageConfig); @@ -309,10 +192,6 @@ public ImageWatcher(ImageConfiguration imageConfig, WatchContext watchContext, S this.postExec = getPostExec(imageConfig); } - public String getContainerId() { - return containerIdRef.get(); - } - public long getInterval() { return interval; } @@ -337,22 +216,10 @@ public ImageConfiguration getImageConfiguration() { return imageConfig; } - public void setImageId(String imageId) { - imageIdRef.set(imageId); - } - - public void setContainerId(String containerId) { - containerIdRef.set(containerId); - } - public String getImageName() { return imageConfig.getName(); } - public String getAndSetImageId(String currentImageId) { - return imageIdRef.getAndSet(currentImageId); - } - public String getPostExec() { return postExec; } diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerCreateConfig.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerCreateConfig.java deleted file mode 100644 index 3b8d4b2ad2..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerCreateConfig.java +++ /dev/null @@ -1,207 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access; - -import java.io.FileNotFoundException; -import java.io.FileReader; -import java.io.IOException; -import java.util.Enumeration; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import org.eclipse.jkube.kit.common.JsonFactory; -import org.eclipse.jkube.kit.common.util.EnvUtil; -import org.eclipse.jkube.kit.common.Arguments; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import org.apache.commons.text.StringSubstitutor; - - -public class ContainerCreateConfig { - - private final JsonObject createConfig = new JsonObject(); - private final String imageName; - - public ContainerCreateConfig(String imageName) { - this.imageName = imageName; - createConfig.addProperty("Image", imageName); - } - - public ContainerCreateConfig binds(List volumes) { - if (volumes != null && !volumes.isEmpty()) { - JsonObject extractedVolumes = new JsonObject(); - - for (String volume : volumes) { - extractedVolumes.add(extractContainerPath(volume), - new JsonObject()); - } - createConfig.add("Volumes", extractedVolumes); - } - return this; - } - - public ContainerCreateConfig command(Arguments command) { - if (command != null) { - createConfig.add("Cmd", JsonFactory.newJsonArray(command.asStrings())); - } - return this; - } - - public ContainerCreateConfig domainname(String domainname) { - return add("Domainname", domainname); - } - - public ContainerCreateConfig entrypoint(Arguments entrypoint) { - if (entrypoint != null) { - createConfig.add("Entrypoint", JsonFactory.newJsonArray(entrypoint.asStrings())); - } - return this; - } - - public ContainerCreateConfig environment(String envPropsFile, Map env, Properties mavenProps) { - - Properties envProps = new Properties(); - if (env != null && env.size() > 0) { - for (Map.Entry entry : env.entrySet()) { - String value = entry.getValue(); - if (value == null) { - value = ""; - } else if(value.matches("^\\+\\$\\{.*}$")) { - /* - * This case is to handle the Maven interpolation issue which used - * to occur when using ${..} only without any suffix. - */ - value = value.substring(1); - } - envProps.put(entry.getKey(), StringSubstitutor.replace(value, mavenProps)); - } - } - if (envPropsFile != null) { - // Props from external file take precedence - addPropertiesFromFile(envPropsFile, envProps); - } - - if (envProps.size() > 0) { - addEnvironment(envProps); - } - return this; - } - - public ContainerCreateConfig labels(Map labels) { - if (labels != null && labels.size() > 0) { - createConfig.add("Labels", JsonFactory.newJsonObject(labels)); - } - return this; - } - - public ContainerCreateConfig exposedPorts(Set portSpecs) { - if (portSpecs != null && !portSpecs.isEmpty()) { - JsonObject exposedPorts = new JsonObject(); - for (String portSpec : portSpecs) { - exposedPorts.add(portSpec, new JsonObject()); - } - createConfig.add("ExposedPorts", exposedPorts); - } - return this; - } - - public String getImageName() { - return imageName; - } - - public ContainerCreateConfig hostname(String hostname) { - return add("Hostname", hostname); - } - - public ContainerCreateConfig user(String user) { - return add("User", user); - } - - public ContainerCreateConfig workingDir(String workingDir) { - return add("WorkingDir", workingDir); - } - - public ContainerCreateConfig hostConfig(ContainerHostConfig startConfig) { - return add("HostConfig", startConfig.toJsonObject()); - } - - public ContainerCreateConfig networkingConfig(ContainerNetworkingConfig networkingConfig) { - return add("NetworkingConfig", networkingConfig.toJsonObject()); - } - - /** - * Get JSON which is used for creating a container - * - * @return string representation for JSON representing creating a container - */ - public String toJson() { - return createConfig.toString(); - } - - // ======================================================================= - - private ContainerCreateConfig add(String name, String value) { - if (value != null) { - createConfig.addProperty(name, value); - } - return this; - } - - private ContainerCreateConfig add(String name, JsonObject value) { - if (value != null) { - createConfig.add(name, value); - } - return this; - } - - private String extractContainerPath(String volume) { - String path = EnvUtil.fixupPath(volume); - if (path.contains(":")) { - String[] parts = path.split(":"); - if (parts.length > 1) { - return parts[1]; - } - } - return path; - } - - private void addEnvironment(Properties envProps) { - JsonArray containerEnv = new JsonArray(); - Enumeration keys = envProps.keys(); - while (keys.hasMoreElements()) { - String key = (String) keys.nextElement(); - String value = envProps.getProperty(key); - if (value == null) { - value = ""; - } - containerEnv.add(key + "=" + value); - } - createConfig.add("Env", containerEnv); - } - - private void addPropertiesFromFile(String envPropsFile, Properties envProps) { - // External properties override internally specified properties - try (FileReader reader = new FileReader(envPropsFile)) { - envProps.load(reader); - } catch (FileNotFoundException e) { - throw new IllegalArgumentException(String.format("Cannot find environment property file '%s'", envPropsFile)); - } catch (IOException e) { - throw new IllegalArgumentException(String.format("Error while loading environment properties: %s", e.getMessage()), e); - } - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerHostConfig.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerHostConfig.java deleted file mode 100644 index e244a6cd20..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerHostConfig.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access; - -import com.google.gson.JsonArray; -import com.google.gson.JsonObject; -import org.eclipse.jkube.kit.build.api.model.PortMapping; -import org.eclipse.jkube.kit.config.image.LogConfiguration; -import org.eclipse.jkube.kit.config.image.UlimitConfig; -import org.eclipse.jkube.kit.common.JsonFactory; -import org.eclipse.jkube.kit.common.util.EnvUtil; - -import java.net.InetAddress; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; - -public class ContainerHostConfig { - - final JsonObject startConfig = new JsonObject(); - - public ContainerHostConfig() {} - - public ContainerHostConfig binds(List bind) { - if (bind != null && !bind.isEmpty()) { - JsonArray binds = new JsonArray(); - - for (String volume : bind) { - volume = EnvUtil.fixupPath(volume); - - if (volume.contains(":")) { - binds.add(volume); - } - } - startConfig.add("Binds", binds); - } - return this; - } - - public ContainerHostConfig capAdd(List capAdd) { - return addAsArray("CapAdd", capAdd); - } - - public ContainerHostConfig capDrop(List capDrop) { - return addAsArray("CapDrop", capDrop); - } - - public ContainerHostConfig securityOpts(List securityOpt) { - return addAsArray("SecurityOpt", securityOpt); - } - - public ContainerHostConfig memory(Long memory) { - return add("Memory", memory); - } - - public ContainerHostConfig memorySwap(Long memorySwap) { - return add("MemorySwap", memorySwap); - } - - public ContainerHostConfig dns(List dns) { - return addAsArray("Dns", dns); - } - - public ContainerHostConfig networkMode(String net) { - return add("NetworkMode",net); - } - - public ContainerHostConfig dnsSearch(List dnsSearch) { - return addAsArray("DnsSearch", dnsSearch); - } - - public ContainerHostConfig cpuShares(Long cpuShares) { - return add("CpuShares", cpuShares); - } - - public ContainerHostConfig cpus(Long cpus) { - return add ("NanoCpus", cpus); - } - - public ContainerHostConfig cpuSet(String cpuSet) { - return add("CpusetCpus", cpuSet); - } - - public ContainerHostConfig extraHosts(List extraHosts) { - if (extraHosts != null) { - List mapped = new ArrayList<>(); - for (int i = 0; i < extraHosts.size(); i++) { - String[] parts = extraHosts.get(i).split(":"); - if (parts.length == 1) { - throw new IllegalArgumentException("extraHosts must be in the form "); - } - - try { - mapped.add(i, parts[0] + ":" + InetAddress.getByName(parts[1]).getHostAddress()); - } catch (UnknownHostException e) { - throw new IllegalArgumentException("unable to resolve ip address for " + parts[1], e); - } - } - return addAsArray("ExtraHosts", mapped); - } - return this; - } - - public ContainerHostConfig volumesFrom(List volumesFrom) { - return addAsArray("VolumesFrom", volumesFrom); - } - - public ContainerHostConfig ulimits(List ulimitsConfig) { - if (ulimitsConfig != null && !ulimitsConfig.isEmpty()) { - JsonArray ulimits = new JsonArray(); - for (UlimitConfig ulimit : ulimitsConfig) { - JsonObject ulimitConfigJson = new JsonObject(); - ulimitConfigJson.addProperty("Name", ulimit.getName()); - addIfNotNull(ulimitConfigJson, "Hard", ulimit.getHard()); - addIfNotNull(ulimitConfigJson, "Soft", ulimit.getSoft()); - ulimits.add(ulimitConfigJson); - } - - startConfig.add("Ulimits", ulimits); - } - return this; - } - - private void addIfNotNull(JsonObject json, String key, Integer value) { - if (value != null) { - json.addProperty(key, value); - } - } - - public ContainerHostConfig links(List links) { - return addAsArray("Links", links); - } - - public ContainerHostConfig portBindings(PortMapping portMapping) { - JsonObject portBindings = portMapping.toDockerPortBindingsJson(); - if (portBindings != null) { - startConfig.add("PortBindings", portBindings); - } - return this; - } - - public ContainerHostConfig privileged(Boolean privileged) { - return add("Privileged", privileged); - } - - public ContainerHostConfig tmpfs(List mounts) { - if (mounts != null && !mounts.isEmpty()) { - JsonObject tmpfs = new JsonObject(); - for (String mount : mounts) { - int idx = mount.indexOf(':'); - if (idx > -1) { - tmpfs.addProperty(mount.substring(0,idx), mount.substring(idx+1)); - } else { - tmpfs.addProperty(mount, ""); - } - } - startConfig.add("Tmpfs", tmpfs); - } - return this; - } - - public ContainerHostConfig shmSize(Long shmSize) { - return add("ShmSize", shmSize); - } - - public ContainerHostConfig restartPolicy(String name, int retry) { - if (name != null) { - JsonObject policy = new JsonObject(); - policy.addProperty("Name", name); - policy.addProperty("MaximumRetryCount", retry); - - startConfig.add("RestartPolicy", policy); - } - return this; - } - - public ContainerHostConfig logConfig(LogConfiguration logConfig) { - if (logConfig != null) { - LogConfiguration.LogDriver logDriver = logConfig.getDriver(); - if (logDriver != null) { - JsonObject logConfigJson = new JsonObject(); - logConfigJson.addProperty("Type", logDriver.getName()); - - Map opts = logDriver.getOpts(); - if (opts != null && opts.size() > 0) { - JsonObject config = new JsonObject(); - for (Map.Entry logOpt : opts.entrySet()) { - config.addProperty(logOpt.getKey(), logOpt.getValue()); - } - logConfigJson.add("Config", config); - } - - startConfig.add("LogConfig", logConfigJson); - } - } - return this; - } - - public ContainerHostConfig readonlyRootfs(Boolean readOnly) { - return add("ReadonlyRootfs", readOnly); - } - - public ContainerHostConfig autoRemove(Boolean autoRemove) { - return add("AutoRemove", autoRemove); - } - - /** - * Get JSON which is used for starting a container - * - * @return string representation for JSON representing the configuration for starting a container - */ - public String toJson() { - return startConfig.toString(); - } - - public JsonObject toJsonObject() { - return startConfig; - } - - ContainerHostConfig addAsArray(String propKey, List props) { - if (props != null) { - startConfig.add(propKey, JsonFactory.newJsonArray(props)); - } - return this; - } - - private ContainerHostConfig add(String name, String value) { - if (value != null) { - startConfig.addProperty(name, value); - } - return this; - } - - private ContainerHostConfig add(String name, Boolean value) { - if (value != null) { - startConfig.addProperty(name, value); - } - return this; - } - - private ContainerHostConfig add(String name, Long value) { - if (value != null) { - startConfig.addProperty(name, value); - } - return this; - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerNetworkingConfig.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerNetworkingConfig.java deleted file mode 100644 index 8a94508c28..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ContainerNetworkingConfig.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access; - -import com.google.gson.JsonObject; -import org.eclipse.jkube.kit.config.image.NetworkConfig; -import org.eclipse.jkube.kit.common.JsonFactory; - - -public class ContainerNetworkingConfig { - - private final JsonObject networkingConfig = new JsonObject(); - - /** - * Add networking aliases to a custom network - * - * @param config network config as configured in the pom.xml - * @return this configuration - */ - public ContainerNetworkingConfig aliases(NetworkConfig config) { - JsonObject endPoints = new JsonObject(); - endPoints.add("Aliases", JsonFactory.newJsonArray(config.getAliases())); - - JsonObject endpointConfigMap = new JsonObject(); - endpointConfigMap.add(config.getCustomNetwork(), endPoints); - - networkingConfig.add("EndpointsConfig", endpointConfigMap); - return this; - } - - public String toJson() { - return networkingConfig.toString(); - } - - public JsonObject toJsonObject() { - return networkingConfig; - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/DockerAccess.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/DockerAccess.java index 837289b468..ac828d79e6 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/DockerAccess.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/DockerAccess.java @@ -14,56 +14,18 @@ package org.eclipse.jkube.kit.build.service.docker.access; import org.eclipse.jkube.kit.build.api.auth.AuthConfig; -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.api.model.ContainerDetails; -import org.eclipse.jkube.kit.build.api.model.ExecDetails; -import org.eclipse.jkube.kit.build.api.model.Network; -import org.eclipse.jkube.kit.build.api.model.NetworkCreateConfig; -import org.eclipse.jkube.kit.build.api.model.VolumeCreateConfig; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogCallback; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogGetHandle; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpec; import org.eclipse.jkube.kit.common.archive.ArchiveCompression; -import org.eclipse.jkube.kit.common.Arguments; import java.io.File; -import java.util.List; /** * Access to the Docker API which - * provides the methods needed bu this maven plugin. + * provides the methods needed by this maven plugin. * * @author roland - * @since 04.04.14 */ public interface DockerAccess { - /** - * Get the API version of the running server - * - * @return api version in the form "1.24" - * @throws DockerAccessException if the api version could not be obtained - */ - String getServerApiVersion() throws DockerAccessException; - - /** - * Get a container - * - * @param containerIdOrName container id or name - * @return ContainerDetails representing the container or null if none could be found - * @throws DockerAccessException if the container could not be inspected - */ - ContainerDetails getContainer(String containerIdOrName) throws DockerAccessException; - - /** - * Get an exec container which is the result of executing a command in a running container. - * - * @param containerIdOrName exec container id or name - * @return ExecDetails representing the container or null if none could be found - * @throws DockerAccessException if the container could not be inspected - */ - ExecDetails getExecContainer(String containerIdOrName) throws DockerAccessException; - /** * Check whether the given name exists as image at the docker daemon * @@ -82,106 +44,6 @@ public interface DockerAccess { */ String getImageId(String name) throws DockerAccessException; - /** - * Get all containers which are build from an image. By default only the last containers are considered but this - * can be tuned with a global parameters. - * - * @param image for which its container are looked up - * @param all whether to fetch also stopped containers. If false only running containers are returned - * @return list of Container objects or an empty list if none is found - * @throws DockerAccessException if the request fails - */ - List getContainersForImage(String image, boolean all) throws DockerAccessException; - - /** - * Starts a previously set up exec instance (via {@link #createExecContainer(String, Arguments)} container - * this API sets up a session with the exec command. Output is streamed to the log. This methods - * returns only when the exec command has finished (i.e this method calls the command in a non-detached mode). - * - * @param containerId id of the exec container - * @param outputSpec how to print out the output of the command - * @throws DockerAccessException if the container could not be created. - */ - void startExecContainer(String containerId, LogOutputSpec outputSpec) throws DockerAccessException; - - /** - * Sets up an exec instance for a running container id - * - * @param containerId id of the running container which the exec container will be created for - * @param arguments container exec commands to run - * @return container created - * @throws DockerAccessException if the container could not be created. - */ - String createExecContainer(String containerId, Arguments arguments) throws DockerAccessException; - - /** - * Create a container from the given image. - * - *

    The container id will be set on the container upon successful creation.

    - * - * @param configuration container configuration - * @param containerName name container should be created with or null for a docker provided name - * @return created container - * @throws DockerAccessException if the container could not be created. - */ - String createContainer(ContainerCreateConfig configuration, String containerName) throws DockerAccessException; - - /** - * Start a container. - * - * @param containerId id of the container to start - * @throws DockerAccessException if the container could not be started. - */ - void startContainer(String containerId) throws DockerAccessException; - - /** - * Stop a container. - * - * @param containerId the container id - * @param killWait the time to wait between stop and kill (in seconds) - * @throws DockerAccessException if the container could not be stopped. - */ - void stopContainer(String containerId, int killWait) throws DockerAccessException; - - /** Copy an archive (must be a tar) into a running container - * Get all containers matching a certain label. This might not be a cheap operation especially if many containers - * are running. Use with care. - * - * @param containerId container to copy into - * @param archive local archive to copy into - * @param targetPath target path to use - * @throws DockerAccessException if the archive could not be copied - */ - void copyArchive(String containerId, File archive, String targetPath) - throws DockerAccessException; - - /** - * Get logs for a container up to now synchronously. - * - * @param containerId container id - * @param callback which is called for each line received - */ - void getLogSync(String containerId, LogCallback callback); - - /** - * Get logs asynchronously. This call will start a thread in the background for doing the request. - * It returns a handle which can be used to abort the request on demand. - * - * @param containerId id of the container for which to fetch the logs - * @param callback to call when log data arrives - * @return handle for managing the lifecycle of the thread - */ - LogGetHandle getLogAsync(String containerId, LogCallback callback); - - /** - * Remove a container with the given id - * - * @param containerId container id for the container to remove - * @param removeVolumes if true, will remove any volumes associated to container - * @throws DockerAccessException if the container couldn't be removed. - */ - void removeContainer(String containerId, boolean removeVolumes) throws DockerAccessException; - /** * Load an image from an archive. * @@ -218,7 +80,7 @@ void copyArchive(String containerId, File archive, String targetPath) void pushImage(String image, AuthConfig authConfig, String registry, int retries) throws DockerAccessException; /** - * Create an docker image from a given archive + * Create a docker image from a given archive * * @param image name of the image to build or null if none should be used * @param dockerArchive from which the docker image should be build @@ -258,32 +120,6 @@ void copyArchive(String containerId, File archive, String targetPath) */ void saveImage(String image, String filename, ArchiveCompression compression) throws DockerAccessException; - /** - * List all networks - * - * @return list of Network objects - * @throws DockerAccessException if the networks could not be listed - */ - List listNetworks() throws DockerAccessException; - - /** - * Create a custom network from the given configuration. - * - * @param configuration network configuration - * @return created network - * @throws DockerAccessException if the container could not be created. - */ - String createNetwork(NetworkCreateConfig configuration) throws DockerAccessException; - - /** - * Remove a custom network - * - * @param networkId network to remove - * @return true if an network was removed, false if none was removed - * @throws DockerAccessException if an image cannot be removed - */ - boolean removeNetwork(String networkId) throws DockerAccessException; - /** * Lifecycle method for this access class which must be called before any other method is called. * @@ -296,21 +132,5 @@ void copyArchive(String containerId, File archive, String targetPath) * cleaning up things. */ void shutdown(); - - /** - * Create a volume - * - * @param configuration volume configuration - * @return the name of the Volume - * @throws DockerAccessException if the volume could not be created. - */ - String createVolume(VolumeCreateConfig configuration) throws DockerAccessException; - - /** - * Removes a volume. It is a no-op if the volume does not exist. - * @param name volume name to remove - * @throws DockerAccessException if the volume could not be removed - */ - void removeVolume(String name) throws DockerAccessException; } diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ExecException.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ExecException.java deleted file mode 100644 index 87daf779f3..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/ExecException.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access; - -import org.eclipse.jkube.kit.build.api.model.ContainerDetails; -import org.eclipse.jkube.kit.build.api.model.ExecDetails; - -import java.util.Arrays; - - -/** - * Exception thrown when the execution of an exec container failed - * - * @author roland - * @since 18.01.18 - */ -public class ExecException extends Exception { - public ExecException(ExecDetails details, ContainerDetails container) { - super(String.format( - "Executing '%s' with args '%s' inside container '%s' [%s](%s) resulted in a non-zero exit code: %d", - details.getEntryPoint(), - Arrays.toString(details.getArguments()), - container.getName(), - container.getImage(), - container.getId(), - details.getExitCode())); - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/DockerAccessWithHcClient.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/DockerAccessWithHcClient.java index 73934995ac..dea5a02f40 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/DockerAccessWithHcClient.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/hc/DockerAccessWithHcClient.java @@ -17,30 +17,16 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.LineNumberReader; import java.io.OutputStream; import java.net.URI; -import java.util.ArrayList; import java.util.Collections; -import java.util.List; import java.util.Map; import java.util.Objects; import com.google.gson.JsonArray; -import com.google.gson.JsonElement; import com.google.gson.JsonObject; -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.api.model.ContainerDetails; -import org.eclipse.jkube.kit.build.api.model.ContainersListElement; -import org.eclipse.jkube.kit.build.api.model.ExecDetails; -import org.eclipse.jkube.kit.build.api.model.Network; -import org.eclipse.jkube.kit.build.api.model.NetworkCreateConfig; -import org.eclipse.jkube.kit.build.api.model.NetworksListElement; -import org.eclipse.jkube.kit.build.api.model.VolumeCreateConfig; import org.eclipse.jkube.kit.build.api.auth.AuthConfig; import org.eclipse.jkube.kit.build.service.docker.access.BuildOptions; -import org.eclipse.jkube.kit.build.service.docker.access.ContainerCreateConfig; import org.eclipse.jkube.kit.build.service.docker.access.CreateImageOptions; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; @@ -51,18 +37,10 @@ import org.eclipse.jkube.kit.build.service.docker.access.hc.unix.UnixSocketClientBuilder; import org.eclipse.jkube.kit.build.service.docker.access.hc.util.ClientBuilder; import org.eclipse.jkube.kit.build.service.docker.access.hc.win.NamedPipeClientBuilder; -import org.eclipse.jkube.kit.build.service.docker.access.log.DefaultLogCallback; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogCallback; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogGetHandle; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpec; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogRequestor; -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; import org.eclipse.jkube.kit.common.JsonFactory; import org.eclipse.jkube.kit.common.KitLogger; -import org.eclipse.jkube.kit.common.util.EnvUtil; import org.eclipse.jkube.kit.config.image.ImageName; import org.eclipse.jkube.kit.common.archive.ArchiveCompression; -import org.eclipse.jkube.kit.common.Arguments; import org.apache.commons.io.IOUtils; import org.apache.http.HttpHeaders; import org.apache.http.client.HttpResponseException; @@ -73,8 +51,6 @@ import static java.net.HttpURLConnection.HTTP_CREATED; import static java.net.HttpURLConnection.HTTP_INTERNAL_ERROR; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; -import static java.net.HttpURLConnection.HTTP_NOT_MODIFIED; -import static java.net.HttpURLConnection.HTTP_NO_CONTENT; import static java.net.HttpURLConnection.HTTP_OK; /** @@ -145,121 +121,6 @@ public DockerAccessWithHcClient(String baseUrl, this.log = log; } - /** {@inheritDoc} */ - @Override - public String getServerApiVersion() throws DockerAccessException { - try { - String url = urlBuilder.version(); - String response = delegate.get(url, 200); - JsonObject info = JsonFactory.newJsonObject(response); - return info.get("ApiVersion").getAsString(); - } catch (Exception e) { - throw new DockerAccessException(e, "Cannot extract API version from server %s", urlBuilder.getBaseUrl()); - } - } - - @Override - public void startExecContainer(String containerId, LogOutputSpec outputSpec) throws DockerAccessException { - try { - String url = urlBuilder.startExecContainer(containerId); - JsonObject request = new JsonObject(); - request.addProperty("Detach", false); - request.addProperty("Tty", true); - - delegate.post(url, request.toString(), createExecResponseHandler(outputSpec), HTTP_OK); - } catch (Exception e) { - throw new DockerAccessException(e, "Unable to start container id [%s]", containerId); - } - } - - private ResponseHandler createExecResponseHandler(LogOutputSpec outputSpec) { - final LogCallback callback = new DefaultLogCallback(outputSpec); - return response -> { - try (InputStream stream = response.getEntity().getContent(); - LineNumberReader reader = new LineNumberReader(new InputStreamReader(stream))) { - String line; - try { - callback.open(); - while ( (line = reader.readLine()) != null) { - callback.log(1, new Timestamp(), line); - } - } catch (LogCallback.DoneException e) { - // Ok, we stop here ... - } finally { - callback.close(); - } - } - return null; - }; - } - - @Override - public String createExecContainer(String containerId, Arguments arguments) throws DockerAccessException { - String url = urlBuilder.createExecContainer(containerId); - JsonObject request = new JsonObject(); - request.addProperty("Tty", true); - request.addProperty("AttachStdin", false); - request.addProperty("AttachStdout", true); - request.addProperty("AttachStderr", true); - request.add("Cmd", JsonFactory.newJsonArray(arguments.getExec())); - - String execJsonRequest = request.toString(); - try { - String response = delegate.post(url, execJsonRequest, new ApacheHttpClientDelegate.BodyResponseHandler(), HTTP_CREATED); - JsonObject json = JsonFactory.newJsonObject(response); - if (json.has("Warnings")) { - logWarnings(json); - } - - return json.get("Id").getAsString(); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to exec [%s] on container [%s]", request.toString(), - containerId); - } - - } - - @Override - public String createContainer(ContainerCreateConfig containerConfig, String containerName) - throws DockerAccessException { - String createJson = containerConfig.toJson(); - log.debug("Container create config: %s", createJson); - - try { - String url = urlBuilder.createContainer(containerName); - String response = - delegate.post(url, createJson, new ApacheHttpClientDelegate.BodyResponseHandler(), HTTP_CREATED); - JsonObject json = JsonFactory.newJsonObject(response); - logWarnings(json); - - // only need first 12 to id a container - return json.get("Id").getAsString().substring(0, 12); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to create container for [%s]", - containerConfig.getImageName()); - } - } - - @Override - public void startContainer(String containerId) throws DockerAccessException { - try { - String url = urlBuilder.startContainer(containerId); - delegate.post(url, HTTP_NO_CONTENT, HTTP_OK); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to start container id [%s]", containerId); - } - } - - @Override - public void stopContainer(String containerId, int killWait) throws DockerAccessException { - try { - String url = urlBuilder.stopContainer(containerId, killWait); - delegate.post(url, HTTP_NO_CONTENT, HTTP_NOT_MODIFIED); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to stop container id [%s]", containerId); - } - } - @Override public void buildImage(String image, File dockerArchive, BuildOptions options) throws DockerAccessException { try { @@ -270,98 +131,6 @@ public void buildImage(String image, File dockerArchive, BuildOptions options) t } } - @Override - public void copyArchive(String containerId, File archive, String targetPath) - throws DockerAccessException { - try { - String url = urlBuilder.copyArchive(containerId, targetPath); - delegate.put(url, archive, HTTP_OK); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to copy archive %s to container [%s] with path %s", - archive.toPath(), containerId, targetPath); - } - } - - @Override - public void getLogSync(String containerId, LogCallback callback) { - LogRequestor extractor = new LogRequestor(delegate.getHttpClient(), urlBuilder, containerId, callback); - extractor.fetchLogs(); - } - - @Override - public LogGetHandle getLogAsync(String containerId, LogCallback callback) { - LogRequestor extractor = new LogRequestor(delegate.createBasicClient(), urlBuilder, containerId, callback); - extractor.start(); - return extractor; - } - - @Override - public List getContainersForImage(String image, boolean all) throws DockerAccessException { - String url; - String serverApiVersion = getServerApiVersion(); - if (EnvUtil.greaterOrEqualsVersion(serverApiVersion, "1.23")) { - // For Docker >= 1.11 we can use a new filter when listing containers - url = urlBuilder.listContainers(all, "ancestor",image); - } else { - // For older versions (< Docker 1.11) we need to iterate over the containers. - url = urlBuilder.listContainers(all); - } - - try { - String response = delegate.get(url, HTTP_OK); - JsonArray array = JsonFactory.newJsonArray(response); - List containers = new ArrayList<>(); - - for (int i = 0; i < array.size(); i++) { - JsonObject element = array.get(i).getAsJsonObject(); - if (image.equals(element.get("Image").getAsString())) { - containers.add(new ContainersListElement(element)); - } - } - return containers; - } catch (IOException e) { - throw new DockerAccessException(e.getMessage()); - } - } - - @Override - public ContainerDetails getContainer(String containerIdOrName) throws DockerAccessException { - ApacheHttpClientDelegate.HttpBodyAndStatus response = inspectContainer(containerIdOrName); - if (response.getStatusCode() == HTTP_NOT_FOUND) { - return null; - } else { - return new ContainerDetails(JsonFactory.newJsonObject(response.getBody())); - } - } - - @Override - public ExecDetails getExecContainer(String containerIdOrName) throws DockerAccessException { - ApacheHttpClientDelegate.HttpBodyAndStatus response = inspectExecContainer(containerIdOrName); - if (response.getStatusCode() == HTTP_NOT_FOUND) { - return null; - } else { - return new ExecDetails(JsonFactory.newJsonObject(response.getBody())); - } - } - - private ApacheHttpClientDelegate.HttpBodyAndStatus inspectContainer(String containerIdOrName) throws DockerAccessException { - try { - String url = urlBuilder.inspectContainer(containerIdOrName); - return delegate.get(url, new ApacheHttpClientDelegate.BodyAndStatusResponseHandler(), HTTP_OK, HTTP_NOT_FOUND); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to retrieve container name for [%s]", containerIdOrName); - } - } - - private ApacheHttpClientDelegate.HttpBodyAndStatus inspectExecContainer(String containerIdOrName) throws DockerAccessException { - try { - String url = urlBuilder.inspectExecContainer(containerIdOrName); - return delegate.get(url, new ApacheHttpClientDelegate.BodyAndStatusResponseHandler(), HTTP_OK, HTTP_NOT_FOUND); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to retrieve container name for [%s]", containerIdOrName); - } - } - @Override public boolean hasImage(String name) throws DockerAccessException { String url = urlBuilder.inspectImage(name); @@ -391,17 +160,6 @@ private ApacheHttpClientDelegate.HttpBodyAndStatus inspectImage(String name) thr } } - @Override - public void removeContainer(String containerId, boolean removeVolumes) - throws DockerAccessException { - try { - String url = urlBuilder.removeContainer(containerId, removeVolumes); - delegate.delete(url, HTTP_NO_CONTENT); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to remove container [%s]", containerId); - } - } - @Override public void loadImage(String image, File tarArchive) throws DockerAccessException { String url = urlBuilder.loadImage(); @@ -494,98 +252,6 @@ public boolean removeImage(String image, boolean... forceOpt) throws DockerAcces } } - @Override - public List listNetworks() throws DockerAccessException { - String url = urlBuilder.listNetworks(); - - try { - String response = delegate.get(url, HTTP_OK); - JsonArray array = JsonFactory.newJsonArray(response); - List networks = new ArrayList<>(array.size()); - - for (int i = 0; i < array.size(); i++) { - networks.add(new NetworksListElement(array.get(i).getAsJsonObject())); - } - - return networks; - } catch (IOException e) { - throw new DockerAccessException(e.getMessage()); - } - } - - @Override - public String createNetwork(NetworkCreateConfig networkConfig) - throws DockerAccessException { - String createJson = networkConfig.toJson(); - log.debug("Network create config: " + createJson); - try { - String url = urlBuilder.createNetwork(); - String response = - delegate.post(url, createJson, new ApacheHttpClientDelegate.BodyResponseHandler(), HTTP_CREATED); - log.debug(response); - JsonObject json = JsonFactory.newJsonObject(response); - if (json.has("Warnings")) { - logWarnings(json); - } - - // only need first 12 to id a container - return json.get("Id").getAsString().substring(0, 12); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to create network for [%s]", - networkConfig.getName()); - } - } - - @Override - public boolean removeNetwork(String networkId) - throws DockerAccessException { - try { - String url = urlBuilder.removeNetwork(networkId); - int status = delegate.delete(url, HTTP_OK, HTTP_NO_CONTENT, HTTP_NOT_FOUND); - return status == HTTP_OK || status == HTTP_NO_CONTENT; - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to remove network [%s]", networkId); - } - } - - @Override - public String createVolume(VolumeCreateConfig containerConfig) - throws DockerAccessException - { - String createJson = containerConfig.toJson(); - log.debug("Volume create config: %s", createJson); - - try - { - String url = urlBuilder.createVolume(); - String response = - delegate.post(url, - createJson, - new ApacheHttpClientDelegate.BodyResponseHandler(), - HTTP_CREATED); - JsonObject json = JsonFactory.newJsonObject(response); - logWarnings(json); - - return json.get("Name").getAsString(); - } - catch (IOException e) - { - throw new DockerAccessException(e, "Unable to create volume for [%s]", - containerConfig.getName()); - } - } - - @Override - public void removeVolume(String name) throws DockerAccessException { - try { - String url = urlBuilder.removeVolume(name); - delegate.delete(url, HTTP_NO_CONTENT, HTTP_NOT_FOUND); - } catch (IOException e) { - throw new DockerAccessException(e, "Unable to remove volume [%s]", name); - } - } - - // --------------- // Lifecycle methods not needed here @Override @@ -671,18 +337,6 @@ private TemporaryImageHandler tagTemporaryImage(ImageName name, String registry) // =========================================================================================================== - private void logWarnings(JsonObject body) { - if (body.has("Warnings")) { - JsonElement warningsObj = body.get("Warnings"); - if (!warningsObj.isJsonNull()) { - JsonArray warnings = (JsonArray) warningsObj; - for (int i = 0; i < warnings.size(); i++) { - log.warn(warnings.get(i).getAsString()); - } - } - } - } - // Callback for processing response chunks private void logRemoveResponse(JsonArray logElements) { for (int i = 0; i < logElements.size(); i++) { diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/DefaultLogCallback.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/DefaultLogCallback.java deleted file mode 100644 index dd40155477..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/DefaultLogCallback.java +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import com.google.common.io.Files; -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; - -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.PrintStream; -import java.util.HashMap; -import java.util.Map; - -/** - * @author roland - * @since 26/09/15 - */ -public class DefaultLogCallback implements LogCallback { - - private static final Map printStreamMap = new HashMap<>(); - - private final LogOutputSpec outputSpec; - private SharedPrintStream sps; - - public DefaultLogCallback(LogOutputSpec outputSpec) { - this.outputSpec = outputSpec; - } - - @Override - public synchronized void open() throws IOException { - if (this.sps == null) { - String file = outputSpec.getFile(); - if (outputSpec.isLogStdout() || file == null) { - this.sps = new SharedPrintStream(System.out); - } else { - SharedPrintStream cachedPs = printStreamMap.get(file); - if (cachedPs == null) { - Files.createParentDirs(new File(file)); - PrintStream ps = new PrintStream(new FileOutputStream(file), true); - cachedPs = new SharedPrintStream(ps); - printStreamMap.put(file, cachedPs); - } else { - cachedPs.allocate(); - } - this.sps = cachedPs; - } - } - } - - @Override - public synchronized void close() { - if (this.sps != null) { - if (sps.close()) { - String file = outputSpec.getFile(); - if (file != null) { - printStreamMap.remove(file); - } - this.sps = null; - } - } - } - - private PrintStream ps() { - return sps.getPrintStream(); - } - - @Override - public void log(int type, Timestamp timestamp, String txt) { - addLogEntry(ps(), new LogEntry(type, timestamp, txt)); - } - - @Override - public void error(String error) { - ps().println(error); - } - - private void addLogEntry(PrintStream ps, LogEntry logEntry) { - // TODO: Add the entry to a queue, and let the queue be picked up with a small delay from an extra - // thread which then can sort the entries by time before printing it out in order to avoid race conditions. - - LogOutputSpec spec = outputSpec; - if (spec == null) { - spec = LogOutputSpec.DEFAULT; - } - String text = logEntry.getText(); - ps.println(spec.getPrompt(spec.isUseColor(),logEntry.getTimestamp()) + text); - } - - // A single log-entry - private static class LogEntry implements Comparable { - private final int type; - private final Timestamp timestamp; - private final String text; - - public LogEntry(int type, Timestamp timestamp, String text) { - this.type = type; - this.timestamp = timestamp; - this.text = text; - } - - public int getType() { - return type; - } - - public Timestamp getTimestamp() { - return timestamp; - } - - public String getText() { - return text; - } - - @Override - public int compareTo(LogEntry entry) { - return timestamp.compareTo(entry.timestamp); - } - } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogCallback.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogCallback.java deleted file mode 100644 index db6f92ff84..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogCallback.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; - -import java.io.IOException; - -/** - * Interface called for each log line received from the docker host when asynchronous - * log fetching is used. - * - * @author roland - * @since 21/11/14 - */ -public interface LogCallback { - - /** - * Receive a log entry - * @param type 1 for log on standard output, 2 for standard error - * @param timestamp timestampp on the server side when this entry happened - * @param txt log output - * @throws DoneException if thrown will stop the logging. - */ - void log(int type, Timestamp timestamp, String txt) throws DoneException; - - /** - * Method called in case on an error when reading the logs - * @param error error description - */ - void error(String error); - - /** - * To be called by a client to start the callback and allocate the underlying output stream. - * In case of a shared stream it might be that the stream is reused - * - * @throws IOException in case of any I/O error - */ - void open() throws IOException; - - /** - * Invoked by a user when callback is no longer used. - * Closing the underlying stream may be delayed by the implementation - * when this stream is shared between multiple clients. - */ - void close(); - - /** - * Exception indicating that logging is done and should be finished - */ - class DoneException extends Exception {} -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogDispatcher.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogDispatcher.java deleted file mode 100644 index 4e52f5eecd..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogDispatcher.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; - -import java.util.HashMap; -import java.util.Map; - -/** - * @author roland - * @since 25/11/14 - */ -public class LogDispatcher { - - private final Map logHandles; - - private final DockerAccess dockerAccess; - - public LogDispatcher(DockerAccess dockerAccess) { - this.dockerAccess = dockerAccess; - logHandles = new HashMap<>(); - } - - public synchronized void trackContainerLog(String containerId, LogOutputSpec spec) { - LogGetHandle handle = dockerAccess.getLogAsync(containerId, new DefaultLogCallback(spec)); - logHandles.put(containerId, handle); - } - - public synchronized void fetchContainerLog(String containerId, LogOutputSpec spec) { - dockerAccess.getLogSync(containerId, new DefaultLogCallback(spec)); - } - - public synchronized void untrackAllContainerLogs() { - for (Map.Entry logHandlesEntry : logHandles.entrySet()) { - LogGetHandle handle = logHandlesEntry.getValue(); - handle.finish(); - } - logHandles.clear(); - } - - // ======================================================================================= - - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogGetHandle.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogGetHandle.java deleted file mode 100644 index 3fafd82f98..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogGetHandle.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - - -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; - -/** - * @author roland - * @since 29/11/14 - */ -public interface LogGetHandle { - - void finish(); - - boolean isError(); - - DockerAccessException getException(); -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpec.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpec.java deleted file mode 100644 index a5f31a5233..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpec.java +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; -import org.fusesource.jansi.Ansi; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.time.format.FormatStyle; - -import static org.fusesource.jansi.Ansi.Color.BLACK; -import static org.fusesource.jansi.Ansi.Color.BLUE; -import static org.fusesource.jansi.Ansi.Color.CYAN; -import static org.fusesource.jansi.Ansi.Color.GREEN; -import static org.fusesource.jansi.Ansi.Color.MAGENTA; -import static org.fusesource.jansi.Ansi.Color.RED; -import static org.fusesource.jansi.Ansi.Color.YELLOW; -import static org.fusesource.jansi.Ansi.ansi; - -@Getter -@EqualsAndHashCode -public class LogOutputSpec { - - public static final LogOutputSpec DEFAULT = new LogOutputSpec("", YELLOW, false , null, null, true, true); - private static final String DEFAULT_TIMESTAMP_PATTERN = "HH:mm:ss.SSS"; - private final boolean useColor; - private final boolean logStdout; - private final boolean fgBright; - private final String prefix; - private final Ansi.Color color; - private final DateTimeFormatter timeFormatter; - private final String file; - - // Palette used for prefixing the log output - private static final Ansi.Color[] COLOR_PALETTE = { - YELLOW,CYAN,MAGENTA,GREEN,RED,BLUE - }; - private static int globalColorIdx = 0; - - @Builder(toBuilder = true) - private LogOutputSpec( - String prefix, Ansi.Color color, boolean fgBright, DateTimeFormatter timeFormatter, String file, - boolean useColor, boolean logStdout) { - - this.prefix = prefix; - this.color = color; - this.fgBright = fgBright; - this.timeFormatter = timeFormatter; - this.file = file; - this.useColor = useColor; - this.logStdout = logStdout; - } - - public boolean isUseColor() { - return useColor && (getFile() == null || isLogStdout()); - } - - public String getPrompt(boolean withColor,Timestamp timestamp) { - return formatTimestamp(timestamp,withColor) + formatPrefix(prefix, withColor); - } - - private String formatTimestamp(Timestamp timestamp,boolean withColor) { - if (timeFormatter == null) { - return ""; - } - - DateTimeFormatter formatter = DateTimeFormatter.ofPattern(DEFAULT_TIMESTAMP_PATTERN); - LocalDateTime localDateTime = LocalDateTime.from(formatter.parse(timestamp.toString())); - - return (withColor ? - ansi().fgBright(BLACK).a(localDateTime).reset().toString() : - localDateTime) + " "; - } - - private String formatPrefix(String prefix, boolean withColor) { - if (withColor) { - Ansi ansi = ansi(); - if (fgBright) { - ansi.fgBright(color); - } else { - ansi.fg(color); - } - return ansi.a(prefix).reset().toString(); - } else { - return prefix; - } - } - - public static class LogOutputSpecBuilder { - public LogOutputSpecBuilder colorString(String color) { - return colorString(color, false); - } - - public LogOutputSpecBuilder colorString(String color, boolean fgBright) { - if (color == null) { - this.color = COLOR_PALETTE[globalColorIdx++ % COLOR_PALETTE.length]; - } else { - try { - this.color = Ansi.Color.valueOf(color.toUpperCase()); - this.fgBright = fgBright; - } catch (IllegalArgumentException exp) { - throw new IllegalArgumentException( - "Invalid color '" + color + - "'. Color must be one of YELLOW, CYAN, MAGENTA, GREEN, RED, BLUE or BLACK"); - } - } - return this; - } - - public LogOutputSpecBuilder timeFormatterString(String formatOrConstant) { - if (formatOrConstant == null || formatOrConstant.equalsIgnoreCase("NONE") - || formatOrConstant.equalsIgnoreCase("FALSE")) { - timeFormatter = null; - } else if (formatOrConstant.length() == 0 || formatOrConstant.equalsIgnoreCase("DEFAULT")) { - timeFormatter = DateTimeFormatter.ofPattern(DEFAULT_TIMESTAMP_PATTERN); - } else if (formatOrConstant.equalsIgnoreCase("ISO8601")) { - timeFormatter = DateTimeFormatter.ISO_DATE_TIME; - } else if (formatOrConstant.equalsIgnoreCase("SHORT")) { - timeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.SHORT); - } else if (formatOrConstant.equalsIgnoreCase("MEDIUM")) { - timeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM); - } else if (formatOrConstant.equalsIgnoreCase("LONG")) { - timeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG); - } else if (formatOrConstant.equalsIgnoreCase("FULL")) { - timeFormatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.FULL); - } else { - try { - timeFormatter = DateTimeFormatter.ofPattern(formatOrConstant); - } catch (IllegalArgumentException exp) { - throw new IllegalArgumentException( - "Cannot parse log date specification '" + formatOrConstant + "'." + - "Must be either DEFAULT, NONE, ISO8601, SHORT, MEDIUM, LONG, FULL or a " + - "format string parseable by DateTimeFormat. See " + - "https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html"); - } - } - return this; - } - } -} \ No newline at end of file diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpecFactory.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpecFactory.java deleted file mode 100644 index 9214ed7705..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogOutputSpecFactory.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.LogConfiguration; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.build.service.docker.helper.FormatParameterReplacer; - -import java.util.HashMap; -import java.util.Map; - - -/** - * @author roland - * @since 26/09/15 - */ -public class LogOutputSpecFactory { - private static final String DEFAULT_PREFIX_FORMAT = "%a> "; - private final boolean useColor; - private final boolean logStdout; - private final String logDate; - - public LogOutputSpecFactory(boolean useColor, boolean logStdout) { - this(useColor, logStdout, null); - } - - public LogOutputSpecFactory(boolean useColor, boolean logStdout, String logDate) { - this.useColor = useColor; - this.logStdout = logStdout; - this.logDate = logDate; - } - - // ================================================================================================ - - public LogOutputSpec createSpec(String containerId, ImageConfiguration imageConfiguration) { - LogOutputSpec.LogOutputSpecBuilder builder = LogOutputSpec.builder(); - LogConfiguration logConfig = extractLogConfiguration(imageConfiguration); - - addLogFormat(builder, logConfig); - addPrefix(builder, logConfig.getPrefix(), imageConfiguration, containerId); - builder.file(logConfig.getFileLocation()) - .useColor(useColor) - .logStdout(logStdout) - .colorString(logConfig.getColor()); - - return builder.build(); - } - - private void addPrefix(LogOutputSpec.LogOutputSpecBuilder builder, String logPrefix, ImageConfiguration imageConfig, String containerId) { - String prefixFormat = logPrefix; - if (prefixFormat == null) { - prefixFormat = DEFAULT_PREFIX_FORMAT; - } - FormatParameterReplacer formatParameterReplacer = new FormatParameterReplacer(getPrefixFormatParameterLookups(imageConfig, containerId)); - builder.prefix(formatParameterReplacer.replace(prefixFormat)); - } - - private Map getPrefixFormatParameterLookups(final ImageConfiguration imageConfig, final String containerId) { - Map ret = new HashMap<>(); - - ret.put("z", () -> ""); - ret.put("c", () -> containerId.substring(0, 6)); - ret.put("C", () -> containerId); - ret.put("a", () -> { - String alias = imageConfig.getAlias(); - if (alias != null) { - return alias; - } - return containerId.substring(0, 6); - }); - ret.put("n", imageConfig::getName); - - return ret; - } - - private void addLogFormat(LogOutputSpec.LogOutputSpecBuilder builder, LogConfiguration logConfig) { - String logFormat = logConfig.getDate() != null ? logConfig.getDate() : logDate; - if (logFormat != null && logFormat.equalsIgnoreCase("true")) { - logFormat = "DEFAULT"; - } - if (logFormat != null) { - builder.timeFormatterString(logFormat); - } - } - - private LogConfiguration extractLogConfiguration(ImageConfiguration imageConfiguration) { - RunImageConfiguration runConfig = imageConfiguration.getRunConfiguration(); - LogConfiguration logConfig = null; - if (runConfig != null) { - logConfig = runConfig.getLog(); - } - if (logConfig == null) { - logConfig = LogConfiguration.DEFAULT; - } - return logConfig; - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogRequestor.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogRequestor.java deleted file mode 100644 index 5cd417c579..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/LogRequestor.java +++ /dev/null @@ -1,224 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import com.google.common.io.ByteStreams; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.build.service.docker.access.UrlBuilder; -import org.eclipse.jkube.kit.build.service.docker.helper.RequestUtil; -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; -import org.apache.commons.codec.binary.Hex; -import org.apache.http.HttpResponse; -import org.apache.http.StatusLine; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.impl.client.CloseableHttpClient; - -import java.io.EOFException; -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.charset.StandardCharsets; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Extractor for parsing the response of a log request - * - * @author roland - * @since 28/11/14 - */ -public class LogRequestor extends Thread implements LogGetHandle { - // Patter for matching log entries - static final Pattern LOG_LINE = Pattern.compile("^\\[?(?[^\\s\\]]*)]? (?.*?)\\s*$", Pattern.DOTALL); - private final CloseableHttpClient client; - - private final String containerId; - - // callback called for each line extracted - private final LogCallback callback; - - private DockerAccessException exception; - - // Remember for asynchronous handling so that the request can be aborted from the outside - private HttpUriRequest request; - - private final UrlBuilder urlBuilder; - - /** - * Create a helper object for requesting log entries synchronously ({@link #fetchLogs()}) or asynchronously ({@link #start()}. - * - * @param client HTTP client to use for requesting the docker host - * @param urlBuilder builder that creates docker urls - * @param containerId container for which to fetch the host - * @param callback callback to call for each line received - */ - public LogRequestor(CloseableHttpClient client, UrlBuilder urlBuilder, String containerId, LogCallback callback) { - this.client = client; - this.containerId = containerId; - - this.urlBuilder = urlBuilder; - - this.callback = callback; - this.exception = null; - } - - /** - * Get logs and feed a callback with the content - */ - public void fetchLogs() { - try { - callback.open(); - this.request = getLogRequest(false); - final HttpResponse response = client.execute(request); - parseResponse(response); - } catch (LogCallback.DoneException e) { - // Signifies we're finished with the log stream. - } catch (IOException exp) { - callback.error(exp.getMessage()); - } finally { - callback.close(); - } - } - - // Fetch log asynchronously as stream and follow stream - @Override - public void run() { - try { - callback.open(); - this.request = getLogRequest(true); - final HttpResponse response = client.execute(request); - parseResponse(response); - } catch (LogCallback.DoneException e) { - // Signifies we're finished with the log stream. - } catch (IOException e) { - callback.error("IO Error while requesting logs: " + e + " " + Thread.currentThread().getName()); - } finally { - callback.close(); - } - } - - private static class NoBytesReadException extends IOException { - public NoBytesReadException() { - } - } - - /** - * This is a copy of ByteStreams.readFully(), with the slight change that it throws - * NoBytesReadException if zero bytes are read. Otherwise it is identical. - * - * @param in - * @param bytes - * @throws IOException - */ - private void readFully(InputStream in, byte[] bytes) throws IOException { - int read = ByteStreams.read(in, bytes, 0, bytes.length); - if (read == 0) { - throw new NoBytesReadException(); - } else if (read != bytes.length) { - throw new EOFException("reached end of stream after reading " - + read + " bytes; " + bytes.length + " bytes expected"); - } - } - - private boolean readStreamFrame(InputStream is) throws IOException, LogCallback.DoneException { - // Read the header, which is composed of eight bytes. The first byte is an integer - // indicating the stream type (0 = stdin, 1 = stdout, 2 = stderr), the next three are thrown - // out, and the final four are the size of the remaining stream as an integer. - ByteBuffer headerBuffer = ByteBuffer.allocate(8); - headerBuffer.order(ByteOrder.BIG_ENDIAN); - try { - this.readFully(is, headerBuffer.array()); - } catch (NoBytesReadException e) { - // Not bytes read for stream. Return false to stop consuming stream. - return false; - } catch (EOFException e) { - throw new IOException("Failed to read log header. Could not read all 8 bytes. " + e.getMessage(), e); - } - - // Grab the stream type (stdout, stderr, stdin) from first byte and throw away other 3 bytes. - int type = headerBuffer.get(); - - // Skip three bytes, then read size from remaining four bytes. - int size = headerBuffer.getInt(4); - - // Ignore empty messages and keep reading. - if (size <= 0) { - return true; - } - - // Read the actual message - ByteBuffer payload = ByteBuffer.allocate(size); - try { - ByteStreams.readFully(is, payload.array()); - } catch (EOFException e) { - throw new IOException("Failed to read log message. Could not read all " + size + " bytes. " + e.getMessage() + - " [ Header: " + Hex.encodeHexString(headerBuffer.array()) + "]", e); - } - - String message = StandardCharsets.UTF_8.decode(payload).toString(); - callLogCallback(type, message); - return true; - } - - private void parseResponse(HttpResponse response) throws LogCallback.DoneException, IOException { - final StatusLine status = response.getStatusLine(); - if (status.getStatusCode() != 200) { - exception = new DockerAccessException("Error while reading logs (" + status + ")"); - throw new LogCallback.DoneException(); - } - - try (InputStream is = response.getEntity().getContent()) { - while (true) { - if (!readStreamFrame(is)) { - return; - } - } - } - } - - private void callLogCallback(int type, String txt) throws LogCallback.DoneException { - Matcher matcher = LOG_LINE.matcher(txt); - if (!matcher.matches()) { - callback.error(String.format("Invalid log format for '%s' (expected: \" \") [%04x %04x]", - txt,(int) (txt.toCharArray())[0],(int) (txt.toCharArray())[1])); - throw new LogCallback.DoneException(); - } - Timestamp ts = new Timestamp(matcher.group("timestamp")); - String logTxt = matcher.group("entry"); - callback.log(type, ts, logTxt); - } - - private HttpUriRequest getLogRequest(boolean follow) { - return RequestUtil.newGet(urlBuilder.containerLogs(containerId, follow)); - } - - @Override - public void finish() { - if (request != null) { - request.abort(); - request = null; - } - } - - @Override - public boolean isError() { - return exception != null; - } - - @Override - public DockerAccessException getException() { - return exception; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/SharedPrintStream.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/SharedPrintStream.java deleted file mode 100644 index 75cb6aa885..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/access/log/SharedPrintStream.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.access.log; - -import java.io.PrintStream; -import java.util.concurrent.atomic.AtomicInteger; - -class SharedPrintStream { - private PrintStream printStream; - - private AtomicInteger numUsers; - - SharedPrintStream(PrintStream ps) { - this.printStream = ps; - this.numUsers = new AtomicInteger(1); - } - - PrintStream getPrintStream() { - return printStream; - } - - void allocate() { - numUsers.incrementAndGet(); - } - - boolean close() { - int nrUsers = numUsers.decrementAndGet(); - if (nrUsers == 0 && printStream != System.out) { - printStream.close(); - return true; - } else { - return false; - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/VolumeConfiguration.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/VolumeConfiguration.java deleted file mode 100644 index d54b8d76d6..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/VolumeConfiguration.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.config; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.util.Map; - -/** - * Volume Configuration for Volumes to be created prior to container start - * - * @author Tom Burton - * @version Dec 15, 2016 - */ -@SuppressWarnings("JavaDoc") -@Builder -@AllArgsConstructor -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class VolumeConfiguration implements Serializable { - - private static final long serialVersionUID = -310412541839312313L; - - /** - * Volume Name - * @param name name of volume configuration - * @return name of specified volume configuration - */ - private String name; - - /** - * Volume driver for mounting the volume - * @param driver volume driver - * @return string indicating volume driver - */ - private String driver; - - /** - * Driver specific options - * @param opts driver specific options - * @return map containing driver specific options - */ - private Map opts; - - /** - * Volume labels - * @param labels volume labels - * @return map containing volume labels - */ - private Map labels; - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandler.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandler.java index b65d61b9ad..d9514e412a 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandler.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandler.java @@ -14,13 +14,6 @@ package org.eclipse.jkube.kit.build.service.docker.config.handler.property; import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.LogConfiguration; -import org.eclipse.jkube.kit.config.image.NetworkConfig; -import org.eclipse.jkube.kit.config.image.RestartPolicy; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.RunVolumeConfiguration; -import org.eclipse.jkube.kit.config.image.UlimitConfig; -import org.eclipse.jkube.kit.config.image.WaitConfiguration; import org.eclipse.jkube.kit.config.image.WatchImageConfiguration; import org.eclipse.jkube.kit.build.service.docker.config.handler.ExternalConfigHandler; import org.eclipse.jkube.kit.common.JavaProject; @@ -53,32 +46,16 @@ import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ASSEMBLY_PERMISSIONS; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ASSEMBLY_TARLONGFILEMODE; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ASSEMBLY_USER; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.AUTO_REMOVE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.BIND; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.BUILD_OPTIONS; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CACHEFROM; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CAP_ADD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CAP_DROP; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CLEANUP; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CMD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CONTAINER_NAME_PATTERN; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CONTEXT_DIR; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CPUS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CPUSET; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.CPUSHARES; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DEPENDS_ON; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DNS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DNS_SEARCH; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DOCKER_ARCHIVE; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DOCKER_FILE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.DOMAINNAME; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ENTRYPOINT; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ENV; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ENV_BUILD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ENV_PROPERTY_FILE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.ENV_RUN; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.EXPOSED_PROPERTY_KEY; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.EXTRA_HOSTS; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.FILTER; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.FROM; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.FROM_EXT; @@ -89,66 +66,23 @@ import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.HEALTHCHECK_RETRIES; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.HEALTHCHECK_START_PERIOD; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.HEALTHCHECK_TIMEOUT; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.HOSTNAME; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.IMAGE_PULL_POLICY_BUILD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.IMAGE_PULL_POLICY_RUN; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LABELS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LINKS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_COLOR; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_DATE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_DRIVER_NAME; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_DRIVER_OPTS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_ENABLED; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_FILE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.LOG_PREFIX; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.MAINTAINER; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.MEMORY; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.MEMORY_SWAP; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NAME; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NET; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NETWORK_ALIAS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NETWORK_MODE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NETWORK_NAME; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.NOCACHE; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.OPTIMISE; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.PORTS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.PORT_PROPERTY_FILE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.PRIVILEGED; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.READ_ONLY; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.RESTART_POLICY_NAME; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.RESTART_POLICY_RETRY; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.RUN; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.SECURITY_OPTS; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.SHELL; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.SHMSIZE; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.SKIP_BUILD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.SKIP_RUN; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.TAGS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.TMPFS; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.USER; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.VOLUMES; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.VOLUMES_FROM; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_EXEC_BREAK_ON_ERROR; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_EXEC_POST_START; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_EXEC_PRE_STOP; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_EXIT; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_HEALTHY; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_HTTP_METHOD; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_HTTP_STATUS; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_HTTP_URL; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_KILL; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_LOG; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_SHUTDOWN; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_TCP_HOST; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_TCP_MODE; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_TCP_PORT; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_TIME; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WAIT_URL; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WATCH_INTERVAL; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WATCH_POSTEXEC; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WATCH_POSTGOAL; import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WORKDIR; -import static org.eclipse.jkube.kit.build.service.docker.config.handler.property.ConfigKey.WORKING_DIR; /** * @author roland @@ -171,7 +105,6 @@ public List resolve(ImageConfiguration fromConfig, JavaProje PropertyMode propertyMode = getMode(externalConfig); ValueProvider valueProvider = new ValueProvider(prefix, properties, propertyMode); - RunImageConfiguration run = extractRunConfiguration(fromConfig, valueProvider); BuildConfiguration build = extractBuildConfiguration(fromConfig, valueProvider, project); WatchImageConfiguration watch = extractWatchConfig(fromConfig, valueProvider); String name = valueProvider.getString(NAME, fromConfig.getName()); @@ -184,7 +117,6 @@ public List resolve(ImageConfiguration fromConfig, JavaProje return Collections.singletonList(ImageConfiguration.builder() .name(name) .alias(alias) - .run(run) .build(build) .watch(watch) .build()); @@ -263,59 +195,6 @@ private BuildConfiguration extractBuildConfiguration(ImageConfiguration fromConf .build(); } - private RunImageConfiguration extractRunConfiguration(ImageConfiguration fromConfig, ValueProvider valueProvider) { - RunImageConfiguration config = fromConfig.getRunConfiguration(); - if (config.isDefault()) { - config = null; - } - - return RunImageConfiguration.builder() - .capAdd(valueProvider.getList(CAP_ADD, config == null ? null : config.getCapAdd())) - .capDrop(valueProvider.getList(CAP_DROP, config == null ? null : config.getCapDrop())) - .securityOpts(valueProvider.getList(SECURITY_OPTS, config == null ? null : config.getSecurityOpts())) - .cmd(extractArguments(valueProvider, CMD, config == null ? null : config.getCmd())) - .dns(valueProvider.getList(DNS, config == null ? null : config.getDns())) - .dependsOn(valueProvider.getList(DEPENDS_ON, config == null ? null : config.getDependsOn())) - .net(valueProvider.getString(NET, config == null ? null : config.getNet())) - .network(extractNetworkConfig(config == null ? null : config.getNetworkingConfig(), valueProvider)) - .dnsSearch(valueProvider.getList(DNS_SEARCH, config == null ? null : config.getDnsSearch())) - .domainname(valueProvider.getString(DOMAINNAME, config == null ? null : config.getDomainname())) - .entrypoint(extractArguments(valueProvider, ENTRYPOINT, config == null ? null : config.getEntrypoint())) - .env(MapUtil.mergeMaps( - valueProvider.getMap(ENV_RUN, config == null ? null : config.getEnv()), - valueProvider.getMap(ENV, Collections.emptyMap()) - )) - .labels(valueProvider.getMap(LABELS, config == null ? null : config.getLabels())) - .envPropertyFile(valueProvider.getString(ENV_PROPERTY_FILE, config == null ? null : config.getEnvPropertyFile())) - .extraHosts(valueProvider.getList(EXTRA_HOSTS, config == null ? null : config.getExtraHosts())) - .hostname(valueProvider.getString(HOSTNAME, config == null ? null : config.getHostname())) - .links(valueProvider.getList(LINKS, config == null ? null : config.getLinks())) - .memory(valueProvider.getLong(MEMORY, config == null ? null : config.getMemory())) - .memorySwap(valueProvider.getLong(MEMORY_SWAP, config == null ? null : config.getMemorySwap())) - .containerNamePattern(valueProvider.getString(CONTAINER_NAME_PATTERN, config == null ? null :config.getContainerNamePattern())) - .exposedPropertyKey(valueProvider.getString(EXPOSED_PROPERTY_KEY, config == null ? null : config.getExposedPropertyKey())) - .portPropertyFile(valueProvider.getString(PORT_PROPERTY_FILE, config == null ? null : config.getPortPropertyFile())) - .ports(valueProvider.getList(PORTS, config == null ? null : config.getPorts())) - .shmSize(valueProvider.getLong(SHMSIZE, config == null ? null : config.getShmSize())) - .privileged(valueProvider.getBoolean(PRIVILEGED, config == null ? null : config.getPrivileged())) - .restartPolicy(extractRestartPolicy(config == null ? null : config.getRestartPolicy(), valueProvider)) - .user(valueProvider.getString(USER, config == null ? null : config.getUser())) - .workingDir(valueProvider.getString(WORKING_DIR, config == null ? null : config.getWorkingDir())) - .log(extractLogConfig(config == null ? null : config.getLog(), valueProvider)) - .wait(extractWaitConfig(config == null ? null : config.getWait(), valueProvider)) - .volumes(extractVolumeConfig(config == null ? null : config.getVolumeConfiguration(), valueProvider)) - .skip(valueProvider.getBoolean(SKIP_RUN, config == null ? null : config.getSkip())) - .imagePullPolicy(valueProvider.getString(IMAGE_PULL_POLICY_RUN, config == null ? null : config.getImagePullPolicy())) - .ulimits(extractUlimits(config == null ? null : config.getUlimits(), valueProvider)) - .tmpfs(valueProvider.getList(TMPFS, config == null ? null : config.getTmpfs())) - .cpuShares(valueProvider.getLong(CPUSHARES, config == null ? null : config.getCpuShares())) - .cpus(valueProvider.getLong(CPUS, config == null ? null : config.getCpus())) - .cpuSet(valueProvider.getString(CPUSET, config == null ? null : config.getCpuSet())) - .readOnly(valueProvider.getBoolean(READ_ONLY, config == null ? null : config.getReadOnly())) - .autoRemove(valueProvider.getBoolean(AUTO_REMOVE, config == null ? null : config.getAutoRemove())) - .build(); - } - List extractCacheFrom(String cacheFrom, String ...more) { if (more == null || more.length == 0) { return Collections.singletonList(cacheFrom); @@ -324,14 +203,6 @@ List extractCacheFrom(String cacheFrom, String ...more) { return Stream.concat(Stream.of(cacheFrom), Arrays.stream(more)).collect(Collectors.toList()); } - private NetworkConfig extractNetworkConfig(NetworkConfig config, ValueProvider valueProvider) { - return NetworkConfig.builder() - .modeString(valueProvider.getString(NETWORK_MODE, config == null || config.getMode() == null ? null : config.getMode().name())) - .name(valueProvider.getString(NETWORK_NAME, config == null ? null : config.getName())) - .aliases(valueProvider.getList(NETWORK_ALIAS, config == null ? null : config.getAliases())) - .build(); - } - private AssemblyConfiguration extractAssembly(AssemblyConfiguration config, ValueProvider valueProvider) { return AssemblyConfiguration.builder() .targetDir(valueProvider.getString(ASSEMBLY_BASEDIR, valueOrNull(config, AssemblyConfiguration::getTargetDir))) @@ -378,54 +249,6 @@ private Arguments extractArguments(ValueProvider valueProvider, ConfigKey config return valueProvider.getObject(configKey, alternative, raw -> raw != null ? Arguments.builder().shell(raw).build() : null); } - private RestartPolicy extractRestartPolicy(RestartPolicy config, ValueProvider valueProvider) { - return RestartPolicy.builder() - .name(valueProvider.getString(RESTART_POLICY_NAME, config == null ? null : config.getName())) - .retry(valueProvider.getInt(RESTART_POLICY_RETRY, config == null || config.getRetry() == 0 ? null : config.getRetry())) - .build(); - } - - private LogConfiguration extractLogConfig(LogConfiguration config, ValueProvider valueProvider) { - return LogConfiguration.builder() - .color(valueProvider.getString(LOG_COLOR, config == null ? null : config.getColor())) - .date(valueProvider.getString(LOG_DATE, config == null ? null : config.getDate())) - .file(valueProvider.getString(LOG_FILE, config == null ? null : config.getFileLocation())) - .prefix(valueProvider.getString(LOG_PREFIX, config == null ? null : config.getPrefix())) - .driverName(valueProvider.getString(LOG_DRIVER_NAME, config == null || config.getDriver() == null ? null : config.getDriver().getName())) - .logDriverOpts(valueProvider.getMap(LOG_DRIVER_OPTS, config == null || config.getDriver() == null ? null : config.getDriver().getOpts())) - .enabled(valueProvider.getBoolean(LOG_ENABLED, Optional.ofNullable(config).map(LogConfiguration::isEnabled).orElse(false))) - .build(); - } - - private WaitConfiguration extractWaitConfig(WaitConfiguration config, ValueProvider valueProvider) { - String url = valueProvider.getString(WAIT_HTTP_URL, config == null ? null : config.getUrl()); - if (url == null) { - // Fallback to deprecated old URL - url = valueProvider.getString(WAIT_URL, config == null ? null : config.getUrl()); - } - WaitConfiguration.ExecConfiguration exec = config == null ? null : config.getExec(); - WaitConfiguration.TcpConfiguration tcp = config == null ? null : config.getTcp(); - WaitConfiguration.HttpConfiguration http = config == null ? null : config.getHttp(); - - return WaitConfiguration.builder() - .time(valueProvider.getInt(WAIT_TIME, config == null ? null : config.getTime())) - .healthy(valueProvider.getBoolean(WAIT_HEALTHY, config == null ? null : config.getHealthy())) - .url(url) - .preStop(valueProvider.getString(WAIT_EXEC_PRE_STOP, exec == null ? null : exec.getPreStop())) - .postStart(valueProvider.getString(WAIT_EXEC_POST_START, exec == null ? null : exec.getPostStart())) - .breakOnError(valueProvider.getBoolean(WAIT_EXEC_BREAK_ON_ERROR, exec == null ? null : exec.isBreakOnError())) - .method(valueProvider.getString(WAIT_HTTP_METHOD, http == null ? null : http.getMethod())) - .status(valueProvider.getString(WAIT_HTTP_STATUS, http == null ? null : http.getStatus())) - .log(valueProvider.getString(WAIT_LOG, config == null ? null : config.getLog())) - .kill(valueProvider.getInteger(WAIT_KILL, config == null ? null : config.getKill())) - .exit(valueProvider.getInteger(WAIT_EXIT, config == null ? null : config.getExit())) - .shutdown(valueProvider.getInteger(WAIT_SHUTDOWN, config == null ? null : config.getShutdown())) - .tcpHost(valueProvider.getString(WAIT_TCP_HOST, tcp == null ? null : tcp.getHost())) - .tcpPorts(valueProvider.getIntList(WAIT_TCP_PORT, tcp == null ? null : tcp.getPorts())) - .tcpModeString(valueProvider.getString(WAIT_TCP_MODE, tcp == null || tcp.getMode() == null ? null : tcp.getMode().name())) - .build(); - } - private WatchImageConfiguration extractWatchConfig(ImageConfiguration fromConfig, ValueProvider valueProvider) { WatchImageConfiguration config = fromConfig.getWatchConfiguration(); @@ -437,33 +260,6 @@ private WatchImageConfiguration extractWatchConfig(ImageConfiguration fromConfig .build(); } - private List extractUlimits(List config, ValueProvider valueProvider) { - List other = null; - if (config != null) { - other = new ArrayList<>(); - // Convert back to string for potential merge - for (UlimitConfig ulimitConfig : config) { - other.add(ulimitConfig.serialize()); - } - } - - List ulimits = valueProvider.getList(ConfigKey.ULIMITS, other); - if (ulimits == null) { - return null; - } - List ret = new ArrayList<>(); - for (String ulimit : ulimits) { - ret.add(new UlimitConfig(ulimit)); - } - return ret; - } - - private RunVolumeConfiguration extractVolumeConfig(RunVolumeConfiguration config, ValueProvider valueProvider) { - return RunVolumeConfiguration.builder() - .bind(valueProvider.getList(BIND, config == null ? null : config.getBind())) - .from(valueProvider.getList(VOLUMES_FROM, config == null ? null : config.getFrom())) - .build(); - } private static String getPrefix(Map externalConfig) { String prefix = externalConfig.get("prefix"); @@ -487,7 +283,7 @@ public static boolean canCoexistWithOtherPropertyConfiguredImages(Map> imageLines = new ThreadLocal<>(); - private ThreadLocal updateCount = new ThreadLocal<>(); - - // Whether to use ANSI codes - private boolean useAnsi; - - public AnsiLoggerFacade(KitLogger log, boolean useColor, boolean verbose) { - this(log, useColor, verbose, false); - } - - public AnsiLoggerFacade(KitLogger log, boolean useColor, boolean verbose, boolean batchMode) { - this(log, useColor, verbose, batchMode, DEFAULT_LOG_PREFIX); - } - - public AnsiLoggerFacade(KitLogger log, boolean useColor, boolean verbose, boolean batchMode, String prefix) { - this.log = log; - this.prefix = prefix; - this.verbose = verbose; - this.batchMode = batchMode; - initializeColor(useColor); - } - - /** {@inheritDoc} */ - public void debug(String message, Object... params) { - if (isDebugEnabled()) { - log.debug(prefix + format(message, params)); - } - } - - /** {@inheritDoc} */ - public void info(String message, Object... params) { - log.info(colored(message, COLOR_INFO, true, params)); - } - - /** {@inheritDoc} */ - public void verbose(String message, Object ... params) { - if (verbose) { - log.info(ansi().fgBright(BLACK).a(prefix).a(format(message, params)).reset().toString()); - } - } - - /** {@inheritDoc} */ - public void warn(String format, Object... params) { - log.warn(colored(format, COLOR_WARNING, true, params)); - } - - /** {@inheritDoc} */ - public void error(String message, Object... params) { - log.error(colored(message, COLOR_ERROR, true, params)); - } - - /** - * Whether debugging is enabled. - */ - public boolean isDebugEnabled() { - return log.isDebugEnabled(); - } - - public boolean isVerboseEnabled() { - return verbose; - } - - /** - * Start a progress bar - */ - public void progressStart() { - // A progress indicator is always written out to standard out if a tty is enabled. - if (!batchMode) { - imageLines.remove(); - updateCount.remove(); - imageLines.set(new HashMap<>()); - updateCount.set(new AtomicInteger()); - } - } - - /** - * Update the progress - */ - public void progressUpdate(String layerId, String status, String progressMessage) { - if (!batchMode && StringUtils.isNotEmpty(layerId)) { - if (useAnsi) { - updateAnsiProgress(layerId, status, progressMessage); - } else { - updateNonAnsiProgress(layerId); - } - flush(); - } - } - - private void updateAnsiProgress(String imageId, String status, String progressMessage) { - Map imgLineMap = imageLines.get(); - Integer line = imgLineMap.get(imageId); - - int diff = 0; - if (line == null) { - line = imgLineMap.size(); - imgLineMap.put(imageId, line); - } else { - diff = imgLineMap.size() - line; - } - - if (diff > 0) { - print(ansi().cursorUp(diff).eraseLine(Ansi.Erase.ALL).toString()); - } - - // Status with progress bars: (max length = 11, hence pad to 11) - // Extracting - // Downloading - String progress = progressMessage != null ? progressMessage : ""; - String msg = - ansi() - .fg(COLOR_PROGRESS_ID).a(imageId).reset().a(": ") - .fg(COLOR_PROGRESS_STATUS).a(StringUtils.rightPad(status,11) + " ") - .fg(COLOR_PROGRESS_BAR).a(progress).toString(); - println(msg); - - if (diff > 0) { - // move cursor back down to bottom - print(ansi().cursorDown(diff - 1).toString()); - } - } - - private void updateNonAnsiProgress(String imageId) { - AtomicInteger count = updateCount.get(); - int nr = count.getAndIncrement(); - if (nr % NON_ANSI_UPDATE_PERIOD == 0) { - print("#"); - } - if (nr > 0 && nr % (80 * NON_ANSI_UPDATE_PERIOD) == 0) { - print("\n"); - } - } - - /** - * Finis progress meter. Must be always called if {@link #progressStart()} has been used. - */ - public void progressFinished() { - if (!batchMode) { - imageLines.remove(); - print(ansi().reset().toString()); - if (!useAnsi) { - println(""); - } - } - } - - private void flush() { - System.out.flush(); - } - - private void initializeColor(boolean useColor) { - // sl4j simple logger used by Maven seems to escape ANSI escapes on Windows - this.useAnsi = useColor && System.console() != null && !log.isDebugEnabled() && !isWindows(); - if (useAnsi) { - AnsiConsole.systemInstall(); - Ansi.setEnabled(true); - } - else { - Ansi.setEnabled(false); - } - } - - private boolean isWindows() { - String os = System.getProperty("os.name"); - return os != null && os.toLowerCase().startsWith("windows"); - } - - private void println(String txt) { - System.out.println(txt); - } - - private void print(String txt) { - System.out.print(txt); - } - - private String colored(String message, Ansi.Color color, boolean addPrefix, Object... params) { - Ansi ansi = ansi().fg(color); - String msgToPrint = addPrefix ? prefix + message : message; - return ansi.a(format(evaluateEmphasis(msgToPrint, color), params)).reset().toString(); - } - - // Use parameters when given, otherwise we use the string directly - private String format(String message, Object[] params) { - if (params.length == 0) { - return message; - } else if (params.length == 1 && params[0] instanceof Throwable) { - // We print only the message here since breaking exception will bubble up - // anyway - return message + ": " + params[0].toString(); - } else { - return String.format(message, params); - } - } - - // Emphasize parts encloses in "[[*]]" tags - private String evaluateEmphasis(String message, Ansi.Color msgColor) { - // Split with delimiters [[.]]. See also http://stackoverflow.com/a/2206545/207604 - String prepared = message.replaceAll("\\[\\[(.)]]", "[[]]$1[[]]"); - String[] parts = prepared.split("\\[\\[]]"); - if (parts.length == 1) { - return message; - } - String msgColorS = ansi().fg(msgColor).toString(); - StringBuilder ret = new StringBuilder(parts[0]); - boolean colorOpen = true; - for (int i = 1; i < parts.length; i+=2) { - ret.append(colorOpen ? getEmphasisColor(parts[i]) : msgColorS); - colorOpen = !colorOpen; - if (i+1 < parts.length) { - ret.append(parts[i+1]); - } - } - return ret.toString(); - } - - private static final Map COLOR_MAP = new HashMap<>(); - - static { - COLOR_MAP.put("*", COLOR_EMPHASIS); - COLOR_MAP.put("B", BLUE); - COLOR_MAP.put("C", CYAN); - COLOR_MAP.put("Y", YELLOW); - COLOR_MAP.put("G", GREEN); - COLOR_MAP.put("M", MAGENTA); - COLOR_MAP.put("R", RED); - COLOR_MAP.put("W", WHITE); - COLOR_MAP.put("S", BLACK); - COLOR_MAP.put("D", DEFAULT); - } - - private String getEmphasisColor(String id) { - Ansi.Color color = COLOR_MAP.get(id.toUpperCase()); - if (color != null) { - return id.toLowerCase().equals(id) ? - // lower case letter means bright color ... - ansi().fgBright(color).toString() : - ansi().fg(color).toString(); - } else { - return ""; - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ConfigHelper.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ConfigHelper.java index c7645808d0..d885cb86f9 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ConfigHelper.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ConfigHelper.java @@ -190,9 +190,6 @@ public static List initImageConfiguration(Date buildTimeStam if (imageConfiguration.getBuild() != null) { imageConfiguration.getBuild().initAndValidate(); } - if (imageConfiguration.getRun() != null) { - imageConfiguration.getRun().initAndValidate(); - } printDockerfileInfoIfDockerfileMode(imageConfiguration, log, jKubeConfiguration); } diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ContainerNamingUtil.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ContainerNamingUtil.java deleted file mode 100644 index 60447ca67f..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/ContainerNamingUtil.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import com.google.common.collect.ImmutableSet; -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.ImageName; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Date; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.function.Function; -import java.util.stream.Collectors; - -/** - * @author marcus - * @since 1.0.0 - */ -public class ContainerNamingUtil { - - private static final String INDEX_PLACEHOLDER = "%i"; - - public static final String DEFAULT_CONTAINER_NAME_PATTERN = "%n-%i"; - - // class with only static methods - private ContainerNamingUtil() { } - - public static String formatContainerName(final ImageConfiguration image, - final String defaultContainerNamePattern, - final Date buildTimestamp, - final Collection existingContainers) { - - String containerNamePattern = extractContainerNamePattern(image, defaultContainerNamePattern); - Set existingContainersNames = extractContainerNames(existingContainers); - - final String partiallyApplied = - replacePlaceholders( - containerNamePattern, - image.getName(), - image.getAlias(), - buildTimestamp); - - - if (partiallyApplied.contains(INDEX_PLACEHOLDER)) { - for (long i = 1; i < Long.MAX_VALUE; i++) { - final String withIndexApplied = partiallyApplied.replaceAll(INDEX_PLACEHOLDER, String.valueOf(i)); - if (!existingContainersNames.contains(withIndexApplied)) { - return withIndexApplied; - } - } - throw new IllegalStateException("Could not find any free container name for pattern " + partiallyApplied); - } else { - return partiallyApplied; - } - } - - /** - * Keep only the entry with the higest index if an indexed naming scheme for container has been chosen. - * @param image the image from which to the the container pattern - * @param defaultContainerNamePattern the default container name pattern - * @param buildTimestamp the timestamp for the build - * @param containers the list of existing containers - * @return a list with potentially lower indexed entries removed - */ - public static Collection getContainersToStop(final ImageConfiguration image, - final String defaultContainerNamePattern, - final Date buildTimestamp, - final Collection containers) { - - String containerNamePattern = extractContainerNamePattern(image, defaultContainerNamePattern); - - // Only special treatment for indexed container names - if (!containerNamePattern.contains(INDEX_PLACEHOLDER)) { - return containers; - } - - final String partiallyApplied = - replacePlaceholders( - containerNamePattern, - image.getName(), - image.getAlias(), - buildTimestamp); - - return keepOnlyLastIndexedContainer(containers, partiallyApplied); - - } - - // ======================================================================================================== - - private static String replacePlaceholders(String containerNamePattern, String imageName, String nameAlias, Date buildTimestamp) { - - Map lookups = new HashMap<>(); - - lookups.put("a", () -> nameAlias); - lookups.put("n", () -> cleanImageName(imageName)); - lookups.put("t", () -> String.valueOf(buildTimestamp.getTime())); - lookups.put("i", () -> INDEX_PLACEHOLDER); - - return new FormatParameterReplacer(lookups).replace(containerNamePattern); - } - - - // Filter out any older indexed containernames, keeping only the last one (i.e. with the highest index) - private static Collection keepOnlyLastIndexedContainer(Collection existingContainers, final String partiallyApplied) { - - Collection result = new ArrayList<>(existingContainers); - - // No index place holder, so nothing to filters - if (!partiallyApplied.contains(INDEX_PLACEHOLDER)) { - return result; - } - - Map containerMap = existingContainers.stream().collect(Collectors.toMap(Container::getName, Function.identity())); - - Container last = null; - for (long i = 1; i < Long.MAX_VALUE; i++) { - final String withIndexApplied = partiallyApplied.replaceAll(INDEX_PLACEHOLDER, String.valueOf(i)); - Container mapped = containerMap.get(withIndexApplied); - if (mapped != null) { - result.remove(mapped); - last = mapped; - } else { - // Readd last one removed (if any) - if (last != null) { - result.add(last); - } - return result; - } - } - throw new IllegalStateException("Internal error: Cannot find a free container index slot in " + existingContainers); - } - - private static Set extractContainerNames(final Collection existingContainers) { - final ImmutableSet.Builder containerNamesBuilder = ImmutableSet.builder(); - for (final Container container : existingContainers) { - containerNamesBuilder.add(container.getName()); - } - return containerNamesBuilder.build(); - } - - private static String extractContainerNamePattern(ImageConfiguration image, String defaultContainerNamePattern) { - RunImageConfiguration runConfig = image.getRunConfiguration(); - if (runConfig != null && runConfig.getContainerNamePattern() != null) { - return runConfig.getContainerNamePattern(); - } - return defaultContainerNamePattern != null ? defaultContainerNamePattern : DEFAULT_CONTAINER_NAME_PATTERN; - } - - private static String cleanImageName(final String imageName) { - return new ImageName(imageName).getSimpleName().replaceAll("[^a-zA-Z0-9_.-]+", "_"); - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/DockerPathUtil.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/DockerPathUtil.java deleted file mode 100644 index d43a16cb65..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/DockerPathUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import java.io.File; -import java.io.IOException; - -/** - * Docker path resolution and manipulation utility methods. - *

    - * This class provides methods for manipulating paths as they appear in docker-compose or Dockerfiles. This - * class does not provide for generic path manipulation across platforms or file systems. Paths that appear in Docker - * configurations use forward slash as a separator character, so this class makes no provisions for handling Windows - * platform path semantics (e.g. the presence of drive letters or backward slash). - *

    - */ -public class DockerPathUtil { - - private DockerPathUtil() { } - - /** - * Resolves the supplied resource (a path or directory on the filesystem) relative the supplied {@code - * baseDir}. The returned {@code File} is guaranteed to be {@link File#isAbsolute() absolute}. The returned file - * is not guaranteed to exist. - *

    - * If the supplied {@code pathToResolve} is already {@link File#isAbsolute() absolute}, then it is returned - * unmodified. Otherwise, the {@code pathToResolve} is returned as an absolute {@code File} using the - * supplied {@code baseDir} as its parent. - *

    - * - * @param pathToResolve represents a filesystem resource, which may be an absolute path - * @param baseDir the absolute path used to resolve non-absolute path resources; must be absolute - * @return an absolute {@code File} reference to {@code pathToResolve}; not guaranteed to exist - */ - public static File resolveAbsolutely(String pathToResolve, String baseDir) { - // TODO: handle the case where pathToResolve specifies a non-existent path, for example, a base directory equal to "/" and a relative path of "../../foo". - File fileToResolve = new File(pathToResolve); - - if (fileToResolve.isAbsolute()) { - return fileToResolve; - } - - if (baseDir == null) { - throw new IllegalArgumentException("Cannot resolve relative path '" + pathToResolve + "' with a " + - "null base directory."); - } - - File baseDirAsFile = new File(baseDir); - if (!baseDirAsFile.isAbsolute()) { - throw new IllegalArgumentException("Base directory '" + baseDirAsFile + "' must be absolute"); - } - - final File toCanonicalize = new File(baseDirAsFile, pathToResolve); - try { - return toCanonicalize.getCanonicalFile(); - } catch (IOException e) { - throw new RuntimeException("Unable to canonicalize the file path '" + toCanonicalize + "'"); - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/RequestUtil.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/RequestUtil.java deleted file mode 100644 index 8602d76850..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/RequestUtil.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import org.apache.http.client.methods.HttpDelete; -import org.apache.http.client.methods.HttpGet; -import org.apache.http.client.methods.HttpPost; -import org.apache.http.client.methods.HttpUriRequest; -import org.apache.http.entity.StringEntity; - -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; -import java.nio.charset.Charset; - -/** - * @author roland - * @since 30/11/14 - */ -public class RequestUtil { - - public static final String HEADER_ACCEPT = "Accept"; - public static final String HEADER_ACCEPT_ALL = "*/*"; - - private RequestUtil() { } - - // ----------------------- - // Request related methods - public static HttpUriRequest newGet(String url) { - return addDefaultHeaders(new HttpGet(url)); - } - - public static HttpUriRequest newPost(String url, String body) { - HttpPost post = new HttpPost(url); - if (body != null) { - post.setEntity(new StringEntity(body, Charset.defaultCharset())); - } - return addDefaultHeaders(post); - } - - public static HttpUriRequest newDelete(String url) { - return addDefaultHeaders(new HttpDelete(url)); - } - - public static HttpUriRequest addDefaultHeaders(HttpUriRequest req) { - req.addHeader(HEADER_ACCEPT, HEADER_ACCEPT_ALL); - req.addHeader("Content-Type", "application/json"); - return req; - } - - @SuppressWarnings("deprecation") - public static String encode(String param) { - try { - return URLEncoder.encode(param, "UTF-8"); - } catch (UnsupportedEncodingException e) { - // wont happen - return URLEncoder.encode(param); - } - } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartContainerExecutor.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartContainerExecutor.java deleted file mode 100644 index b5a2db863d..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartContainerExecutor.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import java.io.File; -import java.io.IOException; -import java.util.Date; -import java.util.Map; -import java.util.Properties; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.NoArgsConstructor; -import org.apache.commons.lang3.StringUtils; -import org.eclipse.jkube.kit.build.api.model.Container; -import org.eclipse.jkube.kit.build.core.GavLabel; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.build.service.docker.access.ExecException; -import org.eclipse.jkube.kit.build.api.model.PortMapping; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogDispatcher; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; -import org.eclipse.jkube.kit.config.image.LogConfiguration; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.WaitConfiguration; -import org.eclipse.jkube.kit.common.KitLogger; - -import org.eclipse.jkube.kit.build.service.docker.DockerServiceHub; - -@Builder -@AllArgsConstructor -@NoArgsConstructor -@EqualsAndHashCode -public class StartContainerExecutor { - - private String exposeContainerProps; - private KitLogger log; - private LogOutputSpecFactory logOutputSpecFactory; - private DockerServiceHub hub; - private boolean follow; - private String showLogs; - private String containerNamePattern; - private Date buildDate; - private Properties projectProperties; - private File basedir; - private ImageConfiguration imageConfig; - private GavLabel gavLabel; - private PortMapping portMapping; - private LogDispatcher dispatcher; - - public String startContainers() throws IOException, ExecException { - final Properties projProperties = projectProperties; - - final String containerId = hub.getRunService().createAndStartContainer(imageConfig, portMapping, gavLabel, projProperties, basedir, containerNamePattern, buildDate); - - showLogsIfRequested(containerId); - exposeContainerProps(containerId); - waitAndPostExec(containerId, projProperties); - - return containerId; - } - - private void exposeContainerProps(String containerId) - throws DockerAccessException { - String propKey = getExposedPropertyKeyPart(); - - if (StringUtils.isNotEmpty(exposeContainerProps) && StringUtils.isNotEmpty(propKey)) { - Container container = hub.getQueryService().getMandatoryContainer(containerId); - - String prefix = addDot(exposeContainerProps) + addDot(propKey); - projectProperties.put(prefix + "id", containerId); - String ip = container.getIPAddress(); - if (StringUtils.isNotEmpty(ip)) { - projectProperties.put(prefix + "ip", ip); - } - - Map nets = container.getCustomNetworkIpAddresses(); - if (nets != null) { - for (Map.Entry entry : nets.entrySet()) { - projectProperties.put(prefix + addDot("net") + addDot(entry.getKey()) + "ip", entry.getValue()); - } - } - } - } - - String getExposedPropertyKeyPart() { - String propKey = imageConfig.getRunConfiguration() != null ? imageConfig.getRunConfiguration().getExposedPropertyKey() : ""; - if (StringUtils.isEmpty(propKey)) { - propKey = imageConfig.getAlias(); - } - return propKey; - } - - private String addDot(String part) { - return part.endsWith(".") ? part : part + "."; - } - - private void showLogsIfRequested(String containerId) { - if (showLogs()) { - dispatcher.trackContainerLog(containerId, - logOutputSpecFactory.createSpec(containerId, imageConfig)); - } - } - - private void waitAndPostExec(String containerId, Properties projProperties) throws IOException, ExecException { - // Wait if requested - hub.getWaitService().wait(imageConfig, projProperties, containerId); - WaitConfiguration waitConfig = imageConfig.getRunConfiguration().getWait(); - if (waitConfig != null && waitConfig.getExec() != null && waitConfig.getExec().getPostStart() != null) { - try { - hub.getRunService().execInContainer(containerId, waitConfig.getExec().getPostStart(), imageConfig); - } catch (ExecException exp) { - if (waitConfig.getExec().isBreakOnError()) { - throw exp; - } else { - log.warn("Cannot run postStart: %s", exp.getMessage()); - } - } - } - } - - boolean showLogs() { - if (StringUtils.isNotBlank(showLogs)) { - if (showLogs.equalsIgnoreCase("true")) { - return true; - } else if (showLogs.equalsIgnoreCase("false")) { - return false; - } else { - return ConfigHelper.matchesConfiguredImages(showLogs, imageConfig); - } - } - - RunImageConfiguration runConfig = imageConfig.getRunConfiguration(); - if (runConfig != null) { - LogConfiguration logConfig = runConfig.getLog(); - if (logConfig != null) { - return logConfig.isActivated(); - } else { - // Default is to show logs if "follow" is true - return follow; - } - } - return false; - } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartOrderResolver.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartOrderResolver.java deleted file mode 100644 index b6bd93e9a5..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/StartOrderResolver.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import org.eclipse.jkube.kit.build.service.docker.QueryService; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.config.image.ImageConfiguration; - -import java.util.ArrayList; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.List; -import java.util.Set; - -/** - * @author roland - */ -public class StartOrderResolver { - - public static final int MAX_RESOLVE_RETRIES = 10; - - private final QueryService queryService; - - private final List secondPass; - private final Set processedImages; - - public static List resolve(QueryService queryService, List convertToResolvables) { - return new StartOrderResolver(queryService).resolve(convertToResolvables); - } - - private StartOrderResolver(QueryService queryService) { - this.queryService = queryService; - - this.secondPass = new ArrayList<>(); - this.processedImages = new HashSet<>(); - } - - - // Check images for volume / link dependencies and return it in the right order. - // Only return images which should be run - // Images references via volumes but with no run configuration are started once to create - // an appropriate container which can be linked into the image - private List resolve(List images) { - List resolved = new ArrayList<>(); - // First pass: Pick all data images and all without dependencies - for (ImageConfiguration config : images) { - List volumesOrLinks = extractDependentImagesFor(config); - if (volumesOrLinks == null) { - // A data image only or no dependency. Add it to the list of data image which can be always - // created first. - updateProcessedImages(config); - resolved.add(config); - } else { - secondPass.add(config); - } - } - - // Next passes: Those with dependencies are checked whether they already have been visited. - return secondPass.isEmpty() ? resolved : resolveRemaining(resolved); - } - - private List resolveRemaining(List ret) { - int retries = MAX_RESOLVE_RETRIES; - String error = null; - try { - do { - resolveImageDependencies(ret); - } while (!secondPass.isEmpty() && retries-- > 0); - } catch (DockerAccessException | ResolveSteadyStateException e) { - error = "Cannot resolve image dependencies for start order\n" + remainingImagesDescription(); - } - if (retries == 0 && !secondPass.isEmpty()) { - error = "Cannot resolve image dependencies after " + MAX_RESOLVE_RETRIES + " passes\n" - + remainingImagesDescription(); - } - if (error != null) { - throw new IllegalStateException(error); - } - return ret; - } - - private void updateProcessedImages(ImageConfiguration config) { - processedImages.add(config.getName()); - if (config.getAlias() != null) { - processedImages.add(config.getAlias()); - } - } - - private String remainingImagesDescription() { - StringBuilder ret = new StringBuilder(); - ret.append("Unresolved images:\n"); - for (ImageConfiguration config : secondPass) { - ret.append("* ") - .append(config.getAlias()) - .append(" depends on ") - .append(String.join(",", config.getDependencies().toArray(new String[0]))) - .append("\n"); - } - return ret.toString(); - } - - private void resolveImageDependencies(List resolved) throws DockerAccessException, ResolveSteadyStateException { - boolean changed = false; - Iterator iterator = secondPass.iterator(); - - while (iterator.hasNext()) { - ImageConfiguration config = iterator.next(); - if (hasRequiredDependencies(config)) { - updateProcessedImages(config); - resolved.add(config); - changed = true; - iterator.remove(); - } - } - - if (!changed) { - throw new ResolveSteadyStateException(); - } - } - - private boolean hasRequiredDependencies(ImageConfiguration config) throws DockerAccessException { - List dependencies = extractDependentImagesFor(config); - if (dependencies == null) { - return false; - } - - for (String dependency : dependencies) { - // make sure the container exists, it's state will be verified elsewhere - if (processedImages.contains(dependency) || - // Check also whether a *container* with this name exists in which case it is interpreted - // as an external dependency which is already running - queryService.hasContainer(dependency)) { - continue; - } - return false; - } - - return true; - } - - private List extractDependentImagesFor(ImageConfiguration config) { - LinkedHashSet ret = new LinkedHashSet<>(config.getDependencies()); - return ret.isEmpty() ? null : new ArrayList<>(ret); - } - - // Exception indicating a steady state while resolving start order of images - private static class ResolveSteadyStateException extends Exception { } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/Timestamp.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/Timestamp.java deleted file mode 100644 index a962122824..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/Timestamp.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Timestamp holding a {@link LocalDateTime} and nano seconds and which can be compared. - * - */ -public class Timestamp implements Comparable { - - private LocalDateTime date; - private int rest; - - private static final Pattern TS_PATTERN = Pattern.compile("^(.*?)(?:\\.(\\d{3})(\\d*))?(Z|[+\\-][\\d:]+)?$",Pattern.CASE_INSENSITIVE); - - /** - * Create a timestamp for *now* - * - */ - public Timestamp() { - date = LocalDateTime.now(); - } - - /** - * Create a timestamp by parsing the given string representation which must be in an extended ISO 8601 Format - * with Nanoseconds since this is the format used by Docker for logging (e.g. "2014-11-24T22:34:00.761764812Z") - * - * @param spec date specification to parse - */ - public Timestamp(String spec) { - // - Matcher matcher = TS_PATTERN.matcher(spec); - if (!matcher.matches()) { - throw new IllegalArgumentException("Invalid timestamp '" + spec + "' given."); - } - String millis = matcher.group(2); - String rest = matcher.group(3); - this.rest = rest != null ? Integer.parseInt(rest) : 0; - date = LocalDateTime.parse(matcher.group(1) + (millis != null ? "." + millis : ".000") + matcher.group(4), DateTimeFormatter.ISO_OFFSET_DATE_TIME); - } - - public LocalDateTime getDate() { - return date; - } - - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - Timestamp timestamp = (Timestamp) o; - - if (rest != timestamp.rest) return false; - if (!date.equals(timestamp.date)) return false; - - return true; - } - - @Override - public int hashCode() { - int result = date.hashCode(); - result = 31 * result + (int) (rest ^ (rest >>> 32)); - return result; - } - - @Override - public int compareTo(Timestamp ts) { - int fc = this.date.compareTo(ts.date); - if (fc != 0) { - return fc; - } - return this.rest - ts.rest; - } - - @Override - public String toString() { - return date.toString(); - } - -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/VolumeBindingUtil.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/VolumeBindingUtil.java deleted file mode 100644 index b3000f5d7b..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/helper/VolumeBindingUtil.java +++ /dev/null @@ -1,361 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - - -import org.eclipse.jkube.kit.config.image.RunVolumeConfiguration; - -import java.io.File; -import java.io.IOException; -import java.util.List; -import java.util.regex.Pattern; - -import static org.eclipse.jkube.kit.build.service.docker.helper.DockerPathUtil.resolveAbsolutely; - - -/** - * Utility methods for working with Docker volume bindings. - *

    - * This class provides explicit support for relative binding paths. This means that the plugin configuration or - * docker compose file can specify a relative path when configuring a volume binding. Methods in this class will - * examine volume binding strings in a {@link RunVolumeConfiguration} and resolve any relative paths in the host portion - * of volume bindings. Examples of relative bindings include: - *

    - *
    - *
    A host path relative to the current working directory
    - *
    ./relative/path:/absolute/container/path
    - * - *
    A host path relative to the current working directory
    - *
    relative/path/:/absolute/container/path
    - * - *
    A host path relative to the parent of the current working directory
    - *
    ../relative/path:/absolute/container/path
    - * - *
    A host path equal to the current user's home directory
    - *
    ~:/absolute/container/path
    - * - *
    A host path relative to the current user's home directory
    - *
    ~/relative/path:/absolute/container/path
    - *
    - *

    - * Understand that the following is not considered a relative binding path, and is instead interpreted as a - * named volume: - *

    - *
    - *
    {@code rel} is interpreted as a named volume. Use {@code ./rel} or {@code rel} to have it - * interpreted as a relative path.
    - *
    rel:/absolute/container/path
    - *
    - *

    - * Volume bindings that specify an absolute path for the host portion are preserved and returned unmodified. - *

    - */ -public class VolumeBindingUtil { - - /** - * A dot representing the current working directory - */ - private static final String DOT = "."; - - /** - * A tilde representing the current user's home directory - */ - private static final String TILDE = "~"; - - /** - * The current runtime platform file separator, '/' for *nix, '\' for Windows - */ - private static final String RUNTIME_SEP = System.getProperty("file.separator"); - - /** - * Windows file separator: '\' - */ - private static final String WINDOWS_SEP = "\\"; - - /** - * Unix file separator '/' - */ - private static final String UNIX_SEP = "/"; - - /** - * Matches a windows drive letter followed by a colon and backwards slash. For example, will match: - * 'C:\' or 'x:\'. - */ - private static final Pattern WINDOWS_DRIVE_PATTERN = Pattern.compile("^[A-Za-z]:\\\\.*"); - - private VolumeBindingUtil() { } - - /** - * Resolves relative paths in the supplied {@code bindingString}, and returns a binding string that has relative - * paths replaced with absolute paths. If the supplied {@code bindingString} does not contain a relative path, it - * is returned unmodified. - * - *
    Discussion: - *

    - * Volumes may be defined inside of {@code service} blocks - * as documented here: - *

    - *
    -     * volumes:
    -     * # Just specify a path and let the Engine create a volume
    -     * - /var/lib/mysql
    -     *
    -     * # Specify an absolute path mapping
    -     * - /opt/data:/var/lib/mysql
    -     *
    -     * # Path on the host, relative to the Compose file
    -     * - ./cache:/tmp/cache
    -     *
    -     * # User-relative path
    -     * - ~/configs:/etc/configs/:ro
    -     *
    -     * # Named volume
    -     * - datavolume:/var/lib/mysql"
    -     * 
    - *

    - * This method only operates on volume strings that are relative: beginning with {@code ./}, {@code ../}, or - * {@code ~}. Relative paths beginning with {@code ./} or {@code ../} are absolutized relative to the supplied - * {@code baseDir}, which must be absolute. Paths beginning with {@code ~} are interpreted relative to - * {@code new File(System.getProperty("user.home"))}, and {@code baseDir} is ignored. - *

    - *

    - * Volume strings that do not begin with a {@code ./}, {@code ../}, or {@code ~} are returned as-is. - *

    - *
    Examples: - *

    - * Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to - * "./reldir:/some/other/dir", this method returns {@code /path/to/basedir/reldir:/some/other/dir} - *

    - *

    - * Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to - * "../reldir:/some/other/dir", this method returns {@code /path/to/reldir:/some/other/dir} - *

    - *

    - * Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} string equal to - * "~/reldir:/some/other/dir", this method returns {@code /home/user/reldir:/some/other/dir} - *

    - *

    - * Given {@code baseDir} equal to "/path/to/basedir" and a {@code bindingString} equal to - * "src/test/docker:/some/other/dir", this method returns {@code /path/to/basedir/src/test/docker:/some/other/dir} - *

    - *

    - * Given a {@code bindingString} equal to "foo:/some/other/dir", this method returns {@code foo:/some/other/dir}, - * because {@code foo} is considered to be a named volume, not a relative path. - *

    - * - * @param baseDir the base directory used to resolve relative paths (e.g. beginning with {@code ./}, {@code ../}, - * {@code ~}) present in the {@code bindingString}; must be absolute - * @param bindingString the volume string from the docker-compose file - * @return the volume string, with any relative paths resolved as absolute paths - */ - public static String resolveRelativeVolumeBinding(File baseDir, String bindingString) { - - // a 'services:' -> service -> 'volumes:' may be formatted as: - // (https://docs.docker.com/compose/compose-file/compose-file-v2/#volumes-volume_driver) - // - // volumes: - // # Just specify a path and let the Engine create a volume - // - /var/lib/mysql - // - // # Specify an absolute path mapping - // - /opt/data:/var/lib/mysql - // - // # Path on the host, relative to the Compose file - // - ./cache:/tmp/cache - // - // # User-relative path - // - ~/configs:/etc/configs/:ro - // - // # Named volume - // - datavolume:/var/lib/mysql - - String[] pathParts = bindingString.split(":"); - String localPath = pathParts[0]; - - if (isRelativePath(localPath)) { - File resolvedFile; - if (isUserHomeRelativePath(localPath)) { - resolvedFile = resolveAbsolutely(prepareUserHomeRelativePath(localPath), System.getProperty("user.home")); - } else { - if (!baseDir.isAbsolute()) { - throw new IllegalArgumentException("Base directory '" + baseDir + "' must be absolute."); - } - resolvedFile = resolveAbsolutely(localPath, baseDir.getAbsolutePath()); - } - try { - localPath = resolvedFile.getCanonicalFile().getAbsolutePath(); - } catch (IOException e) { - throw new RuntimeException("Unable to canonicalize '" + resolvedFile + "'"); - } - } - - if (pathParts.length > 1) { - pathParts[0] = localPath; - return join(":", pathParts); - } - - return localPath; - } - - /** - * Iterates over each {@link RunVolumeConfiguration#getBind() binding} in the {@code volumeConfiguration}, and - * resolves any relative paths in the binding strings using {@link #resolveRelativeVolumeBinding(File, String)}. - * The {@code volumeConfiguration} is modified in place, with any relative paths replaced with absolute paths. - *

    - * Relative paths are resolved relative to the supplied {@code baseDir}, which must be absolute. - *

    - * - * @param baseDir the base directory used to resolve relative paths (e.g. beginning with {@code ./}, {@code ../}, - * {@code ~}) present in the binding string; must be absolute - * @param volumeConfiguration the volume configuration that may contain volume binding specifications - */ - public static void resolveRelativeVolumeBindings(File baseDir, RunVolumeConfiguration volumeConfiguration) { - List bindings = volumeConfiguration.getBind(); - - if (bindings == null || bindings.isEmpty()) { - return; - } - - for (int i = 0; i < bindings.size(); i++) { - bindings.set(i, resolveRelativeVolumeBinding(baseDir, bindings.get(i))); - } - } - - /** - * Determines if the supplied volume binding path contains a relative path. This is subtle, because volume - * bindings may specify a named volume per the discussion below. - *

    Discussion:

    - *

    - * Volumes may be defined inside of {@code service} blocks - * as documented here: - *

    - *
    -     * volumes:
    -     * # Just specify a path and let the Engine create a volume
    -     * - /var/lib/mysql
    -     *
    -     * # Specify an absolute path mapping
    -     * - /opt/data:/var/lib/mysql
    -     *
    -     * # Path on the host, relative to the Compose file
    -     * - ./cache:/tmp/cache
    -     *
    -     * # User-relative path
    -     * - ~/configs:/etc/configs/:ro
    -     *
    -     * # Named volume
    -     * - datavolume:/var/lib/mysql"
    -     * 
    - *

    - * Volume binding paths that begin with {@code ./}, {@code ../}, or {@code ~} clearly represent a relative path. - * However, binding paths that do not begin with those characters may represent a named volume. For - * example, the binding string {@code rel:/path/to/container/mountpoint} refers to the named volume {@code - * rel}. Because it is desirable to fully support relative paths for volumes provided in a run configuration, this - * method attempts to resolve the ambiguity between a named volume and a relative path. - *

    - *

    - * Therefore, volume binding strings will be considered to contain a relative path when any of the following - * conditions are true: - *

      - *
    • the volume binding path begins with {@code ./}, {@code ../}, or {@code ~}
    • - *
    • the volume binding path contains the character {@code /} and {@code /} is not at index 0 of - * the volume binding path
    • - *
    - *

    - *

    - * If the binding string {@code rel:/path/to/container/mountpoint} is intended to represent {@code rel} as a - * relative path and not as a named volume, then the binding string should be modified to contain - * a forward slash like so: {@code rel/:/path/to/container/mountpoint}. Another option would be to prefix {@code - * rel} with a {@code ./} like so: {@code ./rel:/path/to/container/mountpoint} - *

    - * - * - * @param candidatePath the candidate volume binding path - * @return true if the candidate path is considered to be a relative path - */ - static boolean isRelativePath(String candidatePath) { - - // java.io.File considers Windows paths to be absolute _only_ if they start with a drive letter. That is, - // a Windows path '\foo\bar\baz' is _not_ considered absolute by File#isAbsolute. This block differs from - // java.io.File in that it considers Windows paths to be absolute if they begin with the file separator _or_ a - // drive letter - if (candidatePath.startsWith(UNIX_SEP) || - candidatePath.startsWith(WINDOWS_SEP) || - WINDOWS_DRIVE_PATTERN.matcher(candidatePath).matches()) { - return false; - } - - // './' or '../' - if (candidatePath.startsWith(DOT + RUNTIME_SEP) || candidatePath.startsWith(DOT + DOT + RUNTIME_SEP)) { - return true; - } - - if (candidatePath.contains(UNIX_SEP) || candidatePath.contains(WINDOWS_SEP)) { - return true; - } - - if (isUserHomeRelativePath(candidatePath)) { - return true; - } - - return false; - } - - /** - * Returns true if the supplied path begins with {@code ~}. This means that the path should be resolved relative - * to the user's home directory. - * - * @param candidatePath the candidate path that may represent a path under the user's home directory - * @return true if the path begins with {@code ~} - */ - static boolean isUserHomeRelativePath(String candidatePath) { - return candidatePath.startsWith(TILDE); - } - - private static String prepareUserHomeRelativePath(String userHomePath) { - if (!(isUserHomeRelativePath(userHomePath))) { - return userHomePath; - } - - // Handle ~user and ~/path and ~ - - // '~' - if (userHomePath.equals(TILDE)) { - return ""; - } - - // '~/' - if (userHomePath.startsWith(TILDE + RUNTIME_SEP)) { - return userHomePath.substring(2); - } - - // '~user' is not supported; no logic to support "find the home directory for an arbitrary user". - // e.g. '~user' or '~user/foo' - throw new IllegalArgumentException("'" + userHomePath + "' cannot be relativized, cannot resolve arbitrary" + - " user home paths."); - } - - private static String join(String with, String... components) { - StringBuilder result = new StringBuilder(); - int i = 0; - while (i < components.length) { - result.append(components[i++]); - if (i < components.length) { - result.append(with); - } - } - - return result.toString(); - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/ExitCodeChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/ExitCodeChecker.java deleted file mode 100644 index 67f61f8356..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/ExitCodeChecker.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import org.eclipse.jkube.kit.build.service.docker.QueryService; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; - -public class ExitCodeChecker implements WaitChecker { - - private final int exitCodeExpected; - private final String containerId; - private final QueryService queryService; - - public ExitCodeChecker(int exitCodeExpected, QueryService queryService, String containerId) { - this.exitCodeExpected = exitCodeExpected; - this.containerId = containerId; - this.queryService = queryService; - } - - @Override - public boolean check() { - try { - Integer exitCodeActual = queryService.getMandatoryContainer(containerId).getExitCode(); - // container still running - return exitCodeActual != null && exitCodeActual == exitCodeExpected; - } catch (DockerAccessException e) { - return false; - } - } - - @Override - public void cleanUp() { - // No cleanup required - } - - @Override - public String getLogLabel() { - return "on exit code " + exitCodeExpected; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HealthCheckChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HealthCheckChecker.java deleted file mode 100644 index b9b4da6157..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HealthCheckChecker.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import org.eclipse.jkube.kit.build.api.model.ContainerDetails; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccessException; -import org.eclipse.jkube.kit.common.KitLogger; - -/** - * @author roland - * @since 29/03/2017 - */ -public class HealthCheckChecker implements WaitChecker { - - private boolean first = true; - - private final DockerAccess docker; - private final String containerId; - private final KitLogger log; - private final String imageConfigDesc; - - public HealthCheckChecker(DockerAccess docker, String containerId, String imageConfigDesc, KitLogger log) { - this.docker = docker; - this.containerId = containerId; - this.imageConfigDesc = imageConfigDesc; - this.log = log; - } - - @Override - public boolean check() { - try { - final ContainerDetails container = docker.getContainer(containerId); - if (container == null) { - log.debug("HealthWaitChecker: Container %s not found"); - return false; - } - - if (container.getHealthcheck() == null) { - throw new IllegalArgumentException("Can not wait for healthstate of " + imageConfigDesc +". No HEALTHCHECK configured."); - } - - if (first) { - log.info("%s: Waiting to become healthy", imageConfigDesc); - log.debug("HealthWaitChecker: Waiting for healthcheck: '%s'", container.getHealthcheck()); - first = false; - } else if (log.isDebugEnabled()) { - log.debug("HealthWaitChecker: Waiting on healthcheck '%s'", container.getHealthcheck()); - } - - return container.isHealthy(); - } catch(DockerAccessException e) { - log.warn("Error while checking health: %s", e.getMessage()); - return false; - } - } - - @Override - public void cleanUp() {} - - @Override - public String getLogLabel() { - try { - final ContainerDetails container = docker.getContainer(containerId); - return String.format("on healthcheck '%s'",container != null ? container.getHealthcheck() : "[container not found]"); - } catch (DockerAccessException e) { - return String.format("on healthcheck [error fetching container: %s]", e.getMessage()); - } - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HttpPingChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HttpPingChecker.java deleted file mode 100644 index a2fc6a6f1a..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/HttpPingChecker.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import org.eclipse.jkube.kit.config.image.WaitConfiguration; -import org.apache.http.client.config.RequestConfig; -import org.apache.http.client.methods.CloseableHttpResponse; -import org.apache.http.client.methods.RequestBuilder; -import org.apache.http.conn.ssl.NoopHostnameVerifier; -import org.apache.http.conn.ssl.SSLConnectionSocketFactory; -import org.apache.http.conn.ssl.TrustAllStrategy; -import org.apache.http.impl.client.CloseableHttpClient; -import org.apache.http.impl.client.DefaultHttpRequestRetryHandler; -import org.apache.http.impl.client.HttpClientBuilder; -import org.apache.http.ssl.SSLContextBuilder; - -import java.io.IOException; -import java.net.HttpURLConnection; -import java.security.KeyManagementException; -import java.security.KeyStoreException; -import java.security.NoSuchAlgorithmException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Check whether a given URL is available - * - */ -public class HttpPingChecker implements WaitChecker { - - private final int statusMin; - private final int statusMax; - private final String url; - private final String method; - private boolean allowAllHosts; - - // Disable HTTP client retries by default. - private static final int HTTP_CLIENT_RETRIES = 0; - - // Timeout for pings - private static final int HTTP_PING_TIMEOUT = 500; - - /** - * Ping the given URL - * - * @param url URL to check - * @param method HTTP method to use - * @param status status code to check - */ - public HttpPingChecker(String url, String method, String status) { - this.url = url; - this.method = method; - - Matcher matcher = Pattern.compile("^(\\d+)\\s*\\.\\.+\\s*(\\d+)$").matcher(status); - if (matcher.matches()) { - statusMin = Integer.parseInt(matcher.group(1)); - statusMax = Integer.parseInt(matcher.group(2)); - } else { - statusMin = statusMax = Integer.parseInt(status); - } - } - - public HttpPingChecker(String waitUrl) { - this(waitUrl, WaitConfiguration.DEFAULT_HTTP_METHOD, WaitConfiguration.DEFAULT_STATUS_RANGE); - } - - public HttpPingChecker(String url, String method, String status, boolean allowAllHosts) { - this(url, method, status); - this.allowAllHosts = allowAllHosts; - } - - @Override - public boolean check() { - try { - return ping(); - } catch (IOException exception) { - // Could occur and then the check is always considered as failed - return false; - } - } - - private boolean ping() throws IOException { - RequestConfig requestConfig = - RequestConfig.custom() - .setSocketTimeout(HTTP_PING_TIMEOUT) - .setConnectTimeout(HTTP_PING_TIMEOUT) - .setConnectionRequestTimeout(HTTP_PING_TIMEOUT) - .setRedirectsEnabled(false) - .build(); - - CloseableHttpClient httpClient; - if (allowAllHosts) { - SSLContextBuilder builder = new SSLContextBuilder(); - try { - builder.loadTrustMaterial(new TrustAllStrategy()); - SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(builder.build(), NoopHostnameVerifier.INSTANCE); - httpClient = HttpClientBuilder.create() - .setDefaultRequestConfig(requestConfig) - .setRetryHandler(new DefaultHttpRequestRetryHandler(HTTP_CLIENT_RETRIES, false)) - .setSSLSocketFactory(socketFactory) - .setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE) - .build(); - } catch (NoSuchAlgorithmException | KeyStoreException | KeyManagementException e) { - throw new IOException("Unable to set self signed strategy on http wait: " + e, e); - } - } else { - httpClient = HttpClientBuilder.create() - .setDefaultRequestConfig(requestConfig) - .setRetryHandler(new DefaultHttpRequestRetryHandler(HTTP_CLIENT_RETRIES, false)) - .build(); - } - - try (CloseableHttpResponse response = httpClient.execute(RequestBuilder.create(method.toUpperCase()).setUri(url).build())) { - int responseCode = response.getStatusLine().getStatusCode(); - if (responseCode == HttpURLConnection.HTTP_NOT_IMPLEMENTED) { - throw new IllegalArgumentException("Invalid or not supported HTTP method '" + method.toUpperCase() + "' for checking " + url); - } - return responseCode >= statusMin && responseCode <= statusMax; - } finally { - httpClient.close(); - } - } - - @Override - public void cleanUp() { - // No cleanup required for this checker - } - - @Override - public String getLogLabel() { - return "on url " + url; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogMatchCallback.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogMatchCallback.java deleted file mode 100644 index adf80fb9e6..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogMatchCallback.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import org.eclipse.jkube.kit.build.service.docker.access.log.LogCallback; -import org.eclipse.jkube.kit.build.service.docker.helper.Timestamp; -import org.eclipse.jkube.kit.common.KitLogger; - -import java.util.regex.Pattern; - -class LogMatchCallback implements LogCallback { - - private final KitLogger logger; - private final LogWaitCheckerCallback callback; - private final Pattern pattern; - private final StringBuilder logBuffer; - - LogMatchCallback(final KitLogger logger, final LogWaitCheckerCallback callback, final String patternString) { - this.logger = logger; - this.callback = callback; - this.pattern = Pattern.compile(patternString); - logBuffer = (pattern.flags() & Pattern.DOTALL) != 0 ? new StringBuilder() : null; - } - - @Override - public void log(int type, Timestamp timestamp, String txt) throws DoneException { - logger.debug("LogWaitChecker: Trying to match '%s' [Pattern: %s] [thread: %d]", - txt, pattern.pattern(), Thread.currentThread().getId()); - - final String toMatch; - if (logBuffer != null) { - logBuffer.append(txt).append("\n"); - toMatch = logBuffer.toString(); - } else { - toMatch = txt; - } - - if (pattern.matcher(toMatch).find()) { - logger.debug("Found log-wait pattern in log output"); - callback.matched(); - throw new DoneException(); - } - } - - @Override - public void error(String error) { - logger.error("%s", error); - } - - @Override - public void close() { - logger.debug("Closing LogWaitChecker callback"); - } - - @Override - public void open() { - logger.debug("Open LogWaitChecker callback"); - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitChecker.java deleted file mode 100644 index 9f801b0885..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitChecker.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogGetHandle; -import org.eclipse.jkube.kit.common.KitLogger; - -import java.util.concurrent.CountDownLatch; - -/** - * @author roland - * @since 25/03/2017 - */ -public class LogWaitChecker implements WaitChecker, LogWaitCheckerCallback { - - private final String containerId; - private final String logPattern; - private final KitLogger log; - - private final CountDownLatch latch; - private final LogGetHandle logHandle; - - public LogWaitChecker(final String logPattern, final DockerAccess dockerAccess, final String containerId, final KitLogger log) { - this.containerId = containerId; - this.logPattern = logPattern; - this.log = log; - - this.latch = new CountDownLatch(1); - this.logHandle = dockerAccess.getLogAsync(containerId, new LogMatchCallback(log, this, logPattern)); - } - - @Override - public void matched() { - latch.countDown(); - log.info("Pattern '%s' matched for container %s", logPattern, containerId); - } - - @Override - public boolean check() { - return latch.getCount() == 0; - } - - @Override - public void cleanUp() { - if (logHandle != null) { - logHandle.finish(); - } - } - - @Override - public String getLogLabel() { - return "on log out '" + logPattern + "'"; - } -} \ No newline at end of file diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitCheckerCallback.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitCheckerCallback.java deleted file mode 100644 index 2164cd0c2a..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/LogWaitCheckerCallback.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - - -/** - * Interface called during waiting on log when a log line matches - */ -public interface LogWaitCheckerCallback { - void matched(); -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/PreconditionFailedException.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/PreconditionFailedException.java deleted file mode 100644 index 70fe053f41..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/PreconditionFailedException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -/** - * Wait for a certain amount of time - * - * @author roland - * @since 25/03/2017 - */ -public class PreconditionFailedException extends Exception { - private final long waited; - - PreconditionFailedException(String message, long waited) { - super(message); - this.waited = waited; - } - - public long getWaited() { - return waited; - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/TcpPortChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/TcpPortChecker.java deleted file mode 100644 index 4dbbc2ecff..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/TcpPortChecker.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import java.io.IOException; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -/** - * Check whether a given TCP port is available - */ -public class TcpPortChecker implements WaitChecker { - - private static final int TCP_PING_TIMEOUT = 500; - - private final List ports; - - private final List pending; - - public TcpPortChecker(String host, List ports) { - this.ports = ports; - - this.pending = new ArrayList<>(); - for (int port : ports) { - this.pending.add(new InetSocketAddress(host, port)); - } - - } - - public List getPorts() { - return ports; - } - - @Override - public boolean check() { - Iterator iter = pending.iterator(); - - while (iter.hasNext()) { - InetSocketAddress address = iter.next(); - - try (Socket s = new Socket()) { - s.connect(address, TCP_PING_TIMEOUT); - iter.remove(); - } catch (IOException e) { - // Ports isn't opened, yet. So don't remove from queue. - // Can happen and is part of the flow - } - } - return pending.isEmpty(); - } - - @Override - public void cleanUp() { - // No cleanup required - } - - @Override - public String getLogLabel() { - return "on tcp port '" + pending + "'"; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitChecker.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitChecker.java deleted file mode 100644 index 222dca0a49..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitChecker.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -/** - * Interface for various wait checkers - * - * @author roland - * @since 25/03/2017 - */ -public interface WaitChecker { - /** - * @return true if the the check has succeed, false otherwise - */ - boolean check(); - - /** - * Cleanup hook which is called after the wait phase. - */ - void cleanUp(); - - /** - * Get the label to be used in the log - * @return string value of log label - */ - String getLogLabel(); -} \ No newline at end of file diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitTimeoutException.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitTimeoutException.java deleted file mode 100644 index b075ad1521..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitTimeoutException.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import java.util.concurrent.TimeoutException; - -/** - * Wait for a certain amount of time - * - * @author roland - * @since 25/03/2017 - */ -public class WaitTimeoutException extends TimeoutException { - private final long waited; - - WaitTimeoutException(String message, long waited) { - super(message); - this.waited = waited; - } - - public long getWaited() { - return waited; - } -} diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitUtil.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitUtil.java deleted file mode 100644 index ae3bdb1bc9..0000000000 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/wait/WaitUtil.java +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.wait; - -import java.util.Arrays; -import java.util.concurrent.*; - - -/** - * @author roland - * @since 18.10.14 - */ -public class WaitUtil { - - // how long to wait at max when doing a http ping - private static final long DEFAULT_MAX_WAIT = 10 * 1000L; - - // How long to wait between pings - private static final long WAIT_RETRY_WAIT = 500; - - - private WaitUtil() {} - - public static long wait(int wait, Callable callable) throws ExecutionException, WaitTimeoutException { - long now = System.currentTimeMillis(); - if (wait > 0) { - try { - FutureTask task = new FutureTask<>(callable); - task.run(); - - task.get(wait, TimeUnit.SECONDS); - } catch (@SuppressWarnings("unused") InterruptedException e) { - Thread.currentThread().interrupt(); - } catch (@SuppressWarnings("unused") TimeoutException e) { - throw new WaitTimeoutException("timed out waiting for execution to complete: " + e, delta(now)); - } - } - return delta(now); - } - - public static long wait(Precondition precondition, int maxWait, WaitChecker... checkers) throws WaitTimeoutException, PreconditionFailedException { - return wait(precondition, maxWait, Arrays.asList(checkers)); - } - - public static long wait(Precondition precondition, int maxWait, Iterable checkers) throws WaitTimeoutException, PreconditionFailedException { - long max = maxWait > 0 ? maxWait : DEFAULT_MAX_WAIT; - long now = System.currentTimeMillis(); - try { - do { - if (!precondition.isOk()) { - // Final check, could be that the check just succeeded - if (check(checkers)) { - return delta(now); - } - throw new PreconditionFailedException("Precondition failed", delta(now)); - } else { - if (check(checkers)) { - return delta(now); - } - } - sleep(WAIT_RETRY_WAIT); - } while (delta(now) < max); - throw new WaitTimeoutException("No checker finished successfully", delta(now)); - } finally { - precondition.cleanup(); - cleanup(checkers); - } - } - - private static boolean check(Iterable checkers) { - for (WaitChecker checker : checkers) { - if (checker.check()) { - return true; - } - } - return false; - } - - // Give checkers a possibility to clean up - private static void cleanup(Iterable checkers) { - for (WaitChecker checker : checkers) { - checker.cleanUp(); - } - } - - /** - * Sleep a bit - * - * @param millis how long to sleep in milliseconds - */ - public static void sleep(long millis) { - try { - Thread.sleep(millis); - } catch (InterruptedException e) { - // ... - Thread.currentThread().interrupt(); - } - } - - private static long delta(long now) { - return System.currentTimeMillis() - now; - } - - - /** - * Simple interfact for checking some preconditions - */ - public interface Precondition { - // true if precondition is met - boolean isOk(); - // cleanup which might be needed if the check is done. - void cleanup(); - } -} - diff --git a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/watch/WatchContext.java b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/watch/WatchContext.java index c9848e7acc..ae51213403 100644 --- a/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/watch/WatchContext.java +++ b/jkube-kit/build/service/docker/src/main/java/org/eclipse/jkube/kit/build/service/docker/watch/WatchContext.java @@ -19,8 +19,6 @@ import org.eclipse.jkube.kit.build.core.GavLabel; import org.eclipse.jkube.kit.build.service.docker.DockerServiceHub; import org.eclipse.jkube.kit.build.service.docker.WatchService; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogDispatcher; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; import org.eclipse.jkube.kit.build.service.docker.helper.Task; import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.WatchMode; @@ -45,25 +43,16 @@ public class WatchContext implements Serializable { private JKubeConfiguration buildContext; private WatchMode watchMode; private int watchInterval; - private boolean keepRunning; private String watchPostExec; private GavLabel gavLabel; - private boolean keepContainer; - private boolean removeVolumes; - private boolean autoCreateCustomNetworks; private transient Task imageCustomizer; private transient Task containerRestarter; private transient ExecTask containerCommandExecutor; private transient CopyFilesTask containerCopyTask; private transient DockerServiceHub hub; - private transient LogOutputSpecFactory logOutputSpecFactory; - private transient LogDispatcher dispatcher; private transient Runnable postGoalTask; - private boolean follow; - private String showLogs; private Date buildTimestamp; - private String containerNamePattern; } diff --git a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/WatchServiceTest.java b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/WatchServiceTest.java index 8328bb5828..82eaabc123 100644 --- a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/WatchServiceTest.java +++ b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/WatchServiceTest.java @@ -14,118 +14,252 @@ package org.eclipse.jkube.kit.build.service.docker; import java.io.File; +import java.io.IOException; import java.nio.file.Files; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.atomic.AtomicReference; +import java.nio.file.Path; +import java.time.Duration; +import java.util.Collections; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import org.assertj.core.api.InstanceOfAssertFactories; +import org.eclipse.jkube.kit.build.api.assembly.AssemblyManager; import org.eclipse.jkube.kit.build.service.docker.watch.WatchContext; +import org.eclipse.jkube.kit.common.Assembly; +import org.eclipse.jkube.kit.common.AssemblyConfiguration; +import org.eclipse.jkube.kit.common.AssemblyFile; +import org.eclipse.jkube.kit.common.JKubeConfiguration; +import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.KitLogger; import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.WatchImageConfiguration; import org.eclipse.jkube.kit.config.image.WatchMode; +import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; +import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; class WatchServiceTest { - private ArchiveService archiveService; - private BuildService buildService; - private QueryService queryService; - private RunService runService; - private KitLogger logger; - private ImageConfiguration imageConfiguration; + private File watchedFile; + private ScheduledExecutorService executorService; + private ImageConfiguration imageConfiguration; + private BuildService buildService; + private WatchService watchService; + private WatchContext watchContext; + @BeforeEach + void setUp(@TempDir Path tempDir) throws IOException { + watchedFile = Files.createFile(tempDir.resolve("file.txt")).toFile(); + executorService = Executors.newScheduledThreadPool(2); + executorService.scheduleAtFixedRate(this::changeFile, 0, 10, TimeUnit.MILLISECONDS); + final KitLogger logger = new KitLogger.SilentLogger(); + buildService = mock(BuildService.class); + watchService = new WatchService( + new ArchiveService(AssemblyManager.getInstance(), logger), + buildService, + logger); + imageConfiguration = ImageConfiguration.builder() + .name("test-app") + .build(BuildConfiguration.builder() + .assembly(AssemblyConfiguration.builder() + .targetDir("deployments") + .layer(Assembly.builder() + .id("single") + .file(AssemblyFile.builder() + .outputDirectory(new File(".")) + .source(watchedFile) + .fileMode("0755") + .destName("target") + .build()) + .build()) + .build()) + .build()) + .watch(WatchImageConfiguration.builder() + .interval(100) + .postExec("ls -lt /deployments") + .build()) + .build(); + watchContext = WatchContext.builder() + .buildContext(JKubeConfiguration.builder() + .project(JavaProject.builder() + .baseDirectory(tempDir.toFile()) + .build()) + .outputDirectory(Files.createDirectory(tempDir.resolve("target")).toFile().getAbsolutePath()) + .build()) + .build(); + } + + @AfterEach + void tearDown() { + executorService.shutdown(); + } + + @Nested + class Build { @BeforeEach - void setUp() { - archiveService = mock(ArchiveService.class); - buildService = mock(BuildService.class); - queryService = mock(QueryService.class); - runService = mock(RunService.class); - logger = new KitLogger.SilentLogger(); - imageConfiguration = ImageConfiguration.builder() - .name("test-app") - .watch(WatchImageConfiguration.builder() - .postExec("ls -lt /deployments") - .build()) - .build(); + void build() { + watchContext = watchContext.toBuilder().watchMode(WatchMode.build).build(); + } + + @Test + void customizesImage() { + // Given + final CompletableFuture imageCustomized = new CompletableFuture<>(); + watchContext = watchContext.toBuilder() + // Override ImageCustomizer task to set this value to goal executed + .imageCustomizer(imageConfiguration -> imageCustomized.complete(true)) + .build(); + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + assertThat(imageCustomized) + .succeedsWithin(Duration.ofSeconds(5)) + .asInstanceOf(InstanceOfAssertFactories.BOOLEAN) + .isTrue(); } @Test - void restartContainerAndCallPostGoalRestartDisabled() throws Exception { - // Given - AtomicReference stringAtomicReference = new AtomicReference<>("oldVal"); - String mavenGoalToExecute = "org.apache.maven.plugins:maven-help-plugin:help"; - WatchContext watchContext = WatchContext.builder() - .watchMode(WatchMode.both) - // Override PostGoal task to set this value to goal executed - .postGoalTask(() -> stringAtomicReference.compareAndSet( "oldVal", mavenGoalToExecute)) - .build(); - WatchService.ImageWatcher imageWatcher = new WatchService.ImageWatcher(imageConfiguration, watchContext, "test-img", "efe1234"); - WatchService watchService = new WatchService(archiveService, buildService, queryService, runService, logger); - // When - watchService.restartContainerAndCallPostGoal(imageWatcher, false); - // Then - assertThat(stringAtomicReference).hasValue(mavenGoalToExecute); + void buildsImage() throws IOException { + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + verify(buildService, timeout(5000)) + .buildImage(imageConfiguration, null, watchContext.getBuildContext()); } @Test - void restartContainerAndCallPostGoalRestartEnabled() throws Exception { - // Given - AtomicBoolean restarted = new AtomicBoolean(false); - WatchContext watchContext = WatchContext.builder() - .watchMode(WatchMode.both) - .containerRestarter(i -> restarted.set(true)) // Override Restart task to set this value to true - .build(); - WatchService.ImageWatcher imageWatcher = new WatchService.ImageWatcher(imageConfiguration, watchContext, "test-img", "efe1234"); - WatchService watchService = new WatchService(archiveService, buildService, queryService, runService, logger); - // When - watchService.restartContainerAndCallPostGoal(imageWatcher, true); - // Then - assertThat(restarted).isTrue(); + void runsPostGoal() { + // Given + final CompletableFuture postGoalTask = new CompletableFuture<>(); + watchContext = watchContext.toBuilder() + // Override ImageCustomizer task to set this value to goal executed + .postGoalTask(() -> postGoalTask.complete(true)) + .build(); + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + assertThat(postGoalTask) + .succeedsWithin(Duration.ofSeconds(5)) + .asInstanceOf(InstanceOfAssertFactories.BOOLEAN) + .isTrue(); + } + } + @Nested + class Both { + @BeforeEach + void both() { + watchContext = watchContext.toBuilder().watchMode(WatchMode.both).build(); } @Test - void copyFilesToContainer() throws Exception { - // Given - AtomicBoolean fileCopied = new AtomicBoolean(false); - WatchContext watchContext = WatchContext.builder() - .watchMode(WatchMode.copy) - // Override Copy task to set this value to goal executed - .containerCopyTask(f -> fileCopied.compareAndSet(false,true)) - .build(); - File fileToCopy = Files.createTempFile("test-changed-files", "tar").toFile(); - WatchService.ImageWatcher imageWatcher = new WatchService.ImageWatcher(imageConfiguration, watchContext, "test-img", "efe1234"); - WatchService watchService = new WatchService(archiveService, buildService, queryService, runService, logger); - - // When - watchService.copyFilesToContainer(fileToCopy, imageWatcher); - - // Then - assertThat(fileCopied).isTrue(); + void buildsImage() throws IOException { + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + verify(buildService, timeout(5000)) + .buildImage(imageConfiguration, null, watchContext.getBuildContext()); } @Test - void callPostExec() throws Exception { - // Given - AtomicBoolean postExecCommandExecuted = new AtomicBoolean(false); - WatchContext watchContext = WatchContext.builder() - .watchMode(WatchMode.copy) - // Override PostExec task to set this value to goal executed - .containerCommandExecutor(imageWatcher -> { - postExecCommandExecuted.set(true); - return "Some Output"; - }) - .build(); - WatchService.ImageWatcher imageWatcher = new WatchService.ImageWatcher(imageConfiguration, watchContext, "test-img", "efe1234"); - WatchService watchService = new WatchService(archiveService, buildService, queryService, runService, logger); - - // When - watchService.callPostExec(imageWatcher); - - // Then - assertThat(postExecCommandExecuted).isTrue(); + void restartsContainer() { + // Given + final CompletableFuture containerRestarted = new CompletableFuture<>(); + watchContext = watchContext.toBuilder() + // Override ImageCustomizer task to set this value to goal executed + .containerRestarter(imageWatcher -> containerRestarted.complete(true)) + .build(); + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + assertThat(containerRestarted) + .succeedsWithin(Duration.ofSeconds(5)) + .asInstanceOf(InstanceOfAssertFactories.BOOLEAN) + .isTrue(); + } + } + + @Nested + class Copy { + @BeforeEach + void copy() { + watchContext = watchContext.toBuilder().watchMode(WatchMode.copy).build(); + } + + @Test + void copiesFiles() { + // Given + final CompletableFuture fileCopied = new CompletableFuture<>(); + watchContext = watchContext.toBuilder() + // Override Copy task to set this value to goal executed + .containerCopyTask(f -> fileCopied.complete(true)) + .build(); + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + assertThat(fileCopied) + .succeedsWithin(Duration.ofSeconds(5)) + .asInstanceOf(InstanceOfAssertFactories.BOOLEAN) + .isTrue(); + } + + @Test + void callsPostExec() { + // Given + final CompletableFuture postExec = new CompletableFuture<>(); + watchContext = watchContext.toBuilder() + // Override PostExec task to set this value to goal executed + .containerCommandExecutor(imageWatcher -> { + postExec.complete(true); + return "done!"; + }) + .build(); + // When + executorService.submit(() -> { + watchService.watch(watchContext, Collections.singletonList(imageConfiguration)); + return null; + }); + // Then + assertThat(postExec) + .succeedsWithin(Duration.ofSeconds(5)) + .asInstanceOf(InstanceOfAssertFactories.BOOLEAN) + .isTrue(); + } + } + + + private void changeFile() { + try { + Files.write(watchedFile.toPath(), "test".getBytes()); + } catch (IOException e) { + throw new RuntimeException(e); } + } } diff --git a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandlerTest.java b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandlerTest.java index 66522680cc..6d435df24f 100644 --- a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandlerTest.java +++ b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/config/handler/property/PropertyConfigHandlerTest.java @@ -25,8 +25,6 @@ import org.assertj.core.api.InstanceOfAssertFactories; import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.config.image.ImageConfiguration; -import org.eclipse.jkube.kit.config.image.RunImageConfiguration; -import org.eclipse.jkube.kit.config.image.UlimitConfig; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.eclipse.jkube.kit.config.image.build.CleanupMode; import org.junit.jupiter.api.BeforeEach; @@ -66,14 +64,6 @@ void testSkipBuild() { assertThat(resolveExternalImageConfig(mergeArrays(getBaseTestData(), new String[] {k(ConfigKey.NAME), "image", k(ConfigKey.FROM), "busybox"})).getBuildConfiguration().getSkip()).isFalse(); } - @Test - void testSkipRun() { - assertThat(resolveExternalImageConfig(getSkipTestData(ConfigKey.SKIP_RUN, false)).getRunConfiguration().skip()).isFalse(); - assertThat(resolveExternalImageConfig(getSkipTestData(ConfigKey.SKIP_RUN, true)).getRunConfiguration().skip()).isTrue(); - - assertThat(resolveExternalImageConfig(mergeArrays(getBaseTestData(), new String[] {k(ConfigKey.NAME), "image"})).getRunConfiguration().skip()).isFalse(); - } - @Test void testType() { assertThat(configHandler.getType()).isNotNull(); @@ -88,10 +78,6 @@ void testPortsFromConfigAndProperties() { .addCacheFrom("foo/bar:latest") .build() ) - .run(RunImageConfiguration.builder() - .ports(Collections.singletonList("jolokia.port:1234")) - .build() - ) .build(); makeExternalConfigUse(); @@ -104,11 +90,6 @@ void testPortsFromConfigAndProperties() { "docker.from", "busybox" )); assertThat(configs).singleElement() - .satisfies(config -> assertThat(config) - .extracting(ImageConfiguration::getRunConfiguration) - .extracting(RunImageConfiguration::getPorts) - .asList() - .containsExactly("9090", "0.0.0.0:80:80", "jolokia.port:1234")) .satisfies(config -> assertThat(config) .extracting(ImageConfiguration::getBuildConfiguration) .extracting(BuildConfiguration::getPorts) @@ -268,20 +249,14 @@ void testEnvAndLabels() { assertThat(configs).hasSize(1); ImageConfiguration calcConfig = configs.get(0); - for (Map env : new Map[] { calcConfig.getBuildConfiguration().getEnv(), - calcConfig.getRunConfiguration().getEnv()}) { - assertThat(env).hasSize(2) - .contains( - entry("HOME", "/tmp"), - entry("root.dir", "/bla")); - } - for (Map labels : new Map[] { calcConfig.getBuildConfiguration().getLabels(), - calcConfig.getRunConfiguration().getLabels()}) { - assertThat(labels).hasSize(3) - .contains( - entry("version", "1.0.0"), - entry("blub.bla.foobar", "yep")); - } + assertThat(calcConfig.getBuildConfiguration().getEnv()).hasSize(2) + .contains( + entry("HOME", "/tmp"), + entry("root.dir", "/bla")); + assertThat(calcConfig.getBuildConfiguration().getLabels()).hasSize(3) + .contains( + entry("version", "1.0.0"), + entry("blub.bla.foobar", "yep")); } @@ -296,18 +271,11 @@ void testSpecificEnv() { }))); assertThat(configs).singleElement() - .satisfies(config -> assertThat(config) - .extracting(ImageConfiguration::getBuildConfiguration) - .extracting(BuildConfiguration::getEnv) - .asInstanceOf(InstanceOfAssertFactories.MAP) - .hasSize(1) - .containsEntry("HOME", "/tmp")) - .satisfies(config -> assertThat(config) - .extracting(ImageConfiguration::getRunConfiguration) - .extracting(RunImageConfiguration::getEnv) - .asInstanceOf(InstanceOfAssertFactories.MAP) - .hasSize(1) - .containsEntry("root.dir", "/bla")); + .extracting(ImageConfiguration::getBuildConfiguration) + .extracting(BuildConfiguration::getEnv) + .asInstanceOf(InstanceOfAssertFactories.MAP) + .hasSize(1) + .containsEntry("HOME", "/tmp"); } @Test @@ -420,7 +388,6 @@ void testResolve() { ImageConfiguration resolved = resolveExternalImageConfig(mergeArrays(getBaseTestData(), getTestData())); validateBuildConfiguration(resolved.getBuildConfiguration()); - validateRunConfiguration(resolved.getRunConfiguration()); //validateWaitConfiguraion(resolved.getRunConfiguration().getWaitConfiguration()); } @@ -507,69 +474,6 @@ private void validateBuildOptions(Map buildOptions) { assertThat(buildOptions).containsEntry("shmsize", "2147483648"); } - protected void validateRunConfiguration(RunImageConfiguration runConfig) { - assertThat(runConfig) - .returns(a("/foo", "/tmp:/tmp"), c -> c.getVolumeConfiguration().getBind()) - .returns(a("CAP"), RunImageConfiguration::getCapAdd) - .returns(a("CAP"), RunImageConfiguration::getCapDrop) - .returns(a("seccomp=unconfined"), RunImageConfiguration::getSecurityOpts) - .returns("command.sh", c -> c.getCmd().getShell()) - .returns(a("8.8.8.8"), RunImageConfiguration::getDns) - .returns("host", c -> c.getNetworkingConfig().getStandardMode(null)) - .returns(a("example.com"), RunImageConfiguration::getDnsSearch) - .returns("domain.com", RunImageConfiguration::getDomainname) - .returns("entrypoint.sh", c -> c.getEntrypoint().getShell()) - .returns(a("localhost:127.0.0.1"), RunImageConfiguration::getExtraHosts) - .returns("subdomain", RunImageConfiguration::getHostname) - .returns(a("redis"), RunImageConfiguration::getLinks) - .returns(1L, RunImageConfiguration::getMemory) - .returns(1L, RunImageConfiguration::getMemorySwap) - .returns(1000000000L, RunImageConfiguration::getCpus) - .returns(1L, RunImageConfiguration::getCpuShares) - .returns("0,1", RunImageConfiguration::getCpuSet) - .returns("/tmp/envProps.txt", RunImageConfiguration::getEnvPropertyFile) - .returns("/tmp/props.txt", RunImageConfiguration::getPortPropertyFile) - .returns("8081:8080", c -> c.getPorts().get(0)) - .returns(true, RunImageConfiguration::getPrivileged) - .returns("tomcat", RunImageConfiguration::getUser) - .returns(a("from"), c -> c.getVolumeConfiguration().getFrom()) - .returns("foo", RunImageConfiguration::getWorkingDir) - .returns(4, c -> c.getUlimits().size()) - .returns("/var/lib/mysql:10m", c -> c.getTmpfs().get(0)) - .returns("Never", RunImageConfiguration::getImagePullPolicy) - .returns(true, RunImageConfiguration::getReadOnly) - .returns(true, RunImageConfiguration::getAutoRemove) - .returns("on-failure", c -> c.getRestartPolicy().getName()) - .returns(1, c -> c.getRestartPolicy().getRetry()) - .returns("http://foo.com", c -> c.getWait().getUrl()) - .returns("pattern", c -> c.getWait().getLog()) - .returns("post_start_command", c -> c.getWait().getExec().getPostStart()) - .returns("pre_stop_command", c -> c.getWait().getExec().getPreStop()) - .returns(true, c -> c.getWait().getExec().isBreakOnError()) - .returns(5, c -> c.getWait().getTime()) - .returns(true, c -> c.getWait().getHealthy()) - .returns(0, c -> c.getWait().getExit()) - .returns("green", c -> c.getLog().getColor()) - .returns(true, c -> c.getLog().isEnabled()) - .returns("SRV", c -> c.getLog().getPrefix()) - .returns("iso8601", c -> c.getLog().getDate()) - .returns("json", c -> c.getLog().getDriver().getName()) - .returns(2, c -> c.getLog().getDriver().getOpts().size()) - .returns("1024", c -> c.getLog().getDriver().getOpts().get("max-size")) - .returns("10", c -> c.getLog().getDriver().getOpts().get("max-file")); - - assertThat(runConfig.getUlimits()).isNotNull(); - assertUlimitEquals(ulimit(10,10),runConfig.getUlimits().get(0)); - assertUlimitEquals(ulimit(null,-1),runConfig.getUlimits().get(1)); - assertUlimitEquals(ulimit(1024,null),runConfig.getUlimits().get(2)); - assertUlimitEquals(ulimit(2048,null),runConfig.getUlimits().get(3)); - validateEnv(runConfig.getEnv()); - } - - private UlimitConfig ulimit(Integer hard, Integer soft) { - return new UlimitConfig("memlock", hard, soft); - } - private Properties props(String ... args) { Properties ret = new Properties(); for (int i = 0; i < args.length; i += 2) { @@ -665,13 +569,6 @@ private String k(ConfigKey from) { return from.asPropertyKey(); } - private void assertUlimitEquals(UlimitConfig expected, UlimitConfig actual){ - assertThat(actual) - .hasFieldOrPropertyWithValue("name", expected.getName()) - .hasFieldOrPropertyWithValue("soft", expected.getSoft()) - .hasFieldOrPropertyWithValue("hard", expected.getHard()); - } - private List a(String ... args) { return Arrays.asList(args); } @@ -697,4 +594,4 @@ private String[] mergeArrays(String[] a, String[] b) { for (String s : b) mergedArr[mergedIndex++] = s; return mergedArr; } -} \ No newline at end of file +} diff --git a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/helper/AnsiLoggerFacadeTest.java b/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/helper/AnsiLoggerFacadeTest.java deleted file mode 100644 index 8aef031da1..0000000000 --- a/jkube-kit/build/service/docker/src/test/java/org/eclipse/jkube/kit/build/service/docker/helper/AnsiLoggerFacadeTest.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.build.service.docker.helper; - -import org.eclipse.jkube.kit.common.KitLogger; -import org.fusesource.jansi.Ansi; -import org.junit.jupiter.api.Test; - -import static org.assertj.core.api.Assertions.assertThat; - -/** - * @author roland - * @since 07/10/16 - */ -class AnsiLoggerFacadeTest { - - @Test - void emphasize() { - TestLog testLog = new TestLog(); - AnsiLoggerFacade logger = new AnsiLoggerFacade(testLog, true, false, false, "T>"); - Ansi ansi = Ansi.ansi(); - logger.info("Yet another [[*]]Test[[*]] %s","emphasis"); - assertThat(testLog.getMessage()).isEqualTo( - ansi.a("T>") - .fg(AnsiLoggerFacade.COLOR_INFO) - .a("Yet another ") - .fgBright(AnsiLoggerFacade.COLOR_EMPHASIS) - .a("Test") - .fg(AnsiLoggerFacade.COLOR_INFO) - .a(" emphasis") - .reset().toString()); - } - - - private class TestLog extends KitLogger.StdoutLogger { - private String message; - - @Override - public void info(String content, Object ... args) { - this.message = content; - super.info(content); - } - - void reset() { - message = null; - } - - public String getMessage() { - return message; - } - } - -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/ImageConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/ImageConfiguration.java index 9910f3dd34..b87e00928d 100644 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/ImageConfiguration.java +++ b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/ImageConfiguration.java @@ -14,14 +14,8 @@ package org.eclipse.jkube.kit.config.image; import java.io.Serializable; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; import java.util.Map; -import java.util.Optional; -import java.util.stream.Collectors; -import org.eclipse.jkube.kit.common.util.EnvUtil; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import lombok.AllArgsConstructor; @@ -47,7 +41,6 @@ public class ImageConfiguration implements Serializable { */ private String name; private String alias; - private RunImageConfiguration run; private BuildConfiguration build; private WatchImageConfiguration watch; /** @@ -67,10 +60,6 @@ public void setExternalConfiguration(Map externalConfiguration) this.external = externalConfiguration; } - public RunImageConfiguration getRunConfiguration() { - return (run == null) ? RunImageConfiguration.DEFAULT : run; - } - public BuildConfiguration getBuildConfiguration() { return build; } @@ -83,43 +72,6 @@ public Map getExternalConfig() { return external; } - public List getDependencies() { - final RunImageConfiguration runConfig = getRunConfiguration(); - final List ret = new ArrayList<>(); - if (runConfig != null) { - ret.addAll(extractVolumes(runConfig)); - ret.addAll(extractLinks(runConfig)); - getContainerNetwork(runConfig).ifPresent(ret::add); - ret.addAll(extractDependsOn(runConfig)); - } - return ret; - } - - private static List extractVolumes(RunImageConfiguration runConfig) { - return Optional.ofNullable(runConfig).map(RunImageConfiguration::getVolumeConfiguration) - .map(RunVolumeConfiguration::getFrom).orElse(Collections.emptyList()); - } - - private static List extractLinks(RunImageConfiguration runConfig) { - // Custom networks can have circular links, no need to be considered for the starting order. - if (!runConfig.getNetworkingConfig().isCustomNetwork()) { - return EnvUtil.splitOnLastColon(runConfig.getLinks()).stream().map(a -> a[0]).collect(Collectors.toList()); - } - return Collections.emptyList(); - } - - private static Optional getContainerNetwork(RunImageConfiguration runConfig) { - return Optional.ofNullable(runConfig).map(RunImageConfiguration::getNetworkingConfig).map(NetworkConfig::getContainerAlias); - } - - private static List extractDependsOn(RunImageConfiguration runConfig) { - // Only used in custom networks. - if (runConfig.getNetworkingConfig().isCustomNetwork()) { - return runConfig.getDependsOn(); - } - return Collections.emptyList(); - } - public String getDescription() { return String.format("[%s] %s", new ImageName(name).getFullName(), (alias != null ? "\"" + alias + "\"" : "")).trim(); } diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/LogConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/LogConfiguration.java deleted file mode 100644 index df922523a0..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/LogConfiguration.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.util.Map; -import java.util.Optional; - - -/** - * @author roland - */ -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class LogConfiguration implements Serializable { - - private static final long serialVersionUID = 6896468158396394236L; - - public static final LogConfiguration DEFAULT = new LogConfiguration(null, null, null, null, null, null, null); - - private boolean enabled; - private String prefix; - private String date; - private String color; - private String file; - private LogDriver driver; - - @Builder - private LogConfiguration( - Boolean enabled, String prefix, String color, String date, String file, Map logDriverOpts, String driverName) { - this.enabled = Optional.ofNullable(enabled).orElse(false); - this.prefix = prefix; - this.date = date; - this.color = color; - this.file = file; - this.driver = Optional.ofNullable(driverName).map(dn -> new LogDriver(dn, logDriverOpts)).orElse(null); - } - - /** - * If explicitly enabled, or configured in any way and NOT explicitly disabled, return true. - * - * @return whether its activated or not - */ - public boolean isActivated() { - return enabled || !isBlank(); - } - - /** - * Returns true if all options (except enabled) are null, used to decide value of enabled. - * - * @return whether its blank or not - */ - private boolean isBlank() { - return prefix == null && date == null && color == null && file == null && driver == null; - } - - public String getFileLocation() { - return file; - } - - public static class LogDriver implements Serializable { - - private final String name; - - private final Map opts; - - private LogDriver(String name, Map opts) { - this.name = name; - this.opts = opts; - } - - public String getName() { - return name; - } - - public Map getOpts() { - return opts; - } - } - -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/NetworkConfig.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/NetworkConfig.java deleted file mode 100644 index 061923f637..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/NetworkConfig.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; - -/** - * Network config encapsulating network specific configuration - * @author roland - * @since 29/07/16 - */ -@Getter -@EqualsAndHashCode -public class NetworkConfig implements Serializable { - - private final String name; - private final Mode mode; - private final List aliases; - - public NetworkConfig() { - this(null, null, null); - } - - @Builder - public NetworkConfig(Mode mode, String name, List aliases) { - this.name = name; - this.mode = mode; - this.aliases = Optional.ofNullable(aliases).orElse(new ArrayList<>()); - } - // Use by Maven to add flattened entries - // See http://blog.sonatype.com/2011/03/configuring-plugin-goals-in-maven-3/ - public void addAlias(String alias) { - aliases.add(alias); - } - - /** - * Legacy constructor using the ;<net;> config - * @param net net, encapsulating mode and name. - */ - public static NetworkConfig fromLegacyNetSpec(String net) { - Mode mode = null; - String name = null; - if (net != null) { - mode = extractMode(net); - if (mode == Mode.container) { - name = net.substring(Mode.container.name().length() + 1); - } else if (mode == Mode.custom) { - name = net; - } - } - return NetworkConfig.builder().mode(mode).name(name).build(); - } - - private static Mode extractMode(String mode) { - if (mode != null && mode.length() > 0) { - try { - return Mode.valueOf(mode.toLowerCase()); - } catch (IllegalArgumentException exp) { /* could be a custom mode, too */ } - if (mode.toLowerCase().startsWith(Mode.container.name() + ":")) { - return Mode.container; - } else { - return Mode.custom; - } - } - return null; - } - - public boolean isCustomNetwork() { - return (mode != null && mode == Mode.custom) || (mode == null && name != null); - } - - public boolean isStandardNetwork() { - return mode != null && mode != Mode.custom; - } - - public String getStandardMode(String containerId) { - if (isCustomNetwork()) { - throw new IllegalArgumentException("Custom network for network '" + name + - "' can not be used as standard mode"); - } - if (mode == null) { - return null; - } - return mode.name().toLowerCase() + (mode == Mode.container ? ":" + containerId : ""); - } - - public String getContainerAlias() { - return mode == Mode.container ? name : null; - } - - public String getCustomNetwork() { - return mode == Mode.custom || mode == null ? name : null; - } - - public boolean hasAliases() { - return aliases != null && !aliases.isEmpty(); - } - - - // Mode used for determining the network - public enum Mode { - none, - bridge, - host, - container, - custom - } - - public static class NetworkConfigBuilder { - - public NetworkConfigBuilder modeString(String modeString){ - mode = Optional.ofNullable(modeString).map(Mode::valueOf).orElse(null); - return this; - } - - public NetworkConfig build() { - return mode == null && name == null && aliases == null ? - null : new NetworkConfig(mode, name, aliases); - } - - } -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RestartPolicy.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RestartPolicy.java deleted file mode 100644 index fae7b2252b..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RestartPolicy.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; - -/** - * @author roland - */ -@Builder -@AllArgsConstructor -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class RestartPolicy implements Serializable { - - private static final long serialVersionUID = 7192766280075022364L; - - public static final RestartPolicy DEFAULT = new RestartPolicy(); - - private String name; - private int retry; - -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunImageConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunImageConfiguration.java deleted file mode 100644 index adeb99d022..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunImageConfiguration.java +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Optional; - -import javax.annotation.Nonnull; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; -import org.eclipse.jkube.kit.common.util.EnvUtil; -import org.eclipse.jkube.kit.common.Arguments; - -/** - * @author roland - */ -@Builder(toBuilder = true) -@AllArgsConstructor -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class RunImageConfiguration implements Serializable { - - private static final long serialVersionUID = 439009097742935171L; - - public static final RunImageConfiguration DEFAULT = new RunImageConfiguration(); - - public boolean isDefault() { - return this == RunImageConfiguration.DEFAULT; - } - - /** - * Environment variables to set when starting the container. key: variable name, value: env value. - */ - private Map env; - private Map labels; - /** - * Path to a property file holding environment variables. - */ - private String envPropertyFile; - /** - * Command to execute in container. - */ - private Arguments cmd; - /** - * Container domain name. - */ - private String domainname; - private List dependsOn; - /** - * Container entry point. - */ - private Arguments entrypoint; - /** - * Container hostname. - */ - private String hostname; - /** - * Container user. - */ - private String user; - /** - * Working directory. - */ - private String workingDir; - /** - * Size of /dev/shm in bytes. - */ - private Long shmSize; - /** - * Memory in bytes. - */ - private Long memory; - /** - * Total memory (swap + ram) in bytes, -1 to disable. - */ - private Long memorySwap; - /** - * Path to a file where the dynamically mapped properties are written to. - */ - private String portPropertyFile; - /** - * For simple network setups. For complex stuff use "network". - */ - private String net; - private NetworkConfig network; - private List dns; - private List dnsSearch; - private List capAdd; - private List capDrop; - private List securityOpts; - private Boolean privileged; - private List extraHosts; - private Long cpuShares; - private Long cpus; - private String cpuSet; - /** - * Port mapping. Can contain symbolic names in which case dynamic ports are used. - * - * - */ - private List ports; - /** - * A pattern to define the naming of the container where: - * - *
      - *
    • %a for the "alias" mode
    • - *
    • %n for the image name
    • - *
    • %t for a timestamp
    • - *
    • %i for an increasing index of container names
    • - *
    - * - */ - private String containerNamePattern; - /** - * Property key part used to expose the container ip when running. - */ - private String exposedPropertyKey; - /** - * Mount volumes from the given image's started containers. - */ - private RunVolumeConfiguration volumes; - /** - * Links to other container started. - */ - private List links; - /** - * Configuration for how to wait during startup of the container. - */ - private WaitConfiguration wait; - /** - * Mountpath for tmps. - */ - private List tmpfs; - private LogConfiguration log; - private RestartPolicy restartPolicy; - private List ulimits; - private Boolean skip; - /** - * Policy for pulling the image to start - */ - private String imagePullPolicy; - /** - * Mount the container's root filesystem as read only. - */ - private Boolean readOnly; - /** - * Automatically remove the container when it exists. - */ - private Boolean autoRemove; - - public String initAndValidate() { - if (entrypoint != null) { - entrypoint.validate(); - } - if (cmd != null) { - cmd.validate(); - } - - /** - * Custom networks are available since API 1.21 (Docker 1.9). - */ - NetworkConfig config = getNetworkingConfig(); - if (config != null && config.isCustomNetwork()) { - return "1.21"; - } - - return null; - } - - @Nonnull - public List getDependsOn() { - return EnvUtil.splitAtCommasAndTrim(dependsOn); - } - - @Nonnull - public List getPorts() { - return EnvUtil.removeEmptyEntries(ports); - } - - public NetworkConfig getNetworkingConfig() { - if (network != null) { - return network; - } else if (net != null) { - return NetworkConfig.fromLegacyNetSpec(net); - } else { - return new NetworkConfig(); - } - } - - public RunVolumeConfiguration getVolumeConfiguration() { - return volumes; - } - - @Nonnull - public List getLinks() { - return EnvUtil.splitAtCommasAndTrim(links); - } - - public RestartPolicy getRestartPolicy() { - return Optional.ofNullable(restartPolicy).orElse(RestartPolicy.DEFAULT); - } - - public boolean skip() { - return Optional.ofNullable(skip).orElse(false); - } -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunVolumeConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunVolumeConfiguration.java deleted file mode 100644 index bdc1613ae0..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/RunVolumeConfiguration.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.util.*; - -/** - * Run configuration for volumes. - * - * @author roland - */ -@SuppressWarnings("JavaDoc") -@Builder -@AllArgsConstructor -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class RunVolumeConfiguration implements Serializable { - - /** - * List of images names from where volumes are mounted - * - * @return images - */ - private List from; - /** - * List of bind parameters for binding/mounting host directories - * into the container - * - * @return list of bind specs - */ - private List bind; - - public static class RunVolumeConfigurationBuilder { - public RunVolumeConfigurationBuilder from(List args) { - if (args != null) { - if (from == null) { - from = new ArrayList<>(); - } - from.addAll(args); - } - return this; - } - - public RunVolumeConfigurationBuilder bind(List args) { - if (args != null) { - if (bind == null) { - bind = new ArrayList<>(); - } - bind.addAll(args); - } - return this; - } - } -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/UlimitConfig.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/UlimitConfig.java deleted file mode 100644 index 0ea6aa6405..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/UlimitConfig.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import java.io.Serializable; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - - -/** - * Configuration for ulimit - * - * @since 0.15 - * @author Alexis Thaveau - */ -public class UlimitConfig implements Serializable { - - private String name; - - private Integer hard; - - private Integer soft; - - public UlimitConfig(String name, Integer hard, Integer soft) { - this.name = name; - this.hard = hard; - this.soft = soft; - } - - public String getName() { - return name; - } - - public Integer getHard() { - return hard; - } - - public Integer getSoft() { - return soft; - } - - private static final Pattern ULIMIT_PATTERN = Pattern.compile("^(?[^=]+)=(?[^:]*):?(?[^:]*)$"); - - public UlimitConfig() {} - - public UlimitConfig(String ulimit) { - Matcher matcher = ULIMIT_PATTERN.matcher(ulimit); - if (matcher.matches()) { - name = matcher.group("name"); - hard = asInteger(matcher.group("hard")); - soft = asInteger(matcher.group("soft")); - } else { - throw new IllegalArgumentException("Invalid ulimit specification " + ulimit); - } - } - - private Integer asInteger(String number) { - if (number == null || number.length() == 0) { - return null; - } - return Integer.parseInt(number); - } - - public String serialize() { - if(hard != null && soft != null) { - return name + "="+hard+":"+soft; - } else if(hard != null) { - return name + "="+hard; - } else if(soft != null) { - return name + "=:"+soft; - } else { - return null; - } - } -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WaitConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WaitConfiguration.java deleted file mode 100644 index 328e6f73a3..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WaitConfiguration.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image; - -import lombok.AllArgsConstructor; -import lombok.Builder; -import lombok.EqualsAndHashCode; -import lombok.Getter; -import lombok.NoArgsConstructor; - -import java.io.Serializable; -import java.util.List; -import java.util.Optional; - - -/** - * @author roland - */ -@AllArgsConstructor -@NoArgsConstructor -@Getter -@EqualsAndHashCode -public class WaitConfiguration implements Serializable { - - // Default HTTP Method to use - public static final String DEFAULT_HTTP_METHOD = "HEAD"; - - // Default status codes - public static final int DEFAULT_MIN_STATUS = 200; - public static final int DEFAULT_MAX_STATUS = 399; - - public static final String DEFAULT_STATUS_RANGE = String.format("%d..%d", DEFAULT_MIN_STATUS, DEFAULT_MAX_STATUS); - - private Integer time; - private HttpConfiguration http; - private ExecConfiguration exec; - private TcpConfiguration tcp; - private Boolean healthy; - private String log; - private Integer shutdown; - private Integer kill; - private Integer exit; - - @SuppressWarnings("unused") - @Builder - public WaitConfiguration( - Integer time, - String url, String method, String status, - String postStart, String preStop, Boolean breakOnError, - TcpConfigMode tcpMode, String tcpHost, List tcpPorts, - Boolean healthy, String log, Integer shutdown, Integer kill, Integer exit) { - - this.time = time; - if (url != null) { - this.http = new HttpConfiguration(url, method, status); - } - if (postStart != null || preStop != null) { - this.exec = new ExecConfiguration(postStart, preStop, Optional.ofNullable(breakOnError).orElse(false)); - } - if (tcpPorts != null) { - this.tcp = new TcpConfiguration(tcpMode, tcpHost, tcpPorts); - } - this.healthy = healthy; - this.log = log; - this.shutdown = shutdown; - this.kill = kill; - this.exit = exit; - } - - public String getUrl() { - return Optional.ofNullable(http).map(HttpConfiguration::getUrl).orElse(null); - } - - public static class WaitConfigurationBuilder { - public WaitConfigurationBuilder tcpModeString(String tcpModeString) { - tcpMode = Optional.ofNullable(tcpModeString).map(String::toLowerCase).map(TcpConfigMode::valueOf).orElse(null); - return this; - } - } - - @AllArgsConstructor - @NoArgsConstructor - @Getter - @EqualsAndHashCode - public static class ExecConfiguration implements Serializable { - private String postStart; - private String preStop; - private boolean breakOnError; - } - - @AllArgsConstructor - @NoArgsConstructor - @Getter - @EqualsAndHashCode - public static class HttpConfiguration implements Serializable { - - private static final long serialVersionUID = -4093004978420554981L; - - private String url; - private String method = DEFAULT_HTTP_METHOD; - private String status = DEFAULT_STATUS_RANGE; - private boolean allowAllHosts; - - private HttpConfiguration(String url, String method, String status) { - this(url, method, status, false); - } - } - - public enum TcpConfigMode { - // Use mapped ports - mapped, - // Use ports directly on the container - direct, - } - - @AllArgsConstructor - @NoArgsConstructor - @Getter - @EqualsAndHashCode - public static class TcpConfiguration implements Serializable { - - private static final long serialVersionUID = 4809023624478231971L; - - private TcpConfigMode mode; - private String host; - private List ports; - } - -} - diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WatchImageConfiguration.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WatchImageConfiguration.java index 80f988172a..a02f0eb3ea 100644 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WatchImageConfiguration.java +++ b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/WatchImageConfiguration.java @@ -33,14 +33,18 @@ public class WatchImageConfiguration implements Serializable { private static final long serialVersionUID = -8837447095092135706L; + private static final int DEFAULT_INTERVAL = 5000; + /** + * Interval in milliseconds to check/poll for changes + */ private Integer interval; private WatchMode mode; private String postGoal; private String postExec; public int getInterval() { - return interval != null ? interval : 5000; + return interval != null ? interval : DEFAULT_INTERVAL; } public Integer getIntervalRaw() { diff --git a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildImageSelectMode.java b/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildImageSelectMode.java deleted file mode 100644 index 296e4d5b8f..0000000000 --- a/jkube-kit/config/image/src/main/java/org/eclipse/jkube/kit/config/image/build/BuildImageSelectMode.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * Copyright (c) 2019 Red Hat, Inc. - * This program and the accompanying materials are made - * available under the terms of the Eclipse Public License 2.0 - * which is available at: - * - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Red Hat, Inc. - initial API and implementation - */ -package org.eclipse.jkube.kit.config.image.build; - -/** - * How to build source tar files. - * - * @author roland - * @since 26/04/16 - */ -public enum BuildImageSelectMode { - - // Pick only the first build configuration - first, - - // Include all builds with alias names as classifiers - all; - -} diff --git a/jkube-kit/watcher/standard/src/main/java/org/eclipse/jkube/watcher/standard/DockerImageWatcher.java b/jkube-kit/watcher/standard/src/main/java/org/eclipse/jkube/watcher/standard/DockerImageWatcher.java index 17eba41bd1..5722c370f5 100644 --- a/jkube-kit/watcher/standard/src/main/java/org/eclipse/jkube/watcher/standard/DockerImageWatcher.java +++ b/jkube-kit/watcher/standard/src/main/java/org/eclipse/jkube/watcher/standard/DockerImageWatcher.java @@ -104,7 +104,7 @@ public void watch(List configs, String namespace, final Coll DockerServiceHub hub = getContext().getJKubeServiceHub().getDockerServiceHub(); try { - hub.getWatchService().watch(watchContext, getContext().getBuildContext(), configs); + hub.getWatchService().watch(watchContext, configs); } catch (Exception ex) { throw new RuntimeException("Error while watching", ex); } diff --git a/jkube-kit/watcher/standard/src/test/java/org/eclipse/jkube/watcher/standard/DockerImageWatcherTest.java b/jkube-kit/watcher/standard/src/test/java/org/eclipse/jkube/watcher/standard/DockerImageWatcherTest.java index 3a1260c997..1d56b92676 100644 --- a/jkube-kit/watcher/standard/src/test/java/org/eclipse/jkube/watcher/standard/DockerImageWatcherTest.java +++ b/jkube-kit/watcher/standard/src/test/java/org/eclipse/jkube/watcher/standard/DockerImageWatcherTest.java @@ -81,7 +81,7 @@ void watchShouldInitWatchContext() throws IOException { // When dockerImageWatcher.watch(null, null, null, null); // Then - verify(watchService).watch(watchContextArgumentCaptor.capture(),any(),any()); + verify(watchService).watch(watchContextArgumentCaptor.capture(), any()); assertThat(watchContextArgumentCaptor.getValue()) .isNotNull() .extracting("imageCustomizer","containerRestarter","containerCommandExecutor","containerCopyTask") @@ -94,7 +94,7 @@ void watchExecuteCommandInPodTask() throws Exception { // Given ArgumentCaptorwatchContextArgumentCaptor=ArgumentCaptor.forClass(WatchContext.class); dockerImageWatcher.watch(null,null,null,null); - verify(watchService).watch(watchContextArgumentCaptor.capture(),any(),any()); + verify(watchService).watch(watchContextArgumentCaptor.capture(), any()); final ExecTask execTask=watchContextArgumentCaptor.getValue().getContainerCommandExecutor(); //When execTask.exec("thecommand"); @@ -110,7 +110,7 @@ void watchCopyFileToPod() throws Exception { // Given ArgumentCaptor watchContextArgumentCaptor = ArgumentCaptor.forClass(WatchContext.class); dockerImageWatcher.watch(null,null,null,null); - verify(watchService).watch(watchContextArgumentCaptor.capture(),any(),any()); + verify(watchService).watch(watchContextArgumentCaptor.capture(), any()); final CopyFilesTask copyFilesTask = watchContextArgumentCaptor.getValue().getContainerCopyTask(); // When copyFilesTask.copy(null); diff --git a/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/goals/develop/_jkube-watch.adoc b/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/goals/develop/_jkube-watch.adoc index 6825f9a3e5..13354ceec5 100644 --- a/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/goals/develop/_jkube-watch.adoc +++ b/kubernetes-maven-plugin/doc/src/main/asciidoc/inc/goals/develop/_jkube-watch.adoc @@ -156,12 +156,6 @@ Defaults to `both`. Defaults to `5000`. | `jkube.watch.interval` -| *keepRunning* -| If set to true all containers will be kept running after {goal-prefix}:watch has been stopped. - - Defaults to `false`. -| `jkube.watch.keepRunning` - | *watchPostGoal* | A maven goal which should be called if a rebuild or a restart has been performed. @@ -177,30 +171,4 @@ Defaults to `both`. when watchMode is copy. Note that this container must be running. | `jkube.watch.postExec` - -| *keepContainer* -| If this is set to `false` (and `keepRunning` is disabled) then all containers will be removed after - they have been stopped. - - Defaults to `false`. -| `jkube.watch.keepContainer` - -| *removeVolumes* -| If set to `true` remove any volumes associated with the container as well. - - This option will be ignored if either `keepContainer` or `keepRunning` is `true`. - - Defaults to `false`. -| `jkube.watch.removeVolumes` - -| *watchShowLogs* -| If set to `true`, logs will be shown for watched container. -| `jkube.watch.showLogs` - -| *watchFollow* -| If `watchShowLogs` is set to `false`, and there is a run image configuration, logs are followed - if set to `true`. - - Defaults to `false`. -| `jkube.watch.follow` |=== diff --git a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java index b1e2a62968..200325ae2a 100644 --- a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java +++ b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/build/AbstractDockerMojo.java @@ -32,14 +32,11 @@ import org.eclipse.jkube.kit.common.RegistryConfig; import org.eclipse.jkube.kit.build.service.docker.DockerServiceHub; import org.eclipse.jkube.kit.build.service.docker.access.DockerAccess; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogDispatcher; -import org.eclipse.jkube.kit.build.service.docker.access.log.LogOutputSpecFactory; import org.eclipse.jkube.kit.build.service.docker.auth.AuthConfigFactory; import org.eclipse.jkube.kit.build.service.docker.helper.ConfigHelper; import org.eclipse.jkube.kit.build.service.docker.config.DockerMachineConfiguration; import org.eclipse.jkube.kit.config.image.WatchMode; import org.eclipse.jkube.kit.build.service.docker.config.handler.ImageConfigResolver; -import org.eclipse.jkube.kit.build.service.docker.helper.ContainerNamingUtil; import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.KitLogger; import org.eclipse.jkube.kit.common.util.AnsiLogger; @@ -317,8 +314,6 @@ public abstract class AbstractDockerMojo extends AbstractMojo protected KitLogger log; - protected LogOutputSpecFactory logOutputSpecFactory; - // Access for creating OpenShift binary builds protected ClusterAccess clusterAccess; @@ -339,46 +334,18 @@ public abstract class AbstractDockerMojo extends AbstractMojo @Parameter(property = "jkube.watch.interval", defaultValue = "5000") protected int watchInterval; - @Parameter(property = "jkube.watch.keepRunning", defaultValue = "false") - protected boolean keepRunning; - @Parameter(property = "jkube.watch.postGoal") protected String watchPostGoal; @Parameter(property = "jkube.watch.postExec") protected String watchPostExec; - // Whether to keep the containers afters stopping (start/watch/stop) - @Parameter(property = "jkube.watch.keepContainer", defaultValue = "false") - protected boolean keepContainer; - - // Whether to remove volumes when removing the container (start/watch/stop) - @Parameter(property = "jkube.watch.removeVolumes", defaultValue = "false") - protected boolean removeVolumes; - - @Parameter(property = "jkube.watch.follow", defaultValue = "false") - protected boolean watchFollow; - - @Parameter(property = "jkube.watch.showLogs") - protected String watchShowLogs; - /** - * Naming pattern for how to name containers when started - */ - @Parameter(property = "jkube.watch.containerNamePattern") - protected String containerNamePattern = ContainerNamingUtil.DEFAULT_CONTAINER_NAME_PATTERN; - /** * Namespace to use when accessing Kubernetes or OpenShift */ @Parameter(property = "jkube.namespace") protected String namespace; - /** - * Whether to create the customs networks (user-defined bridge networks) before starting automatically - */ - @Parameter(property = "jkube.watch.autoCreateCustomNetworks", defaultValue = "false") - protected boolean autoCreateCustomNetworks; - @Parameter(property = "jkube.offline", defaultValue = "false") protected boolean offline; @@ -410,7 +377,6 @@ public final void execute() throws MojoExecutionException, MojoFailureException protected void init() { log = new AnsiLogger(getLog(), useColorForLogging(), verbose, !settings.getInteractiveMode(), getLogPrefix()); - logOutputSpecFactory = new LogOutputSpecFactory(useColorForLogging(), logStdout, logDate); authConfigFactory = new AuthConfigFactory(log); imageConfigResolver.setLog(log); clusterAccess = new ClusterAccess(initClusterConfiguration()); @@ -438,7 +404,7 @@ protected void doExecute() throws MojoExecutionException { .configuration(initJKubeConfiguration()) .clusterAccess(clusterAccess) .platformMode(getConfiguredRuntimeMode()) - .dockerServiceHub(DockerServiceHub.newInstance(log, dockerAccess, logOutputSpecFactory)) + .dockerServiceHub(DockerServiceHub.newInstance(log, dockerAccess)) .buildServiceConfig(buildServiceConfigBuilder().build()) .offline(offline) .build(); @@ -683,13 +649,4 @@ protected GavLabel getGavLabel() { return new GavLabel(project.getGroupId(), project.getArtifactId(), project.getVersion()); } - protected LogDispatcher getLogDispatcher(DockerServiceHub hub) { - LogDispatcher dispatcher = (LogDispatcher) getPluginContext().get(CONTEXT_KEY_LOG_DISPATCHER); - if (dispatcher == null) { - dispatcher = new LogDispatcher(hub.getDockerAccess()); - getPluginContext().put(CONTEXT_KEY_LOG_DISPATCHER, dispatcher); - } - return dispatcher; - } - } diff --git a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/develop/WatchMojo.java b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/develop/WatchMojo.java index 5b25cb6763..3423c9c9d9 100644 --- a/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/develop/WatchMojo.java +++ b/kubernetes-maven-plugin/plugin/src/main/java/org/eclipse/jkube/maven/plugin/mojo/develop/WatchMojo.java @@ -165,19 +165,10 @@ protected WatchContext getWatchContext() throws DependencyResolutionRequiredExce .watchInterval(watchInterval) .watchMode(watchMode) .watchPostExec(watchPostExec) - .autoCreateCustomNetworks(autoCreateCustomNetworks) - .keepContainer(keepContainer) - .keepRunning(keepRunning) - .removeVolumes(removeVolumes) - .containerNamePattern(containerNamePattern) .buildTimestamp(getBuildTimestamp(getPluginContext(), CONTEXT_KEY_BUILD_TIMESTAMP, project.getBuild().getDirectory(), DOCKER_BUILD_TIMESTAMP)) .gavLabel(getGavLabel()) .buildContext(initJKubeConfiguration()) - .follow(watchFollow) - .showLogs(watchShowLogs) - .logOutputSpecFactory(logOutputSpecFactory) .hub(hub) - .dispatcher(getLogDispatcher(hub)) .postGoalTask(() -> MavenUtil.callMavenPluginWithGoal(project, session, pluginManager, watchPostGoal, log)) .build(); }