From 044deb74b83ea1a6e50c8c9ce3a73ef4a334263e Mon Sep 17 00:00:00 2001
From: Chris Laprun <metacosm@gmail.com>
Date: Fri, 11 Jun 2021 14:41:04 +0200
Subject: [PATCH 1/2] feat: throw new MissingCRDException when CRD validation
 fails

This is useful for processes that observe the controller registration
(the quarkus extension, for example) to know more specifically what
happened instead of using a generic OperatorException.
---
 .../operator/MissingCRDException.java         | 32 +++++++++++++++++++
 .../io/javaoperatorsdk/operator/Operator.java | 13 +++++---
 2 files changed, 41 insertions(+), 4 deletions(-)
 create mode 100644 operator-framework-core/src/main/java/io/javaoperatorsdk/operator/MissingCRDException.java

diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/MissingCRDException.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/MissingCRDException.java
new file mode 100644
index 0000000000..caf310fb22
--- /dev/null
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/MissingCRDException.java
@@ -0,0 +1,32 @@
+package io.javaoperatorsdk.operator;
+
+public class MissingCRDException extends OperatorException {
+  private final String crdName;
+  private final String specVersion;
+
+  public String getCrdName() {
+    return crdName;
+  }
+
+  public String getSpecVersion() {
+    return specVersion;
+  }
+
+  public MissingCRDException(String crdName, String specVersion) {
+    super();
+    this.crdName = crdName;
+    this.specVersion = specVersion;
+  }
+
+  public MissingCRDException(String crdName, String specVersion, String message) {
+    super(message);
+    this.crdName = crdName;
+    this.specVersion = specVersion;
+  }
+
+  public MissingCRDException(String crdName, String specVersion, String message, Throwable cause) {
+    super(message, cause);
+    this.crdName = crdName;
+    this.specVersion = specVersion;
+  }
+}
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
index 9bcd72673d..56e11af4da 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/Operator.java
@@ -114,17 +114,22 @@ public <R extends CustomResource> void register(
       final String controllerName = configuration.getName();
 
       // check that the custom resource is known by the cluster if configured that way
-      final CustomResourceDefinition crd;
+      final CustomResourceDefinition crd; // todo: check proper CRD spec version based on config
       if (configurationService.checkCRDAndValidateLocalModel()) {
         final var crdName = configuration.getCRDName();
+        final var specVersion = "v1";
         crd = k8sClient.apiextensions().v1().customResourceDefinitions().withName(crdName).get();
         if (crd == null) {
-          throw new OperatorException(
+          throw new MissingCRDException(
+              crdName,
+              specVersion,
               "'"
                   + crdName
-                  + "' CRD was not found on the cluster, controller "
+                  + "' "
+                  + specVersion
+                  + " CRD was not found on the cluster, controller '"
                   + controllerName
-                  + " cannot be registered");
+                  + "' cannot be registered");
         }
 
         // Apply validations that are not handled by fabric8

From 1917065f5b0bb04d708c019f3e40b92f54a74623 Mon Sep 17 00:00:00 2001
From: Chris Laprun <metacosm@gmail.com>
Date: Fri, 11 Jun 2021 14:53:41 +0200
Subject: [PATCH 2/2] feat: wrap registration errors in OperatorException

---
 .../processing/event/DefaultEventSourceManager.java    | 10 +++++++++-
 .../operator/processing/event/EventSourceManager.java  |  5 ++++-
 2 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/DefaultEventSourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/DefaultEventSourceManager.java
index a3ea01461b..7d3b733338 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/DefaultEventSourceManager.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/DefaultEventSourceManager.java
@@ -4,6 +4,7 @@
 import io.fabric8.kubernetes.client.CustomResource;
 import io.fabric8.kubernetes.client.dsl.MixedOperation;
 import io.fabric8.kubernetes.client.dsl.Resource;
+import io.javaoperatorsdk.operator.OperatorException;
 import io.javaoperatorsdk.operator.api.ResourceController;
 import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
 import io.javaoperatorsdk.operator.processing.CustomResourceCache;
@@ -69,7 +70,8 @@ public void close() {
   }
 
   @Override
-  public final void registerEventSource(String name, EventSource eventSource) {
+  public final void registerEventSource(String name, EventSource eventSource)
+      throws OperatorException {
     Objects.requireNonNull(eventSource, "EventSource must not be null");
 
     try {
@@ -81,6 +83,12 @@ public final void registerEventSource(String name, EventSource eventSource) {
       eventSources.put(name, eventSource);
       eventSource.setEventHandler(defaultEventHandler);
       eventSource.start();
+    } catch (Throwable e) {
+      if (e instanceof IllegalStateException) {
+        // leave untouched
+        throw e;
+      }
+      throw new OperatorException("Couldn't register event source named '" + name + "'", e);
     } finally {
       lock.unlock();
     }
diff --git a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
index 0aadc5247a..9879b51013 100644
--- a/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
+++ b/operator-framework-core/src/main/java/io/javaoperatorsdk/operator/processing/event/EventSourceManager.java
@@ -1,5 +1,6 @@
 package io.javaoperatorsdk.operator.processing.event;
 
+import io.javaoperatorsdk.operator.OperatorException;
 import java.io.Closeable;
 import java.util.Map;
 import java.util.Optional;
@@ -13,8 +14,10 @@ public interface EventSourceManager extends Closeable {
    * @param eventSource the {@link EventSource} to register
    * @throws IllegalStateException if an {@link EventSource} with the same name is already
    *     registered.
+   * @throws OperatorException if an error occurred during the registration process
    */
-  void registerEventSource(String name, EventSource eventSource);
+  void registerEventSource(String name, EventSource eventSource)
+      throws IllegalStateException, OperatorException;
 
   /**
    * Remove the {@link EventSource} identified by the given <code>name</code> from the event