Skip to content

Commit 305d6e7

Browse files
authored
Merge pull request #66 from ContainerSolutions/remove-doneable
Remove doneable
2 parents 0059029 + e798ab0 commit 305d6e7

File tree

21 files changed

+77
-115
lines changed

21 files changed

+77
-115
lines changed

README.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,7 @@ The Controller implements the business logic and describes all the classes neede
4848

4949
```java
5050
@Controller(customResourceClass = WebServer.class,
51-
crdName = "webservers.sample.javaoperatorsdk",
52-
customResourceListClass = WebServerList.class,
53-
customResourceDonebaleClass = WebServerDoneable.class)
51+
crdName = "webservers.sample.javaoperatorsdk")
5452
public class WebServerController implements ResourceController<WebServer> {
5553

5654
@Override

operator-framework/pom.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,10 @@
7373
<version>4.0.1</version>
7474
<scope>test</scope>
7575
</dependency>
76+
<dependency>
77+
<groupId>jboss</groupId>
78+
<artifactId>javassist</artifactId>
79+
<version>3.8.0.GA</version>
80+
</dependency>
7681
</dependencies>
7782
</project>

operator-framework/src/main/java/com/github/containersolutions/operator/ControllerUtils.java

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,26 @@
22

33
import com.github.containersolutions.operator.api.Controller;
44
import com.github.containersolutions.operator.api.ResourceController;
5+
import io.fabric8.kubernetes.api.builder.Function;
56
import io.fabric8.kubernetes.client.CustomResource;
67
import io.fabric8.kubernetes.client.CustomResourceDoneable;
7-
import io.fabric8.kubernetes.client.CustomResourceList;
8+
import javassist.*;
9+
import org.slf4j.Logger;
10+
import org.slf4j.LoggerFactory;
11+
12+
import java.util.HashMap;
13+
import java.util.Map;
14+
815

916
class ControllerUtils {
1017

18+
private final static Logger log = LoggerFactory.getLogger(Operator.class);
19+
20+
// this is just to support testing, this way we don't try to create class multiple times in memory with same name.
21+
// note that other solution is to add a random string to doneable class name
22+
private static Map<Class<? extends CustomResource>, Class<? extends CustomResourceDoneable<? extends CustomResource>>>
23+
doneableClassCache = new HashMap<>();
24+
1125
static String getDefaultFinalizer(ResourceController controller) {
1226
return getAnnotation(controller).finalizerName();
1327
}
@@ -20,16 +34,37 @@ static String getCrdName(ResourceController controller) {
2034
return getAnnotation(controller).crdName();
2135
}
2236

23-
static <R extends CustomResource> Class<? extends CustomResourceList<R>> getCustomResourceListClass(ResourceController controller) {
24-
return (Class<? extends CustomResourceList<R>>) getAnnotation(controller).customResourceListClass();
25-
}
2637

27-
static <R extends CustomResource> Class<? extends CustomResourceDoneable<R>> getCustomResourceDonebaleClass(ResourceController controller) {
28-
return (Class<? extends CustomResourceDoneable<R>>) getAnnotation(controller).customResourceDoneableClass();
38+
public static <T extends CustomResource> Class<? extends CustomResourceDoneable<T>>
39+
getCustomResourceDoneableClass(ResourceController<T> controller) {
40+
try {
41+
Class<? extends CustomResource> customResourceClass = getAnnotation(controller).customResourceClass();
42+
String className = customResourceClass.getPackage().getName() + "." + customResourceClass.getSimpleName() + "CustomResourceDoneable";
43+
44+
if (doneableClassCache.containsKey(customResourceClass)) {
45+
return (Class<? extends CustomResourceDoneable<T>>) doneableClassCache.get(customResourceClass);
46+
}
47+
48+
ClassPool pool = ClassPool.getDefault();
49+
pool.appendClassPath(new LoaderClassPath(Thread.currentThread().getContextClassLoader()));
50+
51+
CtClass superClass = pool.get(CustomResourceDoneable.class.getName());
52+
CtClass function = pool.get(Function.class.getName());
53+
CtClass customResource = pool.get(customResourceClass.getName());
54+
CtClass[] argTypes = {customResource, function};
55+
CtClass customDoneable = pool.makeClass(className, superClass);
56+
CtConstructor ctConstructor = CtNewConstructor.make(argTypes, null, "super($1, $2);", customDoneable);
57+
customDoneable.addConstructor(ctConstructor);
58+
59+
Class<? extends CustomResourceDoneable<T>> doneableClass = customDoneable.toClass();
60+
doneableClassCache.put(customResourceClass, doneableClass);
61+
return doneableClass;
62+
} catch (CannotCompileException | NotFoundException e) {
63+
throw new IllegalStateException(e);
64+
}
2965
}
3066

3167
private static Controller getAnnotation(ResourceController controller) {
3268
return controller.getClass().getAnnotation(Controller.class);
3369
}
34-
3570
}

operator-framework/src/main/java/com/github/containersolutions/operator/Operator.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import com.github.containersolutions.operator.processing.retry.Retry;
88
import io.fabric8.kubernetes.api.model.apiextensions.CustomResourceDefinition;
99
import io.fabric8.kubernetes.client.CustomResource;
10-
import io.fabric8.kubernetes.client.CustomResourceDoneable;
1110
import io.fabric8.kubernetes.client.CustomResourceList;
1211
import io.fabric8.kubernetes.client.KubernetesClient;
1312
import io.fabric8.kubernetes.client.dsl.MixedOperation;
@@ -59,9 +58,7 @@ private <R extends CustomResource> void registerController(ResourceController<R>
5958
CustomResourceDefinition crd = getCustomResourceDefinitionForController(controller);
6059
KubernetesDeserializer.registerCustomKind(getApiVersion(crd), getKind(crd), resClass);
6160

62-
Class<? extends CustomResourceList<R>> list = getCustomResourceListClass(controller);
63-
Class<? extends CustomResourceDoneable<R>> doneable = getCustomResourceDonebaleClass(controller);
64-
MixedOperation client = k8sClient.customResources(crd, resClass, list, doneable);
61+
MixedOperation client = k8sClient.customResources(crd, resClass, CustomResourceList.class, getCustomResourceDoneableClass(controller));
6562
EventDispatcher eventDispatcher = new EventDispatcher(controller,
6663
getDefaultFinalizer(controller), new EventDispatcher.CustomResourceReplaceFacade(client));
6764
EventScheduler eventScheduler = new EventScheduler(eventDispatcher, retry);

operator-framework/src/main/java/com/github/containersolutions/operator/api/Controller.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package com.github.containersolutions.operator.api;
22

33
import io.fabric8.kubernetes.client.CustomResource;
4-
import io.fabric8.kubernetes.client.CustomResourceDoneable;
5-
import io.fabric8.kubernetes.client.CustomResourceList;
64

75
import java.lang.annotation.ElementType;
86
import java.lang.annotation.Retention;
@@ -19,10 +17,5 @@
1917

2018
Class<? extends CustomResource> customResourceClass();
2119

22-
Class<? extends CustomResourceList<? extends CustomResource>> customResourceListClass();
23-
24-
Class<? extends CustomResourceDoneable<? extends CustomResource>> customResourceDoneableClass();
25-
2620
String finalizerName() default DEFAULT_FINALIZER;
27-
28-
}
21+
}

operator-framework/src/test/java/com/github/containersolutions/operator/ConcurrencyIT.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.github.containersolutions.operator;
22

33
import com.github.containersolutions.operator.sample.TestCustomResource;
4+
import com.github.containersolutions.operator.sample.TestCustomResourceController;
45
import io.fabric8.kubernetes.api.model.ConfigMap;
56
import org.awaitility.Awaitility;
67
import org.junit.jupiter.api.*;
@@ -50,6 +51,7 @@ public void manyResourcesGetCreatedUpdatedAndDeleted() throws InterruptedExcepti
5051
.untilAsserted(() -> {
5152
List<ConfigMap> items = integrationTest.getK8sClient().configMaps()
5253
.inNamespace(TEST_NAMESPACE)
54+
.withLabel("managedBy", TestCustomResourceController.class.getSimpleName())
5355
.list().getItems();
5456
assertThat(items).hasSize(NUMBER_OF_RESOURCES_CREATED);
5557
});
@@ -75,6 +77,7 @@ public void manyResourcesGetCreatedUpdatedAndDeleted() throws InterruptedExcepti
7577
.untilAsserted(() -> {
7678
List<ConfigMap> items = integrationTest.getK8sClient().configMaps()
7779
.inNamespace(TEST_NAMESPACE)
80+
.withLabel("managedBy", TestCustomResourceController.class.getSimpleName())
7881
.list().getItems();
7982
assertThat(items).hasSize(NUMBER_OF_RESOURCES_CREATED - NUMBER_OF_RESOURCES_DELETED);
8083

operator-framework/src/test/java/com/github/containersolutions/operator/ControllerUtilsTest.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,23 +2,21 @@
22

33
import com.github.containersolutions.operator.sample.TestCustomResource;
44
import com.github.containersolutions.operator.sample.TestCustomResourceController;
5-
import com.github.containersolutions.operator.sample.TestCustomResourceDoneable;
6-
import com.github.containersolutions.operator.sample.TestCustomResourceList;
5+
import io.fabric8.kubernetes.client.CustomResourceDoneable;
76
import org.junit.jupiter.api.Test;
87

98
import static com.github.containersolutions.operator.api.Controller.DEFAULT_FINALIZER;
109
import static com.github.containersolutions.operator.sample.TestCustomResourceController.CRD_NAME;
1110
import static org.junit.jupiter.api.Assertions.assertEquals;
11+
import static org.junit.jupiter.api.Assertions.assertTrue;
1212

1313
class ControllerUtilsTest {
1414

1515
@Test
1616
public void returnsValuesFromControllerAnnotationFinalizer() {
1717
assertEquals(DEFAULT_FINALIZER, ControllerUtils.getDefaultFinalizer(new TestCustomResourceController(null)));
1818
assertEquals(TestCustomResource.class, ControllerUtils.getCustomResourceClass(new TestCustomResourceController(null)));
19-
assertEquals(TestCustomResourceDoneable.class, ControllerUtils.getCustomResourceDonebaleClass(new TestCustomResourceController(null)));
20-
assertEquals(TestCustomResourceList.class, ControllerUtils.getCustomResourceListClass(new TestCustomResourceController(null)));
2119
assertEquals(CRD_NAME, ControllerUtils.getCrdName(new TestCustomResourceController(null)));
20+
assertTrue(CustomResourceDoneable.class.isAssignableFrom(ControllerUtils.getCustomResourceDoneableClass(new TestCustomResourceController(null))));
2221
}
23-
2422
}

operator-framework/src/test/java/com/github/containersolutions/operator/IntegrationTestSupport.java

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
11
package com.github.containersolutions.operator;
22

3-
import com.github.containersolutions.operator.sample.*;
3+
import com.github.containersolutions.operator.api.ResourceController;
4+
import com.github.containersolutions.operator.sample.TestCustomResource;
5+
import com.github.containersolutions.operator.sample.TestCustomResourceController;
6+
import com.github.containersolutions.operator.sample.TestCustomResourceSpec;
47
import io.fabric8.kubernetes.api.model.NamespaceBuilder;
58
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
69
import io.fabric8.kubernetes.api.model.apiextensions.CustomResourceDefinition;
10+
import io.fabric8.kubernetes.client.CustomResourceDoneable;
11+
import io.fabric8.kubernetes.client.CustomResourceList;
712
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
813
import io.fabric8.kubernetes.client.KubernetesClient;
914
import io.fabric8.kubernetes.client.dsl.MixedOperation;
@@ -17,6 +22,7 @@
1722
import java.io.InputStream;
1823
import java.util.concurrent.TimeUnit;
1924

25+
import static com.github.containersolutions.operator.ControllerUtils.getCustomResourceDoneableClass;
2026
import static org.assertj.core.api.Assertions.assertThat;
2127
import static org.awaitility.Awaitility.await;
2228

@@ -26,8 +32,8 @@ public class IntegrationTestSupport {
2632
public static final String TEST_CUSTOM_RESOURCE_PREFIX = "test-custom-resource-";
2733
private final static Logger log = LoggerFactory.getLogger(IntegrationTestSupport.class);
2834
private KubernetesClient k8sClient;
29-
private MixedOperation<TestCustomResource, TestCustomResourceList, TestCustomResourceDoneable,
30-
Resource<TestCustomResource, TestCustomResourceDoneable>> crOperations;
35+
private MixedOperation<TestCustomResource, CustomResourceList, CustomResourceDoneable,
36+
Resource<TestCustomResource, CustomResourceDoneable>> crOperations;
3137
private Operator operator;
3238

3339

@@ -52,7 +58,9 @@ public void cleanup() {
5258
k8sClient.customResourceDefinitions().createOrReplace(crd);
5359
KubernetesDeserializer.registerCustomKind(crd.getApiVersion(), crd.getKind(), TestCustomResource.class);
5460

55-
crOperations = k8sClient.customResources(crd, TestCustomResource.class, TestCustomResourceList.class, TestCustomResourceDoneable.class);
61+
ResourceController<TestCustomResource> controller = new TestCustomResourceController(k8sClient);
62+
Class doneableClass = getCustomResourceDoneableClass(controller);
63+
crOperations = k8sClient.customResources(crd, TestCustomResource.class, CustomResourceList.class, doneableClass);
5664
crOperations.inNamespace(TEST_NAMESPACE).delete(crOperations.list().getItems());
5765
//we depend on the actual operator from the startup to handle the finalizers and clean up
5866
//resources from previous test runs
@@ -69,7 +77,9 @@ public void cleanup() {
6977

7078
await("all config maps cleaned up").atMost(60, TimeUnit.SECONDS)
7179
.untilAsserted(() -> {
72-
assertThat(k8sClient.configMaps().inNamespace(TEST_NAMESPACE).list().getItems()).isEmpty();
80+
assertThat(k8sClient.configMaps().inNamespace(TEST_NAMESPACE)
81+
.withLabel("managedBy", TestCustomResourceController.class.getSimpleName())
82+
.list().getItems().isEmpty());
7383
});
7484

7585
log.info("Cleaned up namespace " + TEST_NAMESPACE);
@@ -105,7 +115,7 @@ public KubernetesClient getK8sClient() {
105115
return k8sClient;
106116
}
107117

108-
public MixedOperation<TestCustomResource, TestCustomResourceList, TestCustomResourceDoneable, Resource<TestCustomResource, TestCustomResourceDoneable>> getCrOperations() {
118+
public MixedOperation<TestCustomResource, CustomResourceList, CustomResourceDoneable, Resource<TestCustomResource, CustomResourceDoneable>> getCrOperations() {
109119
return crOperations;
110120
}
111121

operator-framework/src/test/java/com/github/containersolutions/operator/sample/TestCustomResourceController.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,7 @@
1515

1616
@Controller(
1717
crdName = TestCustomResourceController.CRD_NAME,
18-
customResourceClass = TestCustomResource.class,
19-
customResourceListClass = TestCustomResourceList.class,
20-
customResourceDoneableClass = TestCustomResourceDoneable.class)
18+
customResourceClass = TestCustomResource.class)
2119
public class TestCustomResourceController implements ResourceController<TestCustomResource> {
2220

2321
private static final Logger log = LoggerFactory.getLogger(TestCustomResourceController.class);

operator-framework/src/test/java/com/github/containersolutions/operator/sample/TestCustomResourceDoneable.java

Lines changed: 0 additions & 11 deletions
This file was deleted.

0 commit comments

Comments
 (0)