Skip to content

Commit ad1ee2d

Browse files
committed
feat: deploy Docker registry on Kubernetes
1 parent e1f2062 commit ad1ee2d

File tree

3 files changed

+65
-14
lines changed

3 files changed

+65
-14
lines changed

.github/workflows/e2e-tests.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ jobs:
101101
minikube version: v1.25.2
102102
kubernetes version: ${{ matrix.kubernetes }}
103103
github token: ${{ secrets.GITHUB_TOKEN }}
104-
start args: --force
104+
start args: '--force --insecure-registry "0.0.0.0/0"'
105105
- name: Harden Runner
106106
uses: step-security/harden-runner@8e0b4153524c217e5dce81df0986478e95a7004a
107107
with:
@@ -139,7 +139,8 @@ jobs:
139139
us-east4-docker.pkg.dev:443
140140
- name: Install and Run Integration Tests
141141
run: |
142-
JKUBE_VERSION=$(./mvnw -q -f 'jkube/pom.xml' -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) \
142+
eval $(minikube docker-env) \
143+
&& JKUBE_VERSION=$(./mvnw -q -f 'jkube/pom.xml' -Dexec.executable=echo -Dexec.args='${project.version}' --non-recursive exec:exec) \
143144
&& ./mvnw -B -PKubernetes,${{ matrix.suite }} clean verify -Djkube.version="$JKUBE_VERSION"
144145
- name: Save reports as artifact
145146
if: always()

README.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,16 @@
22

33
This project hosts Integration test suites for https://github.com/eclipse/jkube.
44

5+
## Running locally
6+
7+
### Minikube
8+
9+
To be able to run the full suite in Minikube, you need to enable insecure registries (k8s:push tests).
10+
11+
```shell
12+
minikube start --insecure-registry "0.0.0.0/0"
13+
```
14+
515
## Test Structure
616

717
In order to be able to run the tests in a CI environment without hogging the resources

it/src/main/java/org/eclipse/jkube/integrationtests/jupiter/api/extension/RegistryExtension.java

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import org.eclipse.jkube.integrationtests.cli.CliUtils;
2020
import org.eclipse.jkube.integrationtests.jupiter.api.DockerRegistry;
2121
import org.eclipse.jkube.integrationtests.jupiter.api.DockerRegistryHost;
22-
import org.hamcrest.Matchers;
2322
import org.junit.jupiter.api.extension.AfterAllCallback;
2423
import org.junit.jupiter.api.extension.BeforeAllCallback;
2524
import org.junit.jupiter.api.extension.BeforeEachCallback;
@@ -30,9 +29,12 @@
3029
import java.io.File;
3130
import java.io.IOException;
3231
import java.lang.reflect.Field;
32+
import java.util.UUID;
33+
import java.util.stream.Stream;
3334

3435
import static org.eclipse.jkube.integrationtests.cli.CliUtils.isWindows;
3536
import static org.hamcrest.MatcherAssert.assertThat;
37+
import static org.hamcrest.Matchers.notNullValue;
3638

