From bfade4937bba7b67208ab0aea686b3f282bee3be Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Tue, 21 May 2024 12:46:31 +0200 Subject: [PATCH] refactor: JibService uses AuthConfigFactory interface Signed-off-by: Marc Nuri --- .../jkube/kit/service/jib/JibService.java | 46 +++++++++++++-- .../jkube/kit/service/jib/JibServiceTest.java | 57 ++++++++++++++----- .../service/jib/TestAuthConfigFactory.java | 41 +++++++++++++ .../kubernetes/JibImageBuildService.java | 10 ++-- 4 files changed, 129 insertions(+), 25 deletions(-) create mode 100644 jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/TestAuthConfigFactory.java diff --git a/jkube-kit/build/service/jib/src/main/java/org/eclipse/jkube/kit/service/jib/JibService.java b/jkube-kit/build/service/jib/src/main/java/org/eclipse/jkube/kit/service/jib/JibService.java index 2c472bf1e9..9cc70ffdd9 100644 --- a/jkube-kit/build/service/jib/src/main/java/org/eclipse/jkube/kit/service/jib/JibService.java +++ b/jkube-kit/build/service/jib/src/main/java/org/eclipse/jkube/kit/service/jib/JibService.java @@ -25,9 +25,12 @@ import com.google.cloud.tools.jib.event.events.ProgressEvent; import org.eclipse.jkube.kit.build.api.assembly.BuildDirs; import org.eclipse.jkube.kit.build.api.assembly.JKubeBuildTarArchiver; +import org.eclipse.jkube.kit.build.api.auth.AuthConfig; +import org.eclipse.jkube.kit.build.api.auth.AuthConfigFactory; import org.eclipse.jkube.kit.common.JKubeConfiguration; import org.eclipse.jkube.kit.common.JKubeException; import org.eclipse.jkube.kit.common.KitLogger; +import org.eclipse.jkube.kit.common.RegistryConfig; import org.eclipse.jkube.kit.common.archive.ArchiveCompression; import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.ImageName; @@ -40,20 +43,23 @@ import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import static org.eclipse.jkube.kit.build.api.helper.RegistryUtil.getApplicablePushRegistryFrom; import static org.eclipse.jkube.kit.service.jib.JibServiceUtil.toRegistryImage; public class JibService implements AutoCloseable { private static final long JIB_EXECUTOR_SHUTDOWN_TIMEOUT_SECONDS = 10L; + private final AuthConfigFactory authConfigFactory; private final JKubeConfiguration configuration; private final ImageConfiguration imageConfiguration; private final JibLogger jibLogger; private final ExecutorService executorService; - public JibService(KitLogger kitLogger, JKubeConfiguration configuration, ImageConfiguration imageConfiguration) { + public JibService(KitLogger kitLogger, AuthConfigFactory authConfigFactory, JKubeConfiguration configuration, ImageConfiguration imageConfiguration) { + this.authConfigFactory = authConfigFactory; this.configuration = configuration; - this.imageConfiguration = imageConfiguration; + this.imageConfiguration = prependPushRegistry(imageConfiguration, configuration); jibLogger = new JibLogger(kitLogger); executorService = Executors.newCachedThreadPool(); } @@ -71,15 +77,19 @@ public void close() throws Exception { } } - public final void push(Credential pushCredentials /* TODO: remove*/) { - final String imageName = new ImageName(imageConfiguration.getName()).getFullName(); + public final void push() { + final String imageName = getImageName().getFullName(); final TarImage image = TarImage.at(getBuildTarArchive().toPath()); - final RegistryImage registryImage = toRegistryImage(imageName, pushCredentials); + final RegistryImage registryImage = toRegistryImage(imageName, getPushRegistryCredentials()); final Containerizer to = Containerizer.to(registryImage); final JibContainerBuilder from = Jib.from(image); containerize(from, to); } + public final ImageName getImageName() { + return new ImageName(imageConfiguration.getName()); + } + private void containerize(JibContainerBuilder from, Containerizer to) { to.setAllowInsecureRegistries(true); to.setExecutorService(executorService); @@ -105,5 +115,31 @@ private File getBuildTarArchive() { return new File(buildDirs.getTemporaryRootDirectory(), JKubeBuildTarArchiver.ARCHIVE_FILE_NAME + ArchiveCompression.none.getFileSuffix()); } + private Credential getPushRegistryCredentials() { + final RegistryConfig registryConfig = configuration.getPushRegistryConfig(); + final String pushRegistry = getApplicablePushRegistryFrom(imageConfiguration, registryConfig); + try { + final AuthConfig standardAuthConfig = authConfigFactory. + createAuthConfig(true, registryConfig.isSkipExtendedAuth(), registryConfig.getAuthConfig(), registryConfig.getSettings(), null, pushRegistry, registryConfig.getPasswordDecryptionMethod()); + Credential credentials = null; + if (standardAuthConfig != null) { + credentials = Credential.from(standardAuthConfig.getUsername(), standardAuthConfig.getPassword()); + } + return credentials; + } catch (IOException exception) { + throw new JKubeException("Error when getting push registry credentials", exception); + } + } + + private static ImageConfiguration prependPushRegistry(ImageConfiguration imageConfiguration, JKubeConfiguration configuration) { + final ImageConfiguration.ImageConfigurationBuilder icBuilder = imageConfiguration.toBuilder(); + final ImageName imageName = new ImageName(imageConfiguration.getName()); + final String pushRegistry = getApplicablePushRegistryFrom(imageConfiguration, configuration.getPushRegistryConfig()); + if (!imageName.hasRegistry() && pushRegistry != null) { + icBuilder.name(imageName.getFullName(pushRegistry)); + icBuilder.registry(pushRegistry); + } + return icBuilder.build(); + } } diff --git a/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/JibServiceTest.java b/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/JibServiceTest.java index 02ade5cf2c..3deeb4bdf1 100644 --- a/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/JibServiceTest.java +++ b/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/JibServiceTest.java @@ -14,7 +14,6 @@ package org.eclipse.jkube.kit.service.jib; import com.google.cloud.tools.jib.api.Containerizer; -import com.google.cloud.tools.jib.api.Credential; import com.google.cloud.tools.jib.api.Jib; import com.google.cloud.tools.jib.api.RegistryUnauthorizedException; import com.google.cloud.tools.jib.api.TarImage; @@ -30,6 +29,8 @@ import org.eclipse.jkube.kit.common.JKubeException; import org.eclipse.jkube.kit.common.JavaProject; import org.eclipse.jkube.kit.common.KitLogger; +import org.eclipse.jkube.kit.common.RegistryConfig; +import org.eclipse.jkube.kit.common.RegistryServerConfiguration; import org.eclipse.jkube.kit.config.image.ImageConfiguration; import org.eclipse.jkube.kit.config.image.build.BuildConfiguration; import org.junit.jupiter.api.AfterEach; @@ -44,6 +45,7 @@ import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Path; +import java.util.Collections; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; @@ -55,6 +57,7 @@ class JibServiceTest { private Path tempDir; private String remoteOciServer; private KitLogger kitLogger; + private TestAuthConfigFactory testAuthConfigFactory; private JKubeConfiguration configuration; private ImageConfiguration imageConfiguration; @@ -69,7 +72,16 @@ void setUp() { new RepoServerOptions(null, "oci-user", "oci-password") ).out; kitLogger = new KitLogger.SilentLogger(); + testAuthConfigFactory = new TestAuthConfigFactory(); configuration = JKubeConfiguration.builder() + .pushRegistryConfig(RegistryConfig.builder() + .registry(remoteOciServer) + .settings(Collections.singletonList(RegistryServerConfiguration.builder() + .id(remoteOciServer) + .username("oci-user") + .password("oci-password") + .build())) + .build()) .project(JavaProject.builder() .baseDirectory(tempDir.toFile()) .build()) @@ -82,6 +94,19 @@ void setUp() { .build(); } + @Test + void prependsRegistryWhenNotConfiguredInName() throws Exception { + configuration = configuration.toBuilder() + .pushRegistryConfig(RegistryConfig.builder() + .registry("prepend.example.com") + .build()) + .build(); + imageConfiguration = ImageConfiguration.builder().name("the-image-name").build(); + try (JibService jibService = new JibService(kitLogger, testAuthConfigFactory, configuration, imageConfiguration)) { + assertThat(jibService.getImageName().getFullName()).isEqualTo("prepend.example.com/the-image-name:latest"); + } + } + @Nested @DisplayName("push") class Push { @@ -89,9 +114,10 @@ class Push { private boolean sendCredentialsOverHttp; @BeforeEach - void buildContainer() throws Exception { + void setUp() throws Exception { sendCredentialsOverHttp = JibSystemProperties.sendCredentialsOverHttp(); System.setProperty(JibSystemProperties.SEND_CREDENTIALS_OVER_HTTP, "true"); + final BuildDirs buildDirs = new BuildDirs(imageConfiguration.getName(), configuration); Jib.fromScratch() .setFormat(ImageFormat.Docker) @@ -109,19 +135,20 @@ void tearDown() { } @Test - void emptyImageNameThrowsException() throws Exception { - try (JibService jibService = new JibService(kitLogger, configuration, ImageConfiguration.builder().build())) { - assertThatThrownBy(() -> jibService.push(null)) - .isInstanceOf(NullPointerException.class) - .hasMessage("Image name must not be null"); - } + void emptyImageNameThrowsException() { + final ImageConfiguration emptyImageConfiguration = ImageConfiguration.builder().build(); + assertThatThrownBy(() -> new JibService(kitLogger, testAuthConfigFactory, configuration, emptyImageConfiguration)) + .isInstanceOf(NullPointerException.class) + .hasMessage("Image name must not be null"); } @Test void pushInvalidCredentials() throws Exception { - final Credential invalidCredential = Credential.from("oci-user", "oci-password-invalid"); - try (JibService jibService = new JibService(kitLogger, configuration, imageConfiguration)) { - assertThatThrownBy(() -> jibService.push(invalidCredential)) + configuration = configuration.toBuilder() + .pushRegistryConfig(RegistryConfig.builder().build()) + .build(); + try (JibService jibService = new JibService(kitLogger, testAuthConfigFactory, configuration, imageConfiguration)) { + assertThatThrownBy(jibService::push) .isInstanceOf(JKubeException.class) .hasMessageContaining("Unable to containerize image using Jib: Unauthorized for") .cause() @@ -131,8 +158,8 @@ void pushInvalidCredentials() throws Exception { @Test void push() throws Exception { - try (JibService jibService = new JibService(kitLogger, configuration, imageConfiguration)) { - jibService.push(Credential.from("oci-user", "oci-password")); + try (JibService jibService = new JibService(kitLogger, testAuthConfigFactory, configuration, imageConfiguration)) { + jibService.push(); } final HttpURLConnection connection = (HttpURLConnection) new URL("http://" + remoteOciServer + "/v2/the-image-name/tags/list") .openConnection(); @@ -151,8 +178,8 @@ void pushAdditionalTags() throws Exception { .tag("1.0.0") .build()) .build(); - try (JibService jibService = new JibService(kitLogger, configuration, imageConfiguration)) { - jibService.push(Credential.from("oci-user", "oci-password")); + try (JibService jibService = new JibService(kitLogger, testAuthConfigFactory, configuration, imageConfiguration)) { + jibService.push(); } final HttpURLConnection connection = (HttpURLConnection) new URL("http://" + remoteOciServer + "/v2/the-image-name/tags/list") .openConnection(); diff --git a/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/TestAuthConfigFactory.java b/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/TestAuthConfigFactory.java new file mode 100644 index 0000000000..f82dcf3ef3 --- /dev/null +++ b/jkube-kit/build/service/jib/src/test/java/org/eclipse/jkube/kit/service/jib/TestAuthConfigFactory.java @@ -0,0 +1,41 @@ +/* + * 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.jib; + +import org.eclipse.jkube.kit.build.api.auth.AuthConfig; +import org.eclipse.jkube.kit.build.api.auth.AuthConfigFactory; +import org.eclipse.jkube.kit.common.RegistryServerConfiguration; + +import java.util.List; +import java.util.Map; +import java.util.function.UnaryOperator; + +public class TestAuthConfigFactory implements AuthConfigFactory { + + @Override + public AuthConfig createAuthConfig(boolean isPush, boolean skipExtendedAuth, Map authConfig, List settings, String user, String registry, UnaryOperator passwordDecryptionMethod) { + if (settings == null) { + return null; + } + for (RegistryServerConfiguration setting : settings) { + if (setting.getId().equals(registry)) { + return AuthConfig.builder() + .username(setting.getUsername()) + .password(setting.getPassword()) + .build(); + } + } + return null; + } +} diff --git a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/JibImageBuildService.java b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/JibImageBuildService.java index 752e6ded81..45876641e3 100644 --- a/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/JibImageBuildService.java +++ b/jkube-kit/config/service/src/main/java/org/eclipse/jkube/kit/config/service/kubernetes/JibImageBuildService.java @@ -118,11 +118,9 @@ public void buildSingleImage(ImageConfiguration imageConfiguration) throws JKube @Override protected void pushSingleImage(ImageConfiguration imageConfiguration, int retries, boolean skipTag) throws JKubeServiceException { - final RegistryConfig registryConfig = configuration.getPushRegistryConfig(); - final ImageConfiguration imageConfigToPush = prependPushRegistry(imageConfiguration, registryConfig); - kitLogger.info("Pushing image: %s", new ImageName(imageConfigToPush.getName()).getFullName()); - try (JibService jibService = new JibService(kitLogger, configuration, imageConfigToPush)) { - jibService.push(getRegistryCredentials(registryConfig, true, getPushRegistry(imageConfigToPush, registryConfig))); + try (JibService jibService = new JibService(kitLogger, authConfigFactory, configuration, imageConfiguration)) { + kitLogger.info("Pushing image: %s", jibService.getImageName().getFullName()); + jibService.push(); } catch (Exception ex) { throw new JKubeServiceException("Error when push JIB image", ex); } @@ -133,6 +131,7 @@ public void postProcess() { // No post processing required } + // TODO: remove in favor of JibService implementation static ImageConfiguration prependPushRegistry(ImageConfiguration imageConfiguration, RegistryConfig registryConfig) { final ImageConfiguration.ImageConfigurationBuilder icBuilder = imageConfiguration.toBuilder(); final ImageName imageName = new ImageName(imageConfiguration.getName()); @@ -151,6 +150,7 @@ static File getAssemblyTarArchive(ImageConfiguration imageConfig, JKubeConfigura .createDockerTarArchive(targetImage, configuration, imageConfig.getBuildConfiguration(), log, null); } + // TODO: remove in favor of JibService implementation Credential getRegistryCredentials(RegistryConfig registryConfig, boolean isPush, String registry) throws IOException {