diff --git a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerConfiguration.java b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerConfiguration.java index af370ddb283..156b023b0f0 100644 --- a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerConfiguration.java +++ b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerConfiguration.java @@ -23,6 +23,7 @@ import java.util.Objects; import java.util.Optional; +import org.eclipse.kura.container.orchestration.ContainerNetworkConfiguration.ContainerNetworkConfigurationBuilder; import org.eclipse.kura.container.orchestration.ImageConfiguration.ImageConfigurationBuilder; import org.osgi.annotation.versioning.ProviderType; @@ -48,6 +49,7 @@ public class ContainerConfiguration { private Map containerLoggerParameters; private String containerLoggingType; private ImageConfiguration imageConfig; + private ContainerNetworkConfiguration networkConfiguration; private List entryPoint; private ContainerConfiguration() { @@ -201,11 +203,22 @@ public int getImageDownloadTimeoutSeconds() { return this.imageConfig.getimageDownloadTimeoutSeconds(); } + /** + * return the container's network configuration as a + * {@link ContainerNetworkConfiguration}. + * + * @return + * @since 2.4 + */ + public ContainerNetworkConfiguration getContainerNetworkConfiguration() { + return this.networkConfiguration; + } + /** * Returns a List of container entry points. An empty list can be returned if no entrypoints are specified. * * @return - * @since 2.6 + * @since 2.4 */ public List getEntryPoint() { return this.entryPoint; @@ -264,6 +277,7 @@ public static final class ContainerConfigurationBuilder { private Map containerLoggerParameters; private String containerLoggingType; private ImageConfigurationBuilder imageConfigBuilder = new ImageConfiguration.ImageConfigurationBuilder(); + private ContainerNetworkConfigurationBuilder networkConfigurationBuilder = new ContainerNetworkConfigurationBuilder(); private List entryPoint = new LinkedList<>(); public ContainerConfigurationBuilder setContainerName(String serviceName) { @@ -341,6 +355,17 @@ public ContainerConfigurationBuilder setEntryPoint(List entryPoint) { return this; } + /** + * Set the {@link NetworkConfiguration} + * + * @since 2.4 + */ + public ContainerConfigurationBuilder setContainerNetowrkConfiguration( + ContainerNetworkConfiguration networkConfiguration) { + this.networkConfigurationBuilder.setNetworkMode(networkConfiguration.getNetworkMode()); + return this; + } + /** * Set the {@link ImageConfiguration} * @@ -368,6 +393,7 @@ public ContainerConfiguration build() { result.containerLoggerParameters = this.containerLoggerParameters; result.containerLoggingType = this.containerLoggingType; result.imageConfig = this.imageConfigBuilder.build(); + result.networkConfiguration = this.networkConfigurationBuilder.build(); result.entryPoint = requireNonNull(this.entryPoint, "Container EntryPoint list must not be null"); return result; diff --git a/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerNetworkConfiguration.java b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerNetworkConfiguration.java new file mode 100644 index 00000000000..77370f40354 --- /dev/null +++ b/kura/org.eclipse.kura.api/src/main/java/org/eclipse/kura/container/orchestration/ContainerNetworkConfiguration.java @@ -0,0 +1,96 @@ +/******************************************************************************* + * Copyright (c) 2022 Eurotech and/or its affiliates and others + * + * 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: + * Eurotech + *******************************************************************************/ + +package org.eclipse.kura.container.orchestration; + +import static java.util.Objects.requireNonNull; + +import java.util.Objects; +import java.util.Optional; + +import org.osgi.annotation.versioning.ProviderType; + +/** + * Object which represents a container network configuration used to when + * requesting the generation of a new container instance. + * + * @noimplement This interface is not intended to be implemented by clients. + * @since 2.4 + * + */ +@ProviderType +public class ContainerNetworkConfiguration { + + private Optional networkMode; + + private ContainerNetworkConfiguration() { + } + + /** + * + * Returns the network mode a container will be created with (e.g. 'bridge', + * 'none', 'container:', 'host'). + * + * @return + */ + public Optional getNetworkMode() { + return this.networkMode; + } + + /** + * Creates a builder for creating a new {@link ContainerNetworkConfiguration} + * instance. + * + * @return the builder. + */ + public static ContainerNetworkConfigurationBuilder builder() { + return new ContainerNetworkConfigurationBuilder(); + } + + @Override + public int hashCode() { + return Objects.hash(this.networkMode); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ContainerNetworkConfiguration)) { + return false; + } + ContainerNetworkConfiguration other = (ContainerNetworkConfiguration) obj; + return Objects.equals(this.networkMode, other.networkMode); + } + + public static final class ContainerNetworkConfigurationBuilder { + + private Optional networkMode = Optional.empty(); + + public ContainerNetworkConfigurationBuilder setNetworkMode(Optional networkMode) { + this.networkMode = networkMode; + return this; + } + + public ContainerNetworkConfiguration build() { + ContainerNetworkConfiguration result = new ContainerNetworkConfiguration(); + + result.networkMode = requireNonNull(this.networkMode, + "Requested Container Network Mode Name cannot be null"); + + return result; + } + + } +} diff --git a/kura/org.eclipse.kura.container.orchestration.provider/src/main/java/org/eclipse/kura/container/orchestration/provider/impl/ContainerOrchestrationServiceImpl.java b/kura/org.eclipse.kura.container.orchestration.provider/src/main/java/org/eclipse/kura/container/orchestration/provider/impl/ContainerOrchestrationServiceImpl.java index 2b3f045babe..9b6f169bdfa 100644 --- a/kura/org.eclipse.kura.container.orchestration.provider/src/main/java/org/eclipse/kura/container/orchestration/provider/impl/ContainerOrchestrationServiceImpl.java +++ b/kura/org.eclipse.kura.container.orchestration.provider/src/main/java/org/eclipse/kura/container/orchestration/provider/impl/ContainerOrchestrationServiceImpl.java @@ -458,6 +458,8 @@ private String createContainer(ContainerConfiguration containerDescription) thro configuration = containerLogConfigurationHandler(containerDescription, configuration); + configuration = containerNetworkConfigurationHandler(containerDescription, configuration); + if (containerDescription.isContainerPrivileged()) { configuration = configuration.withPrivileged(containerDescription.isContainerPrivileged()); } @@ -529,6 +531,18 @@ private HostConfig containerLogConfigurationHandler(ContainerConfiguration conta return configuration; } + private HostConfig containerNetworkConfigurationHandler(ContainerConfiguration containerDescription, + HostConfig configuration) { + + if (containerDescription.getContainerNetworkConfiguration().getNetworkMode().isPresent() + && !containerDescription.getContainerNetworkConfiguration().getNetworkMode().get().trim().isEmpty()) { + configuration.withNetworkMode(containerDescription.getContainerNetworkConfiguration().getNetworkMode().get() + .toLowerCase().trim()); + } + + return configuration; + } + private HostConfig containerPortManagementHandler(ContainerConfiguration containerDescription, HostConfig commandBuilder) { diff --git a/kura/org.eclipse.kura.container.provider/OSGI-INF/metatype/org.eclipse.kura.container.provider.ContainerInstance.xml b/kura/org.eclipse.kura.container.provider/OSGI-INF/metatype/org.eclipse.kura.container.provider.ContainerInstance.xml index 8f8f24ba28f..6da5ba10c45 100644 --- a/kura/org.eclipse.kura.container.provider/OSGI-INF/metatype/org.eclipse.kura.container.provider.ContainerInstance.xml +++ b/kura/org.eclipse.kura.container.provider/OSGI-INF/metatype/org.eclipse.kura.container.provider.ContainerInstance.xml @@ -75,12 +75,12 @@ + + + REGISTRY_PASSWORD = new Property<>("registry.password", ""); private static final Property IMAGES_DOWNLOAD_TIMEOUT = new Property<>("container.image.download.timeout", 500); + private static final Property CONTAINER_NETWORKING_MODE = new Property<>("container.networkMode", ""); private static final Property CONTAINER_ENTRY_POINT = new Property<>("container.entrypoint", ""); private final boolean enabled; @@ -75,6 +77,7 @@ public class ContainerInstanceOptions { private final Optional registryUsername; private final Optional registryPassword; private final int imageDownloadTimeout; + private final Optional containerNetworkingMode; private final List containerEntryPoint; public ContainerInstanceOptions(final Map properties) { @@ -101,6 +104,7 @@ public ContainerInstanceOptions(final Map properties) { this.registryUsername = REGISTRY_USERNAME.getOptional(properties); this.registryPassword = REGISTRY_PASSWORD.getOptional(properties); this.imageDownloadTimeout = IMAGES_DOWNLOAD_TIMEOUT.get(properties); + this.containerNetworkingMode = CONTAINER_NETWORKING_MODE.getOptional(properties); this.containerEntryPoint = parseStringListSplitByComma(CONTAINER_ENTRY_POINT.get(properties)); } @@ -162,7 +166,7 @@ private List parseStringListSplitByComma(String stringToSplit) { for (String entry : stringToSplit.trim().split(",")) { if (entry.trim().length() > 0) { - stringList.add(entry.trim()); + stringList.add(entry.trim()); } } @@ -229,6 +233,10 @@ public Map getLoggerParameters() { return this.containerLoggingParameters; } + public Optional getContainerNetworkingMode() { + return this.containerNetworkingMode; + } + public Optional getRegistryCredentials() { if (this.registryUsername.isPresent() && this.registryPassword.isPresent()) { return Optional.of(new PasswordRegistryCredentials(this.registryURL, this.registryUsername.get(), @@ -242,6 +250,11 @@ public int getImageDownloadTimeout() { return this.imageDownloadTimeout; } + private ContainerNetworkConfiguration buildContainerNetworkConfig() { + return new ContainerNetworkConfiguration.ContainerNetworkConfigurationBuilder() + .setNetworkMode(getContainerNetworkingMode()).build(); + } + public List getEntryPoint() { return this.containerEntryPoint; } @@ -258,6 +271,7 @@ public ContainerConfiguration getContainerConfiguration() { .setInternalPorts(getContainerPortsInternal()).setEnvVars(getContainerEnvList()) .setVolumes(getContainerVolumeList()).setPrivilegedMode(this.privilegedMode) .setDeviceList(getContainerDeviceList()).setFrameworkManaged(true).setLoggingType(getLoggingType()) + .setContainerNetowrkConfiguration(buildContainerNetworkConfig()) .setLoggerParameters(getLoggerParameters()).setEntryPoint(getEntryPoint()).build(); } @@ -280,7 +294,8 @@ public int hashCode() { this.containerLoggingParameters, this.containerName, this.containerVolumeString, this.containerVolumes, this.enabled, this.externalPorts, this.image, this.imageDownloadTimeout, this.imageTag, this.internalPorts, this.maxDownloadRetries, this.privilegedMode, this.registryPassword, - this.registryURL, this.registryUsername, this.retryInterval, this.containerEntryPoint); + this.registryURL, this.registryUsername, this.retryInterval, this.containerEntryPoint, + this.containerNetworkingMode); } @Override @@ -307,6 +322,7 @@ public boolean equals(Object obj) { && Objects.equals(this.registryPassword, other.registryPassword) && Objects.equals(this.registryURL, other.registryURL) && Objects.equals(this.registryUsername, other.registryUsername) + && Objects.equals(this.containerNetworkingMode, other.containerNetworkingMode) && Objects.equals(this.containerEntryPoint, other.containerEntryPoint) && this.retryInterval == other.retryInterval; } diff --git a/kura/test/org.eclipse.kura.container.orchestration.provider.test/src/test/java/org/eclipse/kura/container/orchestration/provider/ContainerConfigurationTest.java b/kura/test/org.eclipse.kura.container.orchestration.provider.test/src/test/java/org/eclipse/kura/container/orchestration/provider/ContainerConfigurationTest.java index bcf5fada3aa..ed1d163c785 100644 --- a/kura/test/org.eclipse.kura.container.orchestration.provider.test/src/test/java/org/eclipse/kura/container/orchestration/provider/ContainerConfigurationTest.java +++ b/kura/test/org.eclipse.kura.container.orchestration.provider.test/src/test/java/org/eclipse/kura/container/orchestration/provider/ContainerConfigurationTest.java @@ -26,6 +26,7 @@ import org.eclipse.kura.configuration.Password; import org.eclipse.kura.container.orchestration.ContainerConfiguration; import org.eclipse.kura.container.orchestration.ContainerConfiguration.ContainerConfigurationBuilder; +import org.eclipse.kura.container.orchestration.ContainerNetworkConfiguration; import org.eclipse.kura.container.orchestration.ImageConfiguration; import org.eclipse.kura.container.orchestration.PasswordRegistryCredentials; import org.junit.Test; @@ -132,7 +133,9 @@ REGISTRY_USERNAME, new Password(REGISTRY_PASSWORD)))) .setInternalPorts(CONTAINER_PORTS_INTERNAL).setEnvVars(CONTAINER_ENV_VARS) .setDeviceList(CONTAINER_DEVICE_LIST).setVolumes(CONTAINER_VOLUMES).setPrivilegedMode(false) .setFrameworkManaged(false).setLoggerParameters(CONTAINER_LOGGER_PARAMETERS) - .setLoggingType(CONTAINER_LOGGER_TYPE); + .setLoggingType(CONTAINER_LOGGER_TYPE).setContainerNetowrkConfiguration( + new ContainerNetworkConfiguration.ContainerNetworkConfigurationBuilder() + .setNetworkMode(Optional.of("bridge")).build()); } private void givenContainerOne() { diff --git a/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceOptionsTest.java b/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceOptionsTest.java index 11e4fa77ac1..6ffcab4347e 100644 --- a/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceOptionsTest.java +++ b/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceOptionsTest.java @@ -51,6 +51,7 @@ public class ContainerInstanceOptionsTest { private static final String DEFAULT_REGISTRY_USERNAME = ""; private static final String DEFAULT_REGISTRY_PASSWORD = ""; private static final int DEFAULT_IMAGES_DOWNLOAD_TIMEOUT = 500; + private static final String DEFAULT_CONTAINER_NETWORKING_MODE = ""; private static final String DEFAULT_CONTAINER_ENTRY_POINT = ""; private static final String CONTAINER_ENV = "container.env"; @@ -71,6 +72,7 @@ public class ContainerInstanceOptionsTest { private static final String REGISTRY_USERNAME = "registry.username"; private static final String REGISTRY_PASSWORD = "registry.password"; private static final String IMAGES_DOWNLOAD_TIMEOUT = "container.image.download.timeout"; + private static final String CONTAINER_NETWORKING_MODE = "container.networkMode"; private static final String CONTAINER_ENTRY_POINT = "container.entrypoint"; private Map properties; @@ -650,6 +652,7 @@ private void givenDefaultProperties() { this.properties.put(REGISTRY_USERNAME, DEFAULT_REGISTRY_USERNAME); this.properties.put(REGISTRY_PASSWORD, DEFAULT_REGISTRY_PASSWORD); this.properties.put(IMAGES_DOWNLOAD_TIMEOUT, DEFAULT_IMAGES_DOWNLOAD_TIMEOUT); + this.properties.put(CONTAINER_NETWORKING_MODE, DEFAULT_CONTAINER_NETWORKING_MODE); this.properties.put(CONTAINER_ENTRY_POINT, DEFAULT_CONTAINER_ENTRY_POINT); } @@ -671,6 +674,7 @@ private void givenDifferentProperties() { this.newProperties.put(REGISTRY_USERNAME, "test"); this.newProperties.put(REGISTRY_PASSWORD, "test"); this.newProperties.put(IMAGES_DOWNLOAD_TIMEOUT, 100); + this.newProperties.put(CONTAINER_NETWORKING_MODE, "none"); this.newProperties.put(CONTAINER_ENTRY_POINT, "./test.py,-v,-m,--human-readable,,,"); } diff --git a/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceTest.java b/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceTest.java index ab5a32b2c7b..4a4c1168ccc 100644 --- a/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceTest.java +++ b/kura/test/org.eclipse.kura.container.provider.test/src/test/java/org/eclipse/kura/container/provider/ContainerInstanceTest.java @@ -48,6 +48,7 @@ public class ContainerInstanceTest { private static final String CONTAINER_DEVICE = "container.Device"; private static final String CONTAINER_LOGGER_PARAMETERS = "container.loggerParameters"; private static final String CONTAINER_LOGGING_TYPE = "container.loggingType"; + private static final String CONTAINER_NETWORKING_MODE = "container.networkMode"; private ContainerOrchestrationService dockerService; private Map properties; @@ -199,6 +200,7 @@ private void givenFullProperties(boolean enabled) { this.properties.put(CONTAINER_DEVICE, ""); this.properties.put(CONTAINER_LOGGER_PARAMETERS, ""); this.properties.put(CONTAINER_LOGGING_TYPE, "default"); + this.properties.put(CONTAINER_NETWORKING_MODE, ""); } private void givenConfigurableGenericDockerService() {