Skip to content

Commit 134d5c0

Browse files
authored
improve: simpler api for adding additional CRD file (#2574)
Signed-off-by: Attila Mészáros <[email protected]>
1 parent 34f1d81 commit 134d5c0

File tree

3 files changed

+47
-31
lines changed

3 files changed

+47
-31
lines changed

operator-framework-junit5/src/main/java/io/javaoperatorsdk/operator/junit/LocallyRunOperatorExtension.java

+46-30
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.ByteArrayInputStream;
44
import java.io.FileInputStream;
5+
import java.io.FileNotFoundException;
56
import java.io.IOException;
67
import java.io.InputStream;
78
import java.nio.charset.StandardCharsets;
@@ -21,6 +22,7 @@
2122

2223
import io.fabric8.kubernetes.api.model.HasMetadata;
2324
import io.fabric8.kubernetes.api.model.Namespaced;
25+
import io.fabric8.kubernetes.api.model.apiextensions.v1.CustomResourceDefinition;
2426
import io.fabric8.kubernetes.client.CustomResource;
2527
import io.fabric8.kubernetes.client.KubernetesClient;
2628
import io.fabric8.kubernetes.client.LocalPortForward;
@@ -45,7 +47,7 @@ public class LocallyRunOperatorExtension extends AbstractOperatorExtension {
4547
private final List<LocalPortForward> localPortForwards;
4648
private final List<Class<? extends CustomResource>> additionalCustomResourceDefinitions;
4749
private final Map<Reconciler, RegisteredController> registeredControllers;
48-
private final Map<String, String> crdMappings;
50+
private final List<String> additionalCrds;
4951

5052
private LocallyRunOperatorExtension(
5153
List<ReconcilerSpec> reconcilers,
@@ -60,7 +62,7 @@ private LocallyRunOperatorExtension(
6062
Consumer<ConfigurationServiceOverrider> configurationServiceOverrider,
6163
Function<ExtensionContext, String> namespaceNameSupplier,
6264
Function<ExtensionContext, String> perClassNamespaceNameSupplier,
63-
Map<String, String> crdMappings) {
65+
List<String> additionalCrds) {
6466
super(
6567
infrastructure,
6668
infrastructureTimeout,
@@ -80,7 +82,7 @@ private LocallyRunOperatorExtension(
8082
: overrider -> overrider.withKubernetesClient(kubernetesClient);
8183
this.operator = new Operator(configurationServiceOverrider);
8284
this.registeredControllers = new HashMap<>();
83-
this.crdMappings = crdMappings;
85+
this.additionalCrds = additionalCrds;
8486
}
8587

8688
/**
@@ -119,6 +121,10 @@ public static void applyCrd(String resourceTypeName, KubernetesClient client) {
119121
}
120122
}
121123

124+
public static void applyCrd(CustomResourceDefinition crd, KubernetesClient client) {
125+
client.resource(crd).serverSideApply();
126+
}
127+
122128
private static void applyCrd(InputStream is, String path, KubernetesClient client) {
123129
try {
124130
if (is == null) {
@@ -138,6 +144,17 @@ private static void applyCrd(InputStream is, String path, KubernetesClient clien
138144
}
139145
}
140146

147+
public static List<CustomResourceDefinition> parseCrds(String path, KubernetesClient client) {
148+
try (InputStream is = new FileInputStream(path)) {
149+
return client.load(new ByteArrayInputStream(is.readAllBytes()))
150+
.items().stream().map(i -> (CustomResourceDefinition) i).collect(Collectors.toList());
151+
} catch (FileNotFoundException e) {
152+
throw new RuntimeException(e);
153+
} catch (IOException e) {
154+
throw new RuntimeException(e);
155+
}
156+
}
157+
141158
private Stream<Reconciler> reconcilers() {
142159
return reconcilers.stream().map(reconcilerSpec -> reconcilerSpec.reconciler);
143160
}
@@ -190,7 +207,7 @@ protected void before(ExtensionContext context) {
190207
}
191208

192209
additionalCustomResourceDefinitions.forEach(this::applyCrd);
193-
210+
Map<String, CustomResourceDefinition> unappliedCRDs = getAdditionalCRDsFromFiles();
194211
for (var ref : reconcilers) {
195212
final var config = operator.getConfigurationService().getConfigurationFor(ref.reconciler);
196213
final var oconfig = override(config);
@@ -207,29 +224,40 @@ protected void before(ExtensionContext context) {
207224
ref.controllerConfigurationOverrider.accept(oconfig);
208225
}
209226

210-
final var unapplied = new HashMap<>(crdMappings);
211227
final var resourceTypeName = ReconcilerUtils.getResourceTypeName(resourceClass);
212228
// only try to apply a CRD for the reconciler if it is associated to a CR
213229
if (CustomResource.class.isAssignableFrom(resourceClass)) {
214-
applyCrd(resourceTypeName);
215-
unapplied.remove(resourceTypeName);
230+
if (unappliedCRDs.get(resourceTypeName) != null) {
231+
applyCrd(resourceTypeName);
232+
unappliedCRDs.remove(resourceTypeName);
233+
} else {
234+
applyCrd(resourceClass);
235+
}
216236
}
217237

218238
// apply yet unapplied CRDs
219-
unapplied.keySet().forEach(this::applyCrd);
220-
221239
var registeredController = this.operator.register(ref.reconciler, oconfig.build());
222240
registeredControllers.put(ref.reconciler, registeredController);
223241
}
242+
unappliedCRDs.keySet().forEach(this::applyCrd);
224243

225244
LOGGER.debug("Starting the operator locally");
226245
this.operator.start();
227246
}
228247

248+
private Map<String, CustomResourceDefinition> getAdditionalCRDsFromFiles() {
249+
Map<String, CustomResourceDefinition> crdMappings = new HashMap<>();
250+
additionalCrds.forEach(p -> {
251+
var crds = parseCrds(p, getKubernetesClient());
252+
crds.forEach(c -> crdMappings.put(c.getMetadata().getName(), c));
253+
});
254+
return crdMappings;
255+
}
256+
229257
/**
230258
* Applies the CRD associated with the specified custom resource, first checking if a CRD has been
231-
* manually specified using {@link Builder#withCRDMapping(Class, String)}, otherwise assuming that
232-
* its CRD should be found in the standard location as explained in
259+
* manually specified using {@link Builder#withAdditionalCRD(String)}, otherwise assuming that its
260+
* CRD should be found in the standard location as explained in
233261
* {@link LocallyRunOperatorExtension#applyCrd(String, KubernetesClient)}
234262
*
235263
* @param crClass the custom resource class for which we want to apply the CRD
@@ -239,16 +267,7 @@ public void applyCrd(Class<? extends CustomResource> crClass) {
239267
}
240268

241269
public void applyCrd(String resourceTypeName) {
242-
final var path = crdMappings.get(resourceTypeName);
243-
if (path != null) {
244-
try (InputStream inputStream = new FileInputStream(path)) {
245-
applyCrd(inputStream, path, getKubernetesClient());
246-
} catch (IOException e) {
247-
throw new IllegalStateException("Cannot apply CRD yaml: " + path, e);
248-
}
249-
} else {
250-
applyCrd(resourceTypeName, getKubernetesClient());
251-
}
270+
applyCrd(resourceTypeName, getKubernetesClient());
252271
}
253272

254273
@Override
@@ -277,6 +296,7 @@ public static class Builder extends AbstractBuilder<Builder> {
277296
private final List<PortForwardSpec> portForwards;
278297
private final List<Class<? extends CustomResource>> additionalCustomResourceDefinitions;
279298
private final Map<String, String> crdMappings;
299+
private final List<String> additionalCRDs = new ArrayList<>();
280300
private KubernetesClient kubernetesClient;
281301

282302
protected Builder() {
@@ -339,13 +359,8 @@ public Builder withAdditionalCustomResourceDefinition(
339359
return this;
340360
}
341361

342-
public Builder withCRDMapping(Class<? extends CustomResource> customResourceClass,
343-
String path) {
344-
return withCRDMapping(ReconcilerUtils.getResourceTypeName(customResourceClass), path);
345-
}
346-
347-
public Builder withCRDMapping(String resourceTypeName, String path) {
348-
crdMappings.put(resourceTypeName, path);
362+
public Builder withAdditionalCRD(String path) {
363+
additionalCRDs.add(path);
349364
return this;
350365
}
351366

@@ -360,8 +375,9 @@ public LocallyRunOperatorExtension build() {
360375
waitForNamespaceDeletion,
361376
oneNamespacePerClass,
362377
kubernetesClient,
363-
configurationServiceOverrider, namespaceNameSupplier, perClassNamespaceNameSupplier,
364-
crdMappings);
378+
configurationServiceOverrider, namespaceNameSupplier,
379+
perClassNamespaceNameSupplier,
380+
additionalCRDs);
365381
}
366382
}
367383

operator-framework/src/test/java/io/javaoperatorsdk/operator/CRDMappingInTestExtensionIT.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class CRDMappingInTestExtensionIT {
2828
LocallyRunOperatorExtension operator =
2929
LocallyRunOperatorExtension.builder()
3030
.withReconciler(new TestReconciler())
31-
.withCRDMapping("tests.crd.example", "src/test/crd/test.crd")
31+
.withAdditionalCRD("src/test/resources/crd/test.crd")
3232
.build();
3333

3434
@Test

0 commit comments

Comments
 (0)