3739
public class RegistryExtension implements HasKubernetesClient, BeforeAllCallback, BeforeEachCallback, AfterAllCallback {
3840

@@ -43,22 +45,23 @@ public void beforeAll(ExtensionContext context) throws Exception {
4345
final var annotation = context.getRequiredTestClass().getAnnotation(DockerRegistry.class);
4446
CliUtils.runCommand("docker rm -f " + getName(annotation));
4547
log.debug(() -> "Starting Docker Registry Extension");
46-
final CliUtils.CliResult dockerRegistry;
48+
final RegistryInfo dockerRegistry;
4749
if (isWindows()) {
4850
dockerRegistry = startWindowsDockerRegistry(annotation);
4951
} else {
50-
dockerRegistry = startRegularDockerRegistry(annotation);
52+
dockerRegistry = startKubernetesDockerRegistry(context);
5153
}
52-
assertThat(dockerRegistry.getOutput(), dockerRegistry.getExitCode(), Matchers.equalTo(0));
54+
assertThat(dockerRegistry.assertionContext, dockerRegistry.host, notNullValue());
55+
getStore(context).put(RegistryInfo.class, dockerRegistry);
5356
log.debug(() -> "Docker Registry started successfully");
5457
}
5558

5659
@Override
5760
public void beforeEach(ExtensionContext context) throws Exception {
58-
final var annotation = context.getRequiredTestClass().getAnnotation(DockerRegistry.class);
61+
final var registryInfo = getStore(context).get(RegistryInfo.class, RegistryInfo.class);
5962
for (Field f : context.getRequiredTestClass().getDeclaredFields()) {
6063
if (f.isAnnotationPresent(DockerRegistryHost.class) && f.getType() == String.class) {
61-
setFieldValue(f, context.getRequiredTestInstance(), getDockerHost() + ":" + annotation.port());
64+
setFieldValue(f, context.getRequiredTestInstance(), registryInfo.host + ":" + registryInfo.port);
6265
}
6366
}
6467
}
@@ -67,22 +70,45 @@ public void beforeEach(ExtensionContext context) throws Exception {
6770
public void afterAll(ExtensionContext context) throws Exception {
6871
log.debug(() -> "Closing Docker Registry");
6972
CliUtils.runCommand("docker stop " + getName(context.getRequiredTestClass().getAnnotation(DockerRegistry.class)));
73+
if (!isWindows()) {
74+
final var registryInfo = getStore(context).get(RegistryInfo.class, RegistryInfo.class);
75+
final var client = getClient(context);
76+
Stream.of(
77+
client.pods().withName(registryInfo.name),
78+
client.services().withName(registryInfo.name)
79+
).forEach(r -> r.withGracePeriod(0L).delete());
80+
}
7081
}
7182

72-
private static CliUtils.CliResult startRegularDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException {
73-
log.debug(() -> "Starting standard Docker Registry");
74-
return CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " +
75-
getName(dockerRegistry) + " registry:2");
83+
private RegistryInfo startKubernetesDockerRegistry(ExtensionContext context) throws IOException, InterruptedException {
84+
final var name = "registry" + UUID.randomUUID().toString().replace("-", "");
85+
final var client = getClient(context);
86+
final var ip = CliUtils.runCommand("minikube ip").getOutput().trim();
87+
final var dockerRegistry = client.run().withName(name).withImage("registry:2")
88+
.withNewRunConfig()
89+
.addToLabels("app", "docker-registry").addToLabels("group", "jkube-it").done();
90+
final var service = client.services().resource(new ServiceBuilder()
91+
.withNewMetadata().withName(name)
92+
.addToLabels("app", "docker-registry").addToLabels("group", "jkube-it").endMetadata()
93+
.withNewSpec().withType("NodePort").withSelector(dockerRegistry.getMetadata().getLabels())
94+
.addNewPort().withName("http").withPort(5000).withTargetPort(new IntOrString(5000)).endPort().endSpec()
95+
.build())
96+
.serverSideApply(); // Unsupported in K8s 1.12
97+
return new RegistryInfo(name, ip, service.getSpec().getPorts().get(0).getNodePort(), null);
7698
}
7799

78-
private static CliUtils.CliResult startWindowsDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException {
100+
private static RegistryInfo startWindowsDockerRegistry(DockerRegistry dockerRegistry) throws IOException, InterruptedException {
79101
log.debug(() -> "Starting Windows specific Docker Registry");
80102
final var registry = new File("C:\\registry");
81103
if (!registry.exists() && !registry.mkdirs()) {
82104
throw new IllegalStateException("Directory C:\\registry cannot be created");
83105
}
84-
return CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " +
106+
final var result = CliUtils.runCommand("docker run --rm -d -p " + dockerRegistry.port() +":5000 --name " +
85107
getName(dockerRegistry) + " -v C:\\registry:C:\\registry marcnuri/docker-registry-windows:ltsc2022");
108+
if (result.getExitCode() != 0) {
109+
return new RegistryInfo(null, null, -1, result.getOutput());
110+
}
111+
return new RegistryInfo("windows-docker-registry", getDockerHost(), dockerRegistry.port(), result.getOutput());
86112
}
87113

88114
private static String getName(DockerRegistry dockerRegistry) {
@@ -98,4 +124,18 @@ private static String getDockerHost() {
98124
.replaceAll(":\\d+$", "");
99125
}
100126
}
127+
128+
private static final class RegistryInfo {
129+
private final String name;
130+
private final String host;
131+
private final int port;
132+
private final String assertionContext;
133+
134+
public RegistryInfo(String name, String host, int port, String assertionContext) {
135+
this.name = name;
136+
this.host = host;
137+
this.port = port;
138+
this.assertionContext = assertionContext;
139+
}
140+
}
101141
}

0 commit comments

Comments
 (0)