forked from eclipse-jkube/jkube
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor (jkube-kit/build) : Move buildArgs related logic to a new cl…
…ass BuildArgResolverUtil Related to eclipse-jkube#2904 It's better to move code for resolving build args from different sources to a dedicated class. It doesn't look like BuildService is the right place for this. This way we can also use it from other BuildServices of other build strategies. Signed-off-by: Rohan Kumar <[email protected]>
- Loading branch information
1 parent
dbd1067
commit e4b5075
Showing
6 changed files
with
354 additions
and
197 deletions.
There are no files selected for viewing
102 changes: 102 additions & 0 deletions
102
.../build/api/src/main/java/org/eclipse/jkube/kit/build/api/helper/BuildArgResolverUtil.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,102 @@ | ||
/* | ||
* 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.helper; | ||
|
||
import org.apache.commons.lang3.StringUtils; | ||
import org.eclipse.jkube.kit.common.JKubeConfiguration; | ||
import org.eclipse.jkube.kit.config.image.ImageConfiguration; | ||
|
||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Optional; | ||
import java.util.Properties; | ||
|
||
import static org.eclipse.jkube.kit.common.util.MapUtil.mergeMapsImmutable; | ||
|
||
public class BuildArgResolverUtil { | ||
private static final String ARG_PREFIX = "docker.buildArg."; | ||
|
||
private BuildArgResolverUtil() { } | ||
|
||
/** | ||
* Merges Docker Build Args in the following order (in decreasing order of precedence): | ||
* <ul> | ||
* <li>Build Args specified directly in ImageConfiguration</li> | ||
* <li>Build Args specified via System Properties</li> | ||
* <li>Build Args specified via Project Properties</li> | ||
* <li>Build Args specified via Plugin configuration</li> | ||
* <li>Docker Proxy Build Args detected from ~/.docker/config.json</li> | ||
* </ul> | ||
* @param imageConfig ImageConfiguration for which Build Args would be resolved | ||
* @param configuration {@link JKubeConfiguration} JKubeConfiguration | ||
* @return a Map containing merged Build Args from all sources. | ||
*/ | ||
public static Map<String, String> mergeBuildArgs(ImageConfiguration imageConfig, JKubeConfiguration configuration) { | ||
Map<String, String> buildArgsFromProjectProperties = addBuildArgsFromProperties(configuration.getProject().getProperties()); | ||
Map<String, String> buildArgsFromSystemProperties = addBuildArgsFromProperties(System.getProperties()); | ||
Map<String, String> buildArgsFromDockerConfig = addBuildArgsFromDockerConfig(); | ||
|
||
return mergeMapsImmutable(imageConfig.getBuild().getArgs(), | ||
buildArgsFromSystemProperties, | ||
buildArgsFromProjectProperties, | ||
Optional.ofNullable(configuration.getBuildArgs()).orElse(Collections.emptyMap()), | ||
buildArgsFromDockerConfig); | ||
} | ||
|
||
private static Map<String, String> addBuildArgsFromProperties(Properties properties) { | ||
Map<String, String> buildArgs = new HashMap<>(); | ||
for (Object keyObj : properties.keySet()) { | ||
String key = (String) keyObj; | ||
if (key.startsWith(ARG_PREFIX)) { | ||
String argKey = key.replaceFirst(ARG_PREFIX, ""); | ||
String value = properties.getProperty(key); | ||
|
||
if (StringUtils.isNotBlank(value)) { | ||
buildArgs.put(argKey, value); | ||
} | ||
} | ||
} | ||
return buildArgs; | ||
} | ||
|
||
private static Map<String, String> addBuildArgsFromDockerConfig() { | ||
final Map<String, Object> dockerConfig = DockerFileUtil.readDockerConfig(); | ||
if (dockerConfig == null) { | ||
return Collections.emptyMap(); | ||
} | ||
|
||
// add proxies | ||
Map<String, String> buildArgs = new HashMap<>(); | ||
if (dockerConfig.containsKey("proxies")) { | ||
final Map<String, Object> proxies = (Map<String, Object>) dockerConfig.get("proxies"); | ||
if (proxies.containsKey("default")) { | ||
final Map<String, String> defaultProxyObj = (Map<String, String>) proxies.get("default"); | ||
String[] proxyMapping = new String[] { | ||
"httpProxy", "http_proxy", | ||
"httpsProxy", "https_proxy", | ||
"noProxy", "no_proxy", | ||
"ftpProxy", "ftp_proxy" | ||
}; | ||
|
||
for(int index = 0; index < proxyMapping.length; index += 2) { | ||
if (defaultProxyObj.containsKey(proxyMapping[index])) { | ||
buildArgs.put(ARG_PREFIX + proxyMapping[index+1], defaultProxyObj.get(proxyMapping[index])); | ||
} | ||
} | ||
} | ||
} | ||
return buildArgs; | ||
} | ||
} |
188 changes: 188 additions & 0 deletions
188
...t/java/org/eclipse/jkube/kit/build/api/helper/BuildArgResolverUtilMergeBuildArgsTest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,188 @@ | ||
/* | ||
* 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.helper; | ||
|
||
import org.eclipse.jkube.kit.common.JKubeConfiguration; | ||
import org.eclipse.jkube.kit.common.JavaProject; | ||
import org.eclipse.jkube.kit.common.util.EnvUtil; | ||
import org.eclipse.jkube.kit.config.image.ImageConfiguration; | ||
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.DisplayName; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.nio.file.Path; | ||
import java.util.Collections; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Properties; | ||
|
||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; | ||
|
||
class BuildArgResolverUtilMergeBuildArgsTest { | ||
private ImageConfiguration imageConfiguration; | ||
private JKubeConfiguration jKubeConfiguration; | ||
private Properties projectProperties; | ||
private Map<String, String> buildArgFromPluginConfiguration; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
projectProperties = new Properties(); | ||
buildArgFromPluginConfiguration = new HashMap<>(); | ||
jKubeConfiguration = JKubeConfiguration.builder() | ||
.project(JavaProject.builder() | ||
.properties(projectProperties) | ||
.build()) | ||
.buildArgs(buildArgFromPluginConfiguration) | ||
.build(); | ||
imageConfiguration = ImageConfiguration.builder() | ||
.name("image-name") | ||
.build(BuildConfiguration.builder() | ||
.build()) | ||
.build(); | ||
} | ||
|
||
@Test | ||
@DisplayName("build args in image config and project properties") | ||
void whenBuildArgsFromImageConfigAndFromProjectProperties_shouldMergeBuildArgs() { | ||
// Given | ||
projectProperties.setProperty("docker.buildArg.VERSION", "latest"); | ||
projectProperties.setProperty("docker.buildArg.FULL_IMAGE", "busybox:latest"); | ||
Map<String, String> buildArgImageConfiguration = new HashMap<>(); | ||
buildArgImageConfiguration.put("REPO_1", "docker.io/library"); | ||
buildArgImageConfiguration.put("IMAGE-1", "openjdk"); | ||
imageConfiguration = imageConfiguration.toBuilder() | ||
.build(imageConfiguration.getBuild().toBuilder().args(buildArgImageConfiguration).build()) | ||
.build(); | ||
|
||
// When | ||
Map<String, String> mergedBuildArgs = BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration); | ||
|
||
// Then | ||
assertThat(mergedBuildArgs) | ||
.containsEntry("VERSION", "latest") | ||
.containsEntry("FULL_IMAGE", "busybox:latest") | ||
.containsEntry("REPO_1", "docker.io/library") | ||
.containsEntry("IMAGE-1", "openjdk"); | ||
} | ||
|
||
@Test | ||
@DisplayName("build args in image config, project properties, system properties, plugin configuration") | ||
void fromAllSourcesWithDifferentKeys_shouldMergeBuildArgs() { | ||
// Given | ||
givenBuildArgsFromImageConfiguration("VERSION", "latest"); | ||
System.setProperty("docker.buildArg.IMAGE-1", "openjdk"); | ||
projectProperties.setProperty("docker.buildArg.REPO_1", "docker.io/library"); | ||
givenBuildArgsFromJKubeConfiguration("FULL_IMAGE", "busybox:latest"); | ||
|
||
// When | ||
Map<String, String> mergedBuildArgs = BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration); | ||
|
||
// Then | ||
assertThat(mergedBuildArgs) | ||
.containsEntry("VERSION", "latest") | ||
.containsEntry("FULL_IMAGE", "busybox:latest") | ||
.containsEntry("REPO_1", "docker.io/library") | ||
.containsEntry("IMAGE-1", "openjdk"); | ||
} | ||
|
||
@Test | ||
@DisplayName("build args in image config and system properties with same key, should throw exception") | ||
void fromBuildConfigurationAndSystemPropertiesWithSameKey_shouldNotMergeBuildArgs() { | ||
// Given | ||
givenBuildArgsFromImageConfiguration("VERSION", "latest"); | ||
System.setProperty("docker.buildArg.VERSION", "1.0.0"); | ||
|
||
// When & Then | ||
assertThatIllegalArgumentException() | ||
.isThrownBy(() -> BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration)) | ||
.withMessage("Multiple entries with same key: VERSION=latest and VERSION=1.0.0"); | ||
} | ||
|
||
@Test | ||
@DisplayName("build args in image config and project properties with same key, should throw exception") | ||
void fromBuildConfigurationAndProjectPropertiesWithSameKey_shouldNotMergeBuildArgs() { | ||
// Given | ||
givenBuildArgsFromImageConfiguration("VERSION", "latest"); | ||
projectProperties.setProperty("docker.buildArg.VERSION", "1.0.0"); | ||
|
||
// When & Then | ||
assertThatIllegalArgumentException() | ||
.isThrownBy(() -> BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration)) | ||
.withMessage("Multiple entries with same key: VERSION=latest and VERSION=1.0.0"); | ||
} | ||
|
||
@Test | ||
@DisplayName("build args in image config and plugin config with same key, should throw exception") | ||
void fromBuildConfigurationAndJKubeConfigurationWithSameKey_shouldNotMergeBuildArgs() { | ||
// Given | ||
givenBuildArgsFromImageConfiguration("VERSION", "latest"); | ||
givenBuildArgsFromJKubeConfiguration("VERSION", "1.0.0"); | ||
|
||
// When & Then | ||
assertThatIllegalArgumentException() | ||
.isThrownBy(() -> BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration)) | ||
.withMessage("Multiple entries with same key: VERSION=latest and VERSION=1.0.0"); | ||
} | ||
|
||
@Test | ||
@DisplayName("should add proxy build args from ~/.docker/config.json") | ||
void shouldAddBuildArgsFromDockerConfig(@TempDir File temporaryFolder) throws IOException { | ||
try { | ||
// Given | ||
Path dockerConfig = temporaryFolder.toPath(); | ||
final Map<String, String> env = Collections.singletonMap("DOCKER_CONFIG", dockerConfig.toFile().getAbsolutePath()); | ||
EnvUtil.overrideEnvGetter(env::get); | ||
Files.write(dockerConfig.resolve("config.json"), ("{\"proxies\": {\"default\": {\n" + | ||
" \"httpProxy\": \"http://proxy.example.com:3128\",\n" + | ||
" \"httpsProxy\": \"https://proxy.example.com:3129\",\n" + | ||
" \"noProxy\": \"*.test.example.com,.example.org,127.0.0.0/8\"\n" + | ||
" }}}").getBytes()); | ||
// When | ||
final Map<String, String> mergedBuildArgs = BuildArgResolverUtil.mergeBuildArgs(imageConfiguration, jKubeConfiguration); | ||
// Then | ||
assertThat(mergedBuildArgs) | ||
.containsEntry("docker.buildArg.http_proxy", "http://proxy.example.com:3128") | ||
.containsEntry("docker.buildArg.https_proxy", "https://proxy.example.com:3129") | ||
.containsEntry("docker.buildArg.no_proxy", "*.test.example.com,.example.org,127.0.0.0/8"); | ||
} finally { | ||
EnvUtil.overrideEnvGetter(System::getenv); | ||
} | ||
} | ||
|
||
private void givenBuildArgsFromImageConfiguration(String key, String value) { | ||
imageConfiguration = imageConfiguration.toBuilder() | ||
.build(BuildConfiguration.builder() | ||
.args( | ||
Collections.singletonMap(key, value)) | ||
.build()) | ||
.build(); | ||
} | ||
|
||
private void givenBuildArgsFromJKubeConfiguration(String key, String value) { | ||
buildArgFromPluginConfiguration.put(key, value); | ||
} | ||
|
||
@AfterEach | ||
void clearSystemPropertiesUsedInTests() { | ||
System.clearProperty("docker.buildArg.IMAGE-1"); | ||
System.clearProperty("docker.buildArg.VERSION"); | ||
} | ||
} |
Oops, something went wrong.