Skip to content

Commit 7527fcb

Browse files
authored
Merge pull request #56 from ContainerSolutions/remove_group_and_kind
Remove group and kind
2 parents 0360db4 + 4665ca0 commit 7527fcb

File tree

34 files changed

+669
-536
lines changed

34 files changed

+669
-536
lines changed

README.md

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

4949
```java
5050
@Controller(customResourceClass = WebServer.class,
51-
kind = WebServerController.KIND,
52-
group = WebServerController.GROUP,
51+
crdName = "webservers.sample.javaoperatorsdk",
5352
customResourceListClass = WebServerList.class,
5453
customResourceDonebaleClass = WebServerDoneable.class)
5554
public class WebServerController implements ResourceController<WebServer> {
5655

57-
static final String KIND = "WebServer";
58-
static final String GROUP = "sample.javaoperatorsdk";
59-
6056
@Override
61-
public boolean deleteResource(CustomService resource, Context<CustomService> context) {
57+
public boolean deleteResource(CustomService resource) {
6258
// ... your logic ...
6359
return true;
6460
}
6561

6662
// Return the changed resource, so it gets updated. See javadoc for details.
6763
@Override
68-
public Optional<CustomService> createOrUpdateResource(CustomService resource, Context<CustomService> context) {
64+
public Optional<CustomService> createOrUpdateResource(CustomService resource) {
6965
// ... your logic ...
7066
return resource;
7167
}

operator-framework/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,5 +72,11 @@
7272
<version>3.4.1</version>
7373
<scope>test</scope>
7474
</dependency>
75+
<dependency>
76+
<groupId>org.awaitility</groupId>
77+
<artifactId>awaitility</artifactId>
78+
<version>4.0.1</version>
79+
<scope>test</scope>
80+
</dependency>
7581
</dependencies>
7682
</project>

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

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,51 +6,26 @@
66
import io.fabric8.kubernetes.client.CustomResourceDoneable;
77
import io.fabric8.kubernetes.client.CustomResourceList;
88

9-
import java.util.Optional;
10-
119
class ControllerUtils {
1210

13-
public static final String GROUP_API_DELIMITER = "/";
14-
1511
static String getDefaultFinalizer(ResourceController controller) {
16-
return getAnnotation(controller).defaultFinalizer();
12+
return getAnnotation(controller).finalizerName();
1713
}
1814

1915
static <R extends CustomResource> Class<R> getCustomResourceClass(ResourceController controller) {
2016
return (Class<R>) getAnnotation(controller).customResourceClass();
2117
}
2218

23-
static String getApiVersion(ResourceController controller) {
24-
return getGroup(controller) + GROUP_API_DELIMITER + getAnnotation(controller).version();
25-
}
26-
27-
static String getVersion(ResourceController controller) {
28-
return getAnnotation(controller).version();
29-
}
30-
31-
static Optional<String> getCrdName(ResourceController controller) {
32-
String crdName = getAnnotation(controller).crdName();
33-
if (crdName.isEmpty()) {
34-
return Optional.empty();
35-
} else {
36-
return Optional.of(crdName);
37-
}
38-
}
39-
40-
static String getKind(ResourceController controller) {
41-
return getAnnotation(controller).kind();
19+
static String getCrdName(ResourceController controller) {
20+
return getAnnotation(controller).crdName();
4221
}
4322

4423
static <R extends CustomResource> Class<? extends CustomResourceList<R>> getCustomResourceListClass(ResourceController controller) {
4524
return (Class<? extends CustomResourceList<R>>) getAnnotation(controller).customResourceListClass();
4625
}
4726

4827
static <R extends CustomResource> Class<? extends CustomResourceDoneable<R>> getCustomResourceDonebaleClass(ResourceController controller) {
49-
return (Class<? extends CustomResourceDoneable<R>>) getAnnotation(controller).customResourceDonebaleClass();
50-
}
51-
52-
private static String getGroup(ResourceController controller) {
53-
return getAnnotation(controller).group();
28+
return (Class<? extends CustomResourceDoneable<R>>) getAnnotation(controller).customResourceDoneableClass();
5429
}
5530

5631
private static Controller getAnnotation(ResourceController controller) {

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

Lines changed: 30 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@
44
import com.github.containersolutions.operator.processing.EventDispatcher;
55
import com.github.containersolutions.operator.processing.EventScheduler;
66
import io.fabric8.kubernetes.api.model.apiextensions.CustomResourceDefinition;
7-
import io.fabric8.kubernetes.api.model.apiextensions.CustomResourceDefinitionList;
87
import io.fabric8.kubernetes.client.CustomResource;
98
import io.fabric8.kubernetes.client.CustomResourceDoneable;
109
import io.fabric8.kubernetes.client.CustomResourceList;
@@ -18,19 +17,16 @@
1817
import java.util.Arrays;
1918
import java.util.HashMap;
2019
import java.util.Map;
21-
import java.util.Optional;
2220

2321
import static com.github.containersolutions.operator.ControllerUtils.*;
2422

23+
@SuppressWarnings("rawtypes")
2524
public class Operator {
2625

27-
private final KubernetesClient k8sClient;
26+
private final static Logger log = LoggerFactory.getLogger(Operator.class);
2827

29-
private Map<ResourceController, EventScheduler> controllers = new HashMap<>();
28+
private final KubernetesClient k8sClient;
3029
private Map<Class<? extends CustomResource>, CustomResourceOperationsImpl> customResourceClients = new HashMap<>();
31-
private EventScheduler eventScheduler;
32-
33-
private final static Logger log = LoggerFactory.getLogger(Operator.class);
3430

3531
public Operator(KubernetesClient k8sClient) {
3632
this.k8sClient = k8sClient;
@@ -44,36 +40,30 @@ public <R extends CustomResource> void registerController(ResourceController<R>
4440
registerController(controller, false, targetNamespaces);
4541
}
4642

43+
@SuppressWarnings("rawtypes")
4744
private <R extends CustomResource> void registerController(ResourceController<R> controller,
4845
boolean watchAllNamespaces, String... targetNamespaces) throws OperatorException {
4946
Class<R> resClass = getCustomResourceClass(controller);
50-
Optional<CustomResourceDefinition> crd = getCustomResourceDefinitionForController(controller);
51-
String kind = ControllerUtils.getKind(controller);
52-
KubernetesDeserializer.registerCustomKind(getApiVersion(controller), kind, resClass);
53-
54-
if (crd.isPresent()) {
55-
Class<? extends CustomResourceList<R>> list = getCustomResourceListClass(controller);
56-
Class<? extends CustomResourceDoneable<R>> doneable = getCustomResourceDonebaleClass(controller);
57-
MixedOperation client = k8sClient.customResources(crd.get(), resClass, list, doneable);
47+
CustomResourceDefinition crd = getCustomResourceDefinitionForController(controller);
48+
KubernetesDeserializer.registerCustomKind(getApiVersion(crd), getKind(crd), resClass);
5849

59-
EventDispatcher<R> eventDispatcher =
60-
new EventDispatcher<>(controller, (CustomResourceOperationsImpl) client, client, k8sClient,
61-
ControllerUtils.getDefaultFinalizer(controller));
50+
Class<? extends CustomResourceList<R>> list = getCustomResourceListClass(controller);
51+
Class<? extends CustomResourceDoneable<R>> doneable = getCustomResourceDonebaleClass(controller);
52+
MixedOperation client = k8sClient.customResources(crd, resClass, list, doneable);
6253

63-
eventScheduler = new EventScheduler(eventDispatcher);
64-
65-
registerWatches(controller, client, resClass, watchAllNamespaces, targetNamespaces);
66-
} else {
67-
throw new OperatorException("CRD '" + resClass.getSimpleName() + "' with version '"
68-
+ getVersion(controller) + "' not found");
69-
}
54+
EventDispatcher eventDispatcher = new EventDispatcher(controller, (CustomResourceOperationsImpl) client,
55+
getDefaultFinalizer(controller));
56+
EventScheduler eventScheduler = new EventScheduler(eventDispatcher);
57+
registerWatches(controller, client, resClass, watchAllNamespaces, targetNamespaces, eventScheduler);
7058
}
7159

7260
private <R extends CustomResource> void registerWatches(ResourceController<R> controller, MixedOperation client,
7361
Class<R> resClass,
74-
boolean watchAllNamespaces, String[] targetNamespaces) {
62+
boolean watchAllNamespaces, String[] targetNamespaces, EventScheduler eventScheduler) {
63+
7564
CustomResourceOperationsImpl crClient = (CustomResourceOperationsImpl) client;
7665
if (watchAllNamespaces) {
66+
// todo test this
7767
crClient.inAnyNamespace().watch(eventScheduler);
7868
} else if (targetNamespaces.length == 0) {
7969
client.watch(eventScheduler);
@@ -84,22 +74,17 @@ private <R extends CustomResource> void registerWatches(ResourceController<R> co
8474
}
8575
}
8676
customResourceClients.put(resClass, (CustomResourceOperationsImpl) client);
87-
controllers.put(controller, eventScheduler);
8877
log.info("Registered Controller: '{}' for CRD: '{}' for namespaces: {}", controller.getClass().getSimpleName(),
8978
resClass, targetNamespaces.length == 0 ? "[all/client namespace]" : Arrays.toString(targetNamespaces));
9079
}
9180

92-
private Optional<CustomResourceDefinition> getCustomResourceDefinitionForController(ResourceController controller) {
93-
Optional<String> crdName = getCrdName(controller);
94-
if (crdName.isPresent()) {
95-
return Optional.ofNullable(k8sClient.customResourceDefinitions().withName(crdName.get()).get());
96-
} else {
97-
CustomResourceDefinitionList crdList = k8sClient.customResourceDefinitions().list();
98-
return crdList.getItems().stream()
99-
.filter(c -> getKind(controller).equals(c.getSpec().getNames().getKind()) &&
100-
getVersion(controller).equals(c.getSpec().getVersion()))
101-
.findFirst();
81+
private CustomResourceDefinition getCustomResourceDefinitionForController(ResourceController controller) {
82+
String crdName = getCrdName(controller);
83+
CustomResourceDefinition customResourceDefinition = k8sClient.customResourceDefinitions().withName(crdName).get();
84+
if (customResourceDefinition == null) {
85+
throw new OperatorException("Cannot find Custom Resource Definition with name: " + crdName);
10286
}
87+
return customResourceDefinition;
10388
}
10489

10590
public Map<Class<? extends CustomResource>, CustomResourceOperationsImpl> getCustomResourceClients() {
@@ -113,4 +98,12 @@ public void stop() {
11398
public <T extends CustomResource> CustomResourceOperationsImpl getCustomResourceClients(Class<T> customResourceClass) {
11499
return customResourceClients.get(customResourceClass);
115100
}
101+
102+
private String getKind(CustomResourceDefinition crd) {
103+
return crd.getSpec().getNames().getKind();
104+
}
105+
106+
private String getApiVersion(CustomResourceDefinition crd) {
107+
return crd.getSpec().getGroup() + "/" + crd.getSpec().getVersion();
108+
}
116109
}

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

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

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

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

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,14 @@
1515

1616
String DEFAULT_FINALIZER = "operator.default.finalizer";
1717

18-
String DEFAULT_VERSION = "v1";
19-
20-
String version() default DEFAULT_VERSION;
21-
22-
String crdName() default "";
23-
24-
String group();
25-
26-
String kind();
18+
String crdName();
2719

2820
Class<? extends CustomResource> customResourceClass();
2921

3022
Class<? extends CustomResourceList<? extends CustomResource>> customResourceListClass();
3123

32-
Class<? extends CustomResourceDoneable<? extends CustomResource>> customResourceDonebaleClass();
24+
Class<? extends CustomResourceDoneable<? extends CustomResource>> customResourceDoneableClass();
3325

34-
String defaultFinalizer() default DEFAULT_FINALIZER;
26+
String finalizerName() default DEFAULT_FINALIZER;
3527

3628
}

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,23 +10,24 @@ public interface ResourceController<R extends CustomResource> {
1010
* The implementation should delete the associated component(s). Note that this is method is called when an object
1111
* is marked for deletion. After its executed the default finalizer is automatically removed by the framework;
1212
* unless the return value is false - note that this is almost never the case.
13+
* Its important to have the implementation also idempotent, in the current implementation to cover all edge cases
14+
* actually will be executed mostly twice.
1315
*
1416
* @param resource
15-
* @param context
1617
* @return true - so the finalizer is automatically removed after the call.
1718
* false if you don't want to remove the finalizer. Note that this is ALMOST NEVER the case.
1819
*/
19-
boolean deleteResource(R resource, Context<R> context);
20+
boolean deleteResource(R resource);
2021

2122
/**
2223
* The implementation of this operation is required to be idempotent.
2324
*
2425
* @return The resource is updated in api server if the return value is present
25-
* within Optional. This the common use cases. However in cases, for example the operator is restarted,
26-
* and we don't want to have an update call to k8s api to be made unnecessarily, by returning an empty Optional
27-
* this update can be skipped.
28-
* <b>However we will always call an update if there is no finalizer on object and its not marked for deletion.</b>
26+
* within Optional. This the common use cases. However in cases, for example the operator is restarted,
27+
* and we don't want to have an update call to k8s api to be made unnecessarily, by returning an empty Optional
28+
* this update can be skipped.
29+
* <b>However we will always call an update if there is no finalizer on object and its not marked for deletion.</b>
2930
*/
30-
Optional<R> createOrUpdateResource(R resource, Context<R> context);
31+
Optional<R> createOrUpdateResource(R resource);
3132

3233
}

0 commit comments

Comments
 (0)