diff --git a/jkube-kit/build/service/buildpacks/pom.xml b/jkube-kit/build/service/buildpacks/pom.xml
index aaaa882d12..6bf5c3b47b 100644
--- a/jkube-kit/build/service/buildpacks/pom.xml
+++ b/jkube-kit/build/service/buildpacks/pom.xml
@@ -33,6 +33,10 @@
org.eclipse.jkube
jkube-kit-build-api
+
+ org.projectlombok
+ lombok
+
org.eclipse.jkube
jkube-kit-common
@@ -52,6 +56,10 @@
org.assertj
assertj-core
+
+ org.apache.commons
+ commons-lang3
+
diff --git a/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackBuildOptions.java b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackBuildOptions.java
new file mode 100644
index 0000000000..d2aece9da6
--- /dev/null
+++ b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackBuildOptions.java
@@ -0,0 +1,33 @@
+/*
+ * 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.service.buildpacks;
+
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+@Builder(toBuilder = true)
+@AllArgsConstructor
+@NoArgsConstructor
+@Getter
+@Setter
+@EqualsAndHashCode
+public class BuildPackBuildOptions {
+ private String builderImage;
+ private String imageName;
+ private String creationTime;
+}
\ No newline at end of file
diff --git a/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackCliController.java b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackCliController.java
new file mode 100644
index 0000000000..5a174db09b
--- /dev/null
+++ b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackCliController.java
@@ -0,0 +1,83 @@
+/*
+ * 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.service.buildpacks.controller;
+
+import org.apache.commons.lang3.StringUtils;
+import org.eclipse.jkube.kit.common.KitLogger;
+import org.eclipse.jkube.kit.service.buildpacks.BuildPackBuildOptions;
+import org.eclipse.jkube.kit.service.buildpacks.BuildPackCommand;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Consumer;
+
+public class BuildPackCliController implements BuildPackController {
+ private final File pack;
+ private final KitLogger kitLogger;
+
+ public BuildPackCliController(File binaryFile, KitLogger kitLogger) {
+ this.pack = binaryFile;
+ this.kitLogger = kitLogger;
+ }
+
+ @Override
+ public void build(BuildPackBuildOptions buildOptions) {
+ BuildPackCommand buildPackCommand = new BuildPackCommand(kitLogger, pack,
+ createBuildCommandArguments(buildOptions),
+ l -> kitLogger.info("[[s]]%s", l));
+ executePackCommand(buildPackCommand, e -> {
+ throw new IllegalStateException("Process Existed With : " + buildPackCommand.getExitCode() + " [" + e.getMessage() + "]", e);
+ });
+ }
+
+ public String version() {
+ AtomicReference versionRef = new AtomicReference<>();
+ BuildPackCommand versionCommand = new BuildPackCommand(kitLogger, pack, Collections.singletonList("--version"), versionRef::set);
+ executePackCommand(versionCommand, e -> kitLogger.warn(e.getMessage()));
+ if (StringUtils.isNotBlank(versionRef.get())) {
+ return versionRef.get();
+ }
+ return null;
+ }
+
+ private List createBuildCommandArguments(BuildPackBuildOptions buildOptions) {
+ List buildArgs = new ArrayList<>();
+ buildArgs.add("build");
+ buildArgs.add(buildOptions.getImageName());
+ buildArgs.addAll(extractStringArg("--builder", buildOptions.getBuilderImage()));
+ buildArgs.addAll(extractStringArg("--creation-time", buildOptions.getCreationTime()));
+ return buildArgs;
+ }
+
+ private List extractStringArg(String flag, String flagValue) {
+ List args = new ArrayList<>();
+ if (StringUtils.isNotBlank(flagValue)) {
+ args.add(flag);
+ args.add(flagValue);
+ }
+ return args;
+ }
+
+ private void executePackCommand(BuildPackCommand buildPackCommand, Consumer exceptionConsumer) {
+ try {
+ buildPackCommand.execute();
+ } catch (IOException e) {
+ exceptionConsumer.accept(e);
+ }
+ }
+}
diff --git a/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackController.java b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackController.java
new file mode 100644
index 0000000000..3b2d3e8fad
--- /dev/null
+++ b/jkube-kit/build/service/buildpacks/src/main/java/org/eclipse/jkube/kit/service/buildpacks/controller/BuildPackController.java
@@ -0,0 +1,20 @@
+/*
+ * 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.service.buildpacks.controller;
+
+import org.eclipse.jkube.kit.service.buildpacks.BuildPackBuildOptions;
+
+public interface BuildPackController {
+ void build(BuildPackBuildOptions buildOptions);
+}
diff --git a/jkube-kit/build/service/buildpacks/src/test/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackCliControllerTest.java b/jkube-kit/build/service/buildpacks/src/test/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackCliControllerTest.java
new file mode 100644
index 0000000000..3a060496b9
--- /dev/null
+++ b/jkube-kit/build/service/buildpacks/src/test/java/org/eclipse/jkube/kit/service/buildpacks/BuildPackCliControllerTest.java
@@ -0,0 +1,120 @@
+/*
+ * 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.service.buildpacks;
+
+import org.eclipse.jkube.kit.common.KitLogger;
+import org.eclipse.jkube.kit.common.util.EnvUtil;
+import org.eclipse.jkube.kit.service.buildpacks.controller.BuildPackCliController;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.DisplayName;
+import org.junit.jupiter.api.Nested;
+import org.junit.jupiter.api.Test;
+
+import java.io.File;
+import java.util.Objects;
+
+import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
+import static org.assertj.core.api.AssertionsForInterfaceTypes.assertThat;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.verify;
+
+class BuildPackCliControllerTest {
+ private KitLogger kitLogger;
+ private BuildPackCliController buildPackCliController;
+ private BuildPackBuildOptions buildOptions;
+ private File pack;
+
+ @BeforeEach
+ void setUp() {
+ kitLogger = spy(new KitLogger.SilentLogger());
+ String validPackBinary = EnvUtil.isWindows() ? "pack.bat" : "pack";
+ pack = new File(Objects.requireNonNull(getClass().getResource(String.format("/%s", validPackBinary))).getFile());
+ buildPackCliController = new BuildPackCliController(pack, kitLogger);
+ buildOptions = BuildPackBuildOptions.builder()
+ .imageName("foo/bar:latest")
+ .builderImage("foo/builder:base")
+ .creationTime("now")
+ .build();
+ }
+
+ @Nested
+ @DisplayName("pack command succeeds")
+ class CommandSucceeds {
+ @Test
+ @DisplayName("build, BuildPackBuildOptions passes as commandline arguments")
+ void build_whenInvoked_thenBuildPackBuildOptionsPassedAsCommandLineArguments() {
+ // When
+ buildPackCliController.build(buildOptions);
+
+ // Then
+ verify(kitLogger).info("[[s]]%s", "build foo/bar:latest --builder foo/builder:base --creation-time now");
+ }
+
+ @Test
+ @DisplayName("build, null/empty BuildPackBuildOption fields are not passes as commandline arguments")
+ void build_whenNullOrBlankBuildOptions_thenOnlyValidBuildPackBuildOptionsPassedAsCommandLineArguments() {
+ // Given
+ buildOptions = buildOptions.toBuilder()
+ .creationTime("")
+ .builderImage(null)
+ .build();
+
+ // When
+ buildPackCliController.build(buildOptions);
+
+ // Then
+ verify(kitLogger).info("[[s]]%s", "build foo/bar:latest");
+ }
+
+ @Test
+ @DisplayName("version, should get pack version")
+ void version() {
+ // When
+ String version = buildPackCliController.version();
+
+ // Then
+ assertThat(version).isEqualTo("0.32.1+git-b14250b.build-5241");
+ }
+ }
+
+ @Nested
+ @DisplayName("pack command fails")
+ class CommandFails {
+ @BeforeEach
+ void setUp() {
+ String invalidPackBinary = EnvUtil.isWindows() ? "invalid-pack.bat" : "invalid-pack";
+ pack = new File(Objects.requireNonNull(BuildPackCliControllerTest.class.getResource(String.format("/%s", invalidPackBinary))).getFile());
+ buildPackCliController = new BuildPackCliController(pack, kitLogger);
+ }
+
+ @Test
+ @DisplayName("build, throws exception")
+ void build_whenCommandFailed_thenThrowException() {
+ // When + Then
+ assertThatIllegalStateException()
+ .isThrownBy(() -> buildPackCliController.build(buildOptions))
+ .withMessageContaining("Process Existed With : 1");
+ }
+
+ @Test
+ @DisplayName("version, returns null on failure")
+ void version_whenCommandFailed_thenReturnNull() {
+ // When
+ String version = buildPackCliController.version();
+
+ // Then
+ assertThat(version).isNull();
+ }
+ }
+}