-
Notifications
You must be signed in to change notification settings - Fork 527
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat (jkube-kit/config/service) : Add BuildPackBuildService (#2493)
+ Add new enum for buildpacks in JKubeBuildStrategy + Add BuildPackBuildService that would be activated when build strategy is set to buildpacks Signed-off-by: Rohan Kumar <[email protected]>
- Loading branch information
1 parent
ed628ab
commit 96fc976
Showing
7 changed files
with
303 additions
and
1 deletion.
There are no files selected for viewing
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
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
115 changes: 115 additions & 0 deletions
115
.../src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/BuildPackBuildService.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,115 @@ | ||
/* | ||
* 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.service.kubernetes; | ||
|
||
import java.io.File; | ||
import java.net.MalformedURLException; | ||
import java.util.Objects; | ||
import java.util.Properties; | ||
|
||
import org.eclipse.jkube.kit.common.KitLogger; | ||
import org.eclipse.jkube.kit.common.RegistryConfig; | ||
import org.eclipse.jkube.kit.common.util.EnvUtil; | ||
import org.eclipse.jkube.kit.common.util.PropertiesUtil; | ||
import org.eclipse.jkube.kit.config.image.ImageConfiguration; | ||
import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; | ||
import org.eclipse.jkube.kit.config.service.AbstractImageBuildService; | ||
import org.eclipse.jkube.kit.config.service.BuildServiceConfig; | ||
import org.eclipse.jkube.kit.config.service.JKubeServiceException; | ||
import org.eclipse.jkube.kit.config.service.JKubeServiceHub; | ||
import org.eclipse.jkube.kit.service.buildpacks.BuildPackBuildOptions; | ||
import org.eclipse.jkube.kit.service.buildpacks.controller.BuildPackCliController; | ||
|
||
import static org.apache.commons.lang3.StringUtils.strip; | ||
import static org.eclipse.jkube.kit.common.util.EnvUtil.findBinaryFileInUserPath; | ||
|
||
public class BuildPackBuildService extends AbstractImageBuildService { | ||
private static final String DEFAULT_BUILDER_IMAGE = "paketobuildpacks/builder:base"; | ||
private static final String PACK_CONFIG_DIR = ".pack"; | ||
private static final String PACK_CONFIG_FILE = "config.toml"; | ||
|
||
private final BuildServiceConfig buildServiceConfig; | ||
private final KitLogger kitLogger; | ||
|
||
public BuildPackBuildService(JKubeServiceHub jKubeServiceHub) { | ||
super(jKubeServiceHub); | ||
this.buildServiceConfig = Objects.requireNonNull(jKubeServiceHub.getBuildServiceConfig(), | ||
"BuildServiceConfig is required"); | ||
this.kitLogger = Objects.requireNonNull(jKubeServiceHub.getLog()); | ||
} | ||
|
||
@Override | ||
protected void buildSingleImage(ImageConfiguration imageConfiguration) { | ||
kitLogger.info("Delegating container image building process to BuildPacks"); | ||
doBuildPackBuild(imageConfiguration); | ||
} | ||
|
||
private void doBuildPackBuild(ImageConfiguration imageConfiguration) { | ||
Properties packProperties = PropertiesUtil.getPropertiesFromResource(BuildPackBuildService.class.getResource("/META-INF/jkube/pack-cli.properties")); | ||
File packCli = getLocalPackCLI(packProperties); | ||
kitLogger.info("Using pack %s", packCli.getAbsolutePath()); | ||
BuildPackCliController packCliController = new BuildPackCliController(packCli, kitLogger); | ||
BuildPackBuildOptions buildOptions = createBuildPackOptions(imageConfiguration); | ||
packCliController.build(buildOptions); | ||
} | ||
|
||
private File getLocalPackCLI(Properties packProperties) { | ||
kitLogger.info("Checking for local pack CLI"); | ||
String applicableBinaryProperty = String.format("%s.binary-name", EnvUtil.isWindows() ? "windows" : "unix"); | ||
String platformBinaryName = (String) packProperties.get(applicableBinaryProperty); | ||
File pack = findBinaryFileInUserPath(platformBinaryName); | ||
if (pack == null) { | ||
throw new IllegalStateException("No local pack binary found"); | ||
} | ||
return pack; | ||
} | ||
|
||
private BuildPackBuildOptions createBuildPackOptions(ImageConfiguration imageConfiguration) { | ||
Properties packConfigProperties = readLocalPackConfig(); | ||
String builderImage = strip(packConfigProperties.getProperty("default-builder-image", DEFAULT_BUILDER_IMAGE), "\""); | ||
BuildPackBuildOptions.BuildPackBuildOptionsBuilder buildOptionsBuilder = BuildPackBuildOptions.builder(); | ||
buildOptionsBuilder.imageName(imageConfiguration.getName()); | ||
buildOptionsBuilder.builderImage(builderImage); | ||
buildOptionsBuilder.creationTime("now"); | ||
return buildOptionsBuilder.build(); | ||
} | ||
|
||
private Properties readLocalPackConfig() { | ||
File packConfigDir = new File(EnvUtil.getUserHome(), PACK_CONFIG_DIR); | ||
if (packConfigDir.exists() && packConfigDir.isDirectory()) { | ||
File packConfig = new File(packConfigDir, PACK_CONFIG_FILE); | ||
try { | ||
return PropertiesUtil.getPropertiesFromResource(packConfig.toURI().toURL()); | ||
} catch (MalformedURLException e) { | ||
kitLogger.warn("Failure in reading pack local configuration : " + e.getMessage()); | ||
} | ||
} | ||
return new Properties(); | ||
} | ||
|
||
@Override | ||
protected void pushSingleImage(ImageConfiguration imageConfiguration, int retries, RegistryConfig registryConfig, boolean skipTag) throws JKubeServiceException { | ||
} | ||
|
||
@Override | ||
public boolean isApplicable() { | ||
return buildServiceConfig.getJKubeBuildStrategy() != null && | ||
buildServiceConfig.getJKubeBuildStrategy().equals(JKubeBuildStrategy.buildpacks); | ||
} | ||
|
||
@Override | ||
public void postProcess() { | ||
// NOOP | ||
} | ||
} |
1 change: 1 addition & 0 deletions
1
jkube-kit/config/service/src/main/resources/META-INF/jkube/build-service
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 |
---|---|---|
@@ -1,3 +1,4 @@ | ||
org.eclipse.jkube.kit.config.service.kubernetes.JibBuildService,100 | ||
org.eclipse.jkube.kit.config.service.kubernetes.BuildPackBuildService,110 | ||
org.eclipse.jkube.kit.config.service.openshift.OpenshiftBuildService,200 | ||
org.eclipse.jkube.kit.config.service.kubernetes.DockerBuildService,9999 |
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
169 changes: 169 additions & 0 deletions
169
.../test/java/org/eclipse/jkube/kit/config/service/kubernetes/BuildPackBuildServiceTest.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,169 @@ | ||
/* | ||
* 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.service.kubernetes; | ||
|
||
import org.eclipse.jkube.kit.common.KitLogger; | ||
import org.eclipse.jkube.kit.common.util.EnvUtil; | ||
import org.eclipse.jkube.kit.common.util.PropertiesUtil; | ||
import org.eclipse.jkube.kit.config.image.ImageConfiguration; | ||
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; | ||
import org.eclipse.jkube.kit.config.image.build.JKubeBuildStrategy; | ||
import org.eclipse.jkube.kit.config.service.JKubeServiceHub; | ||
|
||
import org.junit.jupiter.api.AfterEach; | ||
import org.junit.jupiter.api.BeforeEach; | ||
import org.junit.jupiter.api.Test; | ||
import org.junit.jupiter.api.io.TempDir; | ||
import org.junit.jupiter.params.ParameterizedTest; | ||
import org.junit.jupiter.params.provider.CsvSource; | ||
import org.mockito.MockedStatic; | ||
|
||
import java.io.File; | ||
import java.io.IOException; | ||
import java.nio.file.Files; | ||
import java.util.HashMap; | ||
import java.util.Map; | ||
import java.util.Objects; | ||
import java.util.Properties; | ||
|
||
import static java.nio.file.StandardCopyOption.COPY_ATTRIBUTES; | ||
import static org.assertj.core.api.Assertions.assertThat; | ||
import static org.mockito.ArgumentMatchers.any; | ||
import static org.mockito.Mockito.RETURNS_DEEP_STUBS; | ||
import static org.mockito.Mockito.mock; | ||
import static org.mockito.Mockito.mockStatic; | ||
import static org.mockito.Mockito.spy; | ||
import static org.mockito.Mockito.verify; | ||
import static org.mockito.Mockito.when; | ||
|
||
class BuildPackBuildServiceTest { | ||
private KitLogger kitLogger; | ||
private JKubeServiceHub mockedServiceHub; | ||
private static final String TEST_PACK_VERSION = "v0.32.1"; | ||
private String applicablePackBinary; | ||
private ImageConfiguration imageConfiguration; | ||
private MockedStatic<PropertiesUtil> propertiesUtilMockedStatic; | ||
|
||
@TempDir | ||
private File temporaryFolder; | ||
|
||
@BeforeEach | ||
void setUp() { | ||
mockedServiceHub = mock(JKubeServiceHub.class, RETURNS_DEEP_STUBS); | ||
kitLogger = spy(new KitLogger.SilentLogger()); | ||
when(mockedServiceHub.getLog()).thenReturn(kitLogger); | ||
imageConfiguration = ImageConfiguration.builder() | ||
.name("foo/bar:latest") | ||
.build(BuildConfiguration.builder() | ||
.from("foo/base:latest") | ||
.build()) | ||
.build(); | ||
applicablePackBinary = EnvUtil.isWindows() ? "pack.bat" : "pack"; | ||
Map<String, String> properties = new HashMap<>(); | ||
properties.put("user.home", temporaryFolder.getAbsolutePath()); | ||
properties.put("os.name", System.getProperty("os.name")); | ||
properties.put("os.arch", System.getProperty("os.arch")); | ||
Map<String, String> env = new HashMap<>(); | ||
env.put("HOME", temporaryFolder.getAbsolutePath()); | ||
env.put("PATH", temporaryFolder.toPath().resolve("bin").toFile().getAbsolutePath()); | ||
EnvUtil.overrideEnvGetter(env::get); | ||
EnvUtil.overridePropertyGetter(properties::get); | ||
propertiesUtilMockedStatic = mockStatic(PropertiesUtil.class); | ||
} | ||
|
||
@AfterEach | ||
void tearDown() { | ||
EnvUtil.overrideEnvGetter(System::getenv); | ||
EnvUtil.overridePropertyGetter(System::getProperty); | ||
propertiesUtilMockedStatic.close(); | ||
} | ||
|
||
@Test | ||
void isApplicable_withNoBuildStrategy_shouldReturnFalse() { | ||
// When | ||
final boolean result = new BuildPackBuildService(mockedServiceHub).isApplicable(); | ||
// Then | ||
assertThat(result).isFalse(); | ||
} | ||
|
||
@ParameterizedTest | ||
@CsvSource({ | ||
"s2i,false", "jib,false", "docker,false", "buildpacks,true" | ||
}) | ||
void isApplicable_withGivenStrategy_shouldReturnTrueOnlyForBuildPackStrategy(String buildStrategyValue, boolean expectedResult) { | ||
// Given | ||
when(mockedServiceHub.getBuildServiceConfig().getJKubeBuildStrategy()).thenReturn(JKubeBuildStrategy.valueOf(buildStrategyValue)); | ||
// When | ||
final boolean result = new BuildPackBuildService(mockedServiceHub).isApplicable(); | ||
// Then | ||
assertThat(result).isEqualTo(expectedResult); | ||
} | ||
|
||
|
||
@Test | ||
void buildImage_whenLocalPackCLIAndPackConfigHasDefaultBuilderSet_thenUseThatBuilder() throws IOException { | ||
// Given | ||
givenPackConfigHasDefaultBuilder(temporaryFolder); | ||
propertiesUtilMockedStatic.when(() -> PropertiesUtil.getPropertiesFromResource(any())) | ||
.thenReturn(createPackProperties("http://localhost.idontexist")) | ||
.thenCallRealMethod(); | ||
givenPackCliPresentOnUserMachine(String.format("/%s", applicablePackBinary)); | ||
|
||
// When | ||
new BuildPackBuildService(mockedServiceHub).buildSingleImage(imageConfiguration); | ||
|
||
// Then | ||
verify(kitLogger).info("[[s]]%s","build foo/bar:latest --builder cnbs/sample-builder:bionic --creation-time now"); | ||
} | ||
|
||
@Test | ||
void buildImage_whenLocalPackCLIAndNoDefaultBuilderInPackConfig_thenUseOpinionatedBuilderImage() throws IOException { | ||
propertiesUtilMockedStatic.when(() -> PropertiesUtil.getPropertiesFromResource(any())) | ||
.thenReturn(createPackProperties("http://localhost.idontexist")); | ||
givenPackCliPresentOnUserMachine(String.format("/%s", applicablePackBinary)); | ||
|
||
// When | ||
new BuildPackBuildService(mockedServiceHub).buildSingleImage(imageConfiguration); | ||
|
||
// Then | ||
verify(kitLogger).info("[[s]]%s", "build foo/bar:latest --builder paketobuildpacks/builder:base --creation-time now"); | ||
} | ||
|
||
private void givenPackCliPresentOnUserMachine(String packResource) throws IOException { | ||
File bin = new File(temporaryFolder, "bin"); | ||
File pack = new File(Objects.requireNonNull(getClass().getResource(packResource)).getFile()); | ||
Files.createDirectory(bin.toPath()); | ||
Files.copy(pack.toPath(), bin.toPath().resolve(pack.getName()), COPY_ATTRIBUTES); | ||
} | ||
|
||
private Properties createPackProperties(String baseUrl) { | ||
Properties properties = new Properties(); | ||
properties.put("unix.binary-name", applicablePackBinary); | ||
properties.put("windows.binary-name", applicablePackBinary); | ||
properties.put("version", TEST_PACK_VERSION); | ||
properties.put("linux.artifact", baseUrl + "pack-" + TEST_PACK_VERSION + "-linux.tgz"); | ||
properties.put("linux-arm64.artifact", baseUrl + "pack-" + TEST_PACK_VERSION + "-linux-arm64.tgz"); | ||
properties.put("macos.artifact", baseUrl + "pack-" + TEST_PACK_VERSION + "-macos.tgz"); | ||
properties.put("macos-arm64.artifact", baseUrl + "pack-" + TEST_PACK_VERSION + "-macos-arm64.tgz"); | ||
properties.put("windows.artifact", baseUrl + "pack-" + TEST_PACK_VERSION + "-windows.zip"); | ||
return properties; | ||
} | ||
|
||
private void givenPackConfigHasDefaultBuilder(File userHome) throws IOException { | ||
File packHome = new File(userHome, ".pack"); | ||
Files.createDirectory(packHome.toPath()); | ||
File packConfig = new File(packHome, "config.toml"); | ||
Files.write(packConfig.toPath(), String.format("default-builder-image=\"%s\"", "cnbs/sample-builder:bionic").getBytes()); | ||
} | ||
} |
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