Skip to content

Commit

Permalink
Fix for #14744: support KibernetesServer test resource for CRUD opera…
Browse files Browse the repository at this point in the history
…tions
  • Loading branch information
FroMage committed Feb 4, 2021
1 parent ad2b90b commit b7e948f
Show file tree
Hide file tree
Showing 4 changed files with 178 additions and 55 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package io.quarkus.test.kubernetes.client;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.GenericKubernetesClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

public abstract class AbstractKubernetesTestResource<T> implements QuarkusTestResourceLifecycleManager {
protected T server;

@Override
public Map<String, String> start() {
final Map<String, String> systemProps = new HashMap<>();
systemProps.put(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
systemProps.put(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
systemProps.put(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
systemProps.put(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
systemProps.put(Config.KUBERNETES_HTTP2_DISABLE, "true");

server = createServer();
initServer();

try (GenericKubernetesClient<?> client = getClient()) {
systemProps.put(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.getConfiguration().getMasterUrl());
}

configureServer();

return systemProps;
}

protected abstract GenericKubernetesClient<?> getClient();

/**
* Can be used by subclasses in order to
* setup the mock server before the Quarkus application starts
*/
protected void configureServer() {}

protected void initServer() {}

protected abstract T createServer();

protected boolean useHttps() {
return Boolean.getBoolean("quarkus.kubernetes-client.test.https");
}

@Override
public void inject(Object testInstance) {
Class<?> c = testInstance.getClass();
Class<? extends Annotation> annotation = getInjectionAnnotation();
Class<?> injectedClass = getInjectedClass();
while (c != Object.class) {
for (Field f : c.getDeclaredFields()) {
if (f.getAnnotation(annotation) != null) {
if (!injectedClass.isAssignableFrom(f.getType())) {
throw new RuntimeException(annotation+" can only be used on fields of type "+injectedClass);
}

f.setAccessible(true);
try {
f.set(testInstance, server);
return;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
c = c.getSuperclass();
}
}

protected abstract Class<?> getInjectedClass();

protected abstract Class<? extends Annotation> getInjectionAnnotation();

}
Original file line number Diff line number Diff line change
@@ -1,81 +1,62 @@
package io.quarkus.test.kubernetes.client;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.lang.annotation.Annotation;

import io.fabric8.kubernetes.client.Config;
import io.fabric8.kubernetes.client.NamespacedKubernetesClient;
import io.fabric8.kubernetes.client.GenericKubernetesClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesMockServer;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;

public class KubernetesMockServerTestResource implements QuarkusTestResourceLifecycleManager {

private KubernetesMockServer mockServer;
public class KubernetesMockServerTestResource extends AbstractKubernetesTestResource<KubernetesMockServer> {

@Override
public Map<String, String> start() {
final Map<String, String> systemProps = new HashMap<>();
systemProps.put(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
systemProps.put(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
systemProps.put(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
systemProps.put(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
systemProps.put(Config.KUBERNETES_HTTP2_DISABLE, "true");

mockServer = createMockServer();
mockServer.init();
try (NamespacedKubernetesClient client = mockServer.createClient()) {
systemProps.put(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, client.getConfiguration().getMasterUrl());
}

configureMockServer(mockServer);

return systemProps;
protected GenericKubernetesClient<?> getClient() {
return server.createClient();
}


@Override
protected void initServer() {
server.init();
}

@Override
protected KubernetesMockServer createServer() {
return createMockServer();
}

/**
* @deprecated use {@link #createServer()}
*/
@Deprecated
protected KubernetesMockServer createMockServer() {
return new KubernetesMockServer(useHttps());
}

@Override
protected void configureServer() {
configureMockServer(server);
}

/**
* Can be used by subclasses of {@code KubernetesMockServerTestResource} in order to
* setup the mock server before the Quarkus application starts
* @deprecated use {@link #configureServer()}
*/
@Deprecated
public void configureMockServer(KubernetesMockServer mockServer) {

}

@Override
public void stop() {
if (mockServer != null) {
mockServer.destroy();
if (server != null) {
server.destroy();
server = null;
}
}

@Override
public void inject(Object testInstance) {
Class<?> c = testInstance.getClass();
while (c != Object.class) {
for (Field f : c.getDeclaredFields()) {
if (f.getAnnotation(MockServer.class) != null) {
if (!KubernetesMockServer.class.isAssignableFrom(f.getType())) {
throw new RuntimeException("@MockServer can only be used on fields of type KubernetesMockServer");
}

f.setAccessible(true);
try {
f.set(testInstance, mockServer);
return;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
c = c.getSuperclass();
}
protected Class<?> getInjectedClass() {
return KubernetesMockServer.class;
}

protected boolean useHttps() {
return Boolean.getBoolean("quarkus.kubernetes-client.test.https");

@Override
protected Class<? extends Annotation> getInjectionAnnotation() {
return MockServer.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package io.quarkus.test.kubernetes.client;

import java.lang.annotation.Annotation;

import io.fabric8.kubernetes.client.GenericKubernetesClient;
import io.fabric8.kubernetes.client.server.mock.KubernetesServer;

public class KubernetesServerTestResource extends AbstractKubernetesTestResource<KubernetesServer> {

@Override
protected GenericKubernetesClient<?> getClient() {
return server.getClient();
}

@Override
protected void initServer() {
server.before();
}

@Override
protected KubernetesServer createServer() {
return new KubernetesServer(useHttps(), true);
}

@Override
public void stop() {
if (server != null) {
server.after();
server = null;
}
}

@Override
protected Class<?> getInjectedClass() {
return KubernetesServer.class;
}

@Override
protected Class<? extends Annotation> getInjectionAnnotation() {
return Server.class;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package io.quarkus.test.kubernetes.client;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import io.fabric8.kubernetes.client.server.mock.KubernetesServer;

/**
* Used to specify that the field should be injected with the mock Kubernetes API server
* Can only be used on type {@link KubernetesServer}
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Server {

}

0 comments on commit b7e948f

Please sign in to comment.