Skip to content

Commit

Permalink
refactor: JibService uses AuthConfigFactory interface
Browse files Browse the repository at this point in the history
Signed-off-by: Marc Nuri <[email protected]>
  • Loading branch information
manusa authored May 21, 2024
1 parent db6f177 commit bfade49
Show file tree
Hide file tree
Showing 4 changed files with 129 additions and 25 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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();
}
Expand All @@ -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);
Expand All @@ -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();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand All @@ -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;
Expand All @@ -55,6 +57,7 @@ class JibServiceTest {
private Path tempDir;
private String remoteOciServer;
private KitLogger kitLogger;
private TestAuthConfigFactory testAuthConfigFactory;
private JKubeConfiguration configuration;
private ImageConfiguration imageConfiguration;

Expand All @@ -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())
Expand All @@ -82,16 +94,30 @@ 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 {

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)
Expand All @@ -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()
Expand All @@ -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();
Expand All @@ -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();
Expand Down
Original file line number Diff line number Diff line change
@@ -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<RegistryServerConfiguration> settings, String user, String registry, UnaryOperator<String> 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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -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());
Expand All @@ -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 {

Expand Down

0 comments on commit bfade49

Please sign in to comment.