From b4b772d110c15578a1861fbdf383a14ccebb21bb Mon Sep 17 00:00:00 2001 From: Marc Nuri Date: Wed, 22 Mar 2023 19:53:27 +0100 Subject: [PATCH] feat: deploy Docker registry on Kubernetes --- .../api/extension/RegistryExtension.java | 65 +++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/it/src/main/java/org/eclipse/jkube/integrationtests/jupiter/api/extension/RegistryExtension.java b/it/src/main/java/org/eclipse/jkube/integrationtests/jupiter/api/extension/RegistryExtension.java index e83da08b..7fa7c3c2 100644 --- a/it/src/main/java/org/eclipse/jkube/integrationtests/jupiter/api/extension/RegistryExtension.java +++ b/it/src/main/java/org/eclipse/jkube/integrationtests/jupiter/api/extension/RegistryExtension.java @@ -19,7 +19,6 @@ import org.eclipse.jkube.integrationtests.cli.CliUtils; import org.eclipse.jkube.integrationtests.jupiter.api.DockerRegistry; import org.eclipse.jkube.integrationtests.jupiter.api.DockerRegistryHost; -import org.hamcrest.Matchers; import org.junit.jupiter.api.extension.AfterAllCallback; import org.junit.jupiter.api.extension.BeforeAllCallback; import org.junit.jupiter.api.extension.BeforeEachCallback; @@ -30,35 +29,40 @@ import java.io.File; import java.io.IOException; import java.lang.reflect.Field; +import java.util.stream.Stream; import static org.eclipse.jkube.integrationtests.cli.CliUtils.isWindows; import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.notNullValue; public class RegistryExtension implements HasKubernetesClient, BeforeAllCallback, BeforeEachCallback, AfterAllCallback { private static final Logger log = LoggerFactory.getLogger(RegistryExtension.class); + private static final String K8S_RESOURCE_NAME = "docker-registry"; + @Override public void beforeAll(ExtensionContext context) throws Exception { final var annotation = context.getRequiredTestClass().getAnnotation(DockerRegistry.class); CliUtils.runCommand("docker rm -f " + getName(annotation)); log.debug(() -> "Starting Docker Registry Extension"); - final CliUtils.CliResult dockerRegistry; + final RegistryInfo dockerRegistry; if (isWindows()) { dockerRegistry = startWindowsDockerRegistry(annotation); } else { - dockerRegistry = startRegularDockerRegistry(annotation); + dockerRegistry = startKubernetesDockerRegistry(context); } - assertThat(dockerRegistry.getOutput(), dockerRegistry.getExitCode(), Matchers.equalTo(0)); + assertThat(dockerRegistry.assertionContext, dockerRegistry.host, notNullValue()); + getStore(context).put(RegistryInfo.class, dockerRegistry); log.debug(() -> "Docker Registry started successfully"); } @Override public void beforeEach(ExtensionContext context) throws Exception { - final var annotation = context.getRequiredTestClass().getAnnotation(DockerRegistry.class); + final var registryInfo = getStore(context).get(RegistryInfo.class, RegistryInfo.class); for (Field f : context.getRequiredTestClass().getDeclaredFields()) { if (f.isAnnotationPresent(DockerRegistryHost.class) && f.getType() == String.class) { - setFieldValue(f, context.getRequiredTestInstance(), getDockerHost() + ":" + annotation.port()); + setFieldValue(f, context.getRequiredTestInstance(), registryInfo.host + ":" + registryInfo.port); } } } @@ -67,22 +71,47 @@ public void beforeEach(ExtensionContext context) throws Exception { public void afterAll(ExtensionContext context) throws Exception { log.debug(() -> "Closing Docker Registry"); CliUtils.runCommand("docker stop " + getName(context.getRequiredTestClass().getAnnotation(DockerRegistry.class))); + if (!isWindows()) { + deleteKubernetesDockerRegistry(context); + } + } + + private void deleteKubernetesDockerRegistry(ExtensionContext context) { + final var client = getClient(context); + Stream.of( + client.pods().withName(K8S_RESOURCE_NAME), + client.services().withName(K8S_RESOURCE_NAME) + ).forEach(r -> r.withGracePeriod(0L).delete()); } - private static CliUtils.CliResult startRegularDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException { - log.debug(() -> "Starting standard Docker Registry"); - return CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " + - getName(dockerRegistry) + " registry:2"); + private RegistryInfo startKubernetesDockerRegistry(ExtensionContext context) throws IOException, InterruptedException { + deleteKubernetesDockerRegistry(context); + final var client = getClient(context); + final var ip = CliUtils.runCommand("minikube ip").getOutput().trim(); + final var dockerRegistry = client.run().withName(K8S_RESOURCE_NAME).withImage("registry:2") + .withNewRunConfig() + .addToLabels("app", K8S_RESOURCE_NAME).addToLabels("group", "jkube-it").done(); + final var service = client.services().resource(new ServiceBuilder() + .withNewMetadata().withName(K8S_RESOURCE_NAME) + .addToLabels("app", K8S_RESOURCE_NAME).addToLabels("group", "jkube-it").endMetadata() + .withNewSpec().withType("NodePort").withSelector(dockerRegistry.getMetadata().getLabels()) + .addNewPort().withName("http").withPort(5000).withTargetPort(new IntOrString(5000)).endPort().endSpec() + .build()).serverSideApply(); + return new RegistryInfo(ip, service.getSpec().getPorts().get(0).getNodePort(), null); } - private static CliUtils.CliResult startWindowsDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException { + private static RegistryInfo startWindowsDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException { log.debug(() -> "Starting Windows specific Docker Registry"); final var registry = new File("C:\\registry"); if (!registry.exists() && !registry.mkdirs()) { throw new IllegalStateException("Directory C:\\registry cannot be created"); } - return CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " + + final var result = CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " + getName(dockerRegistry) + " -v C:\\registry:C:\\registry marcnuri/docker-registry-windows:ltsc2022"); + if (result.getExitCode() != 0) { + return new RegistryInfo(null, -1, result.getOutput()); + } + return new RegistryInfo(getDockerHost(), dockerRegistry.port(), result.getOutput()); } private static String getName(DockerRegistry dockerRegistry) { @@ -98,4 +127,16 @@ private static String getDockerHost() { .replaceAll(":\\d+$", ""); } } + + private static final class RegistryInfo { + private final String host; + private final int port; + private final String assertionContext; + + public RegistryInfo(String host, int port, String assertionContext) { + this.host = host; + this.port = port; + this.assertionContext = assertionContext; + } + } }