|
9 | 9 | import static io.quarkus.arc.processor.DotNames.APPLICATION_SCOPED;
|
10 | 10 |
|
11 | 11 | import java.lang.annotation.Annotation;
|
12 |
| -import java.util.ArrayList; |
13 | 12 | import java.util.Arrays;
|
14 | 13 | import java.util.Collections;
|
15 | 14 | import java.util.HashMap;
|
16 | 15 | import java.util.HashSet;
|
17 | 16 | import java.util.List;
|
| 17 | +import java.util.Map; |
18 | 18 | import java.util.Optional;
|
19 | 19 | import java.util.Set;
|
20 | 20 | import java.util.function.BooleanSupplier;
|
| 21 | +import java.util.function.Predicate; |
21 | 22 | import java.util.stream.Collectors;
|
22 | 23 |
|
23 | 24 | import javax.enterprise.inject.Instance;
|
|
39 | 40 | import io.javaoperatorsdk.operator.api.config.ConfigurationService;
|
40 | 41 | import io.javaoperatorsdk.operator.api.reconciler.Reconciler;
|
41 | 42 | import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
|
42 |
| -import io.javaoperatorsdk.operator.processing.dependent.kubernetes.KubernetesDependent; |
43 | 43 | import io.quarkiverse.operatorsdk.common.ClassUtils;
|
44 | 44 | import io.quarkiverse.operatorsdk.common.ClassUtils.ReconcilerInfo;
|
45 | 45 | import io.quarkiverse.operatorsdk.common.ConfigurationUtils;
|
@@ -381,55 +381,8 @@ private QuarkusControllerConfiguration createControllerConfiguration(
|
381 | 381 | // extract the namespaces
|
382 | 382 | final var namespaces = configExtractor.namespaces(name);
|
383 | 383 |
|
384 |
| - // deal with dependent resources |
385 |
| - var dependentResources = Collections.<QuarkusDependentResourceSpec> emptyList(); |
386 |
| - if (controllerAnnotation != null) { |
387 |
| - final var dependents = controllerAnnotation.value("dependents"); |
388 |
| - if (dependents != null) { |
389 |
| - final var dependentAnnotations = dependents.asNestedArray(); |
390 |
| - dependentResources = new ArrayList<>(dependentAnnotations.length); |
391 |
| - for (AnnotationInstance dependentConfig : dependentAnnotations) { |
392 |
| - final var dependentTypeName = dependentConfig.value("type").asClass().name(); |
393 |
| - final var dependentType = index.getClassByName(dependentTypeName); |
394 |
| - if (!dependentType.hasNoArgsConstructor()) { |
395 |
| - throw new IllegalArgumentException( |
396 |
| - "DependentResource implementations must provide a no-arg constructor for instantiation purposes"); |
397 |
| - } |
398 |
| - |
399 |
| - final var dependentClass = loadClass(dependentTypeName.toString(), DependentResource.class); |
400 |
| - registerForReflection(reflectionClasses, dependentTypeName.toString()); |
401 |
| - |
402 |
| - // further process Kubernetes dependents |
403 |
| - final boolean isKubernetesDependent; |
404 |
| - try { |
405 |
| - isKubernetesDependent = JandexUtil.isSubclassOf(index, dependentType, |
406 |
| - KUBERNETES_DEPENDENT_RESOURCE); |
407 |
| - } catch (BuildException e) { |
408 |
| - throw new IllegalStateException("DependentResource " + dependentType + " is not indexed", e); |
409 |
| - } |
410 |
| - Object cfg = null; |
411 |
| - if (isKubernetesDependent) { |
412 |
| - final var kubeDepConfig = dependentType.classAnnotation(KUBERNETES_DEPENDENT); |
413 |
| - final var labelSelector = getLabelSelector(kubeDepConfig); |
414 |
| - // if the dependent doesn't explicitly provide a namespace configuration, inherit the configuration from the reconciler configuration |
415 |
| - final Set<String> dependentNamespaces = ConfigurationUtils.annotationValueOrDefault( |
416 |
| - kubeDepConfig, |
417 |
| - "namespaces", v -> new HashSet<>( |
418 |
| - Arrays.asList(v.asStringArray())), |
419 |
| - () -> namespaces); |
420 |
| - final var owned = ConfigurationUtils.annotationValueOrDefault( |
421 |
| - kubeDepConfig, |
422 |
| - "owned", |
423 |
| - AnnotationValue::asBoolean, |
424 |
| - () -> KubernetesDependent.ADD_OWNER_REFERENCE_DEFAULT); |
425 |
| - cfg = new QuarkusKubernetesDependentResourceConfig( |
426 |
| - owned, dependentNamespaces.toArray(new String[0]), labelSelector); |
427 |
| - } |
428 |
| - |
429 |
| - dependentResources.add(new QuarkusDependentResourceSpec(dependentClass, cfg)); |
430 |
| - } |
431 |
| - } |
432 |
| - } |
| 384 | + final var dependentResources = createDependentResources( |
| 385 | + reflectionClasses, index, controllerAnnotation, namespaces, additionalBeans); |
433 | 386 |
|
434 | 387 | // create the configuration
|
435 | 388 | configuration = new QuarkusControllerConfiguration(
|
@@ -465,6 +418,71 @@ private QuarkusControllerConfiguration createControllerConfiguration(
|
465 | 418 | return configuration;
|
466 | 419 | }
|
467 | 420 |
|
| 421 | + @SuppressWarnings("unchecked") |
| 422 | + private Map<String, QuarkusDependentResourceSpec> createDependentResources( |
| 423 | + BuildProducer<ReflectiveClassBuildItem> reflectionClasses, IndexView index, |
| 424 | + AnnotationInstance controllerAnnotation, Set<String> namespaces, |
| 425 | + BuildProducer<AdditionalBeanBuildItem> additionalBeans) { |
| 426 | + // deal with dependent resources |
| 427 | + var dependentResources = Collections.<String, QuarkusDependentResourceSpec> emptyMap(); |
| 428 | + if (controllerAnnotation != null) { |
| 429 | + final var dependents = controllerAnnotation.value("dependents"); |
| 430 | + if (dependents != null) { |
| 431 | + final var dependentAnnotations = dependents.asNestedArray(); |
| 432 | + dependentResources = new HashMap<>(dependentAnnotations.length); |
| 433 | + for (AnnotationInstance dependentConfig : dependentAnnotations) { |
| 434 | + final var dependentTypeDN = dependentConfig.value("type").asClass().name(); |
| 435 | + final var dependentType = index.getClassByName(dependentTypeDN); |
| 436 | + if (!dependentType.hasNoArgsConstructor()) { |
| 437 | + throw new IllegalArgumentException( |
| 438 | + "DependentResource implementations must provide a no-arg constructor for instantiation purposes"); |
| 439 | + } |
| 440 | + |
| 441 | + final var dependentTypeName = dependentTypeDN.toString(); |
| 442 | + final var dependentClass = loadClass(dependentTypeName, DependentResource.class); |
| 443 | + registerForReflection(reflectionClasses, dependentTypeName); |
| 444 | + |
| 445 | + // further process Kubernetes dependents |
| 446 | + final boolean isKubernetesDependent; |
| 447 | + try { |
| 448 | + isKubernetesDependent = JandexUtil.isSubclassOf(index, dependentType, |
| 449 | + KUBERNETES_DEPENDENT_RESOURCE); |
| 450 | + } catch (BuildException e) { |
| 451 | + throw new IllegalStateException("DependentResource " + dependentType + " is not indexed", e); |
| 452 | + } |
| 453 | + Object cfg = null; |
| 454 | + if (isKubernetesDependent) { |
| 455 | + final var kubeDepConfig = dependentType.classAnnotation(KUBERNETES_DEPENDENT); |
| 456 | + final var labelSelector = getLabelSelector(kubeDepConfig); |
| 457 | + // if the dependent doesn't explicitly provide a namespace configuration, inherit the configuration from the reconciler configuration |
| 458 | + final Set<String> dependentNamespaces = ConfigurationUtils.annotationValueOrDefault( |
| 459 | + kubeDepConfig, |
| 460 | + "namespaces", v -> new HashSet<>( |
| 461 | + Arrays.asList(v.asStringArray())), |
| 462 | + () -> namespaces); |
| 463 | + cfg = new QuarkusKubernetesDependentResourceConfig(dependentNamespaces.toArray(new String[0]), |
| 464 | + labelSelector); |
| 465 | + } |
| 466 | + |
| 467 | + var nameField = dependentConfig.value("name"); |
| 468 | + final var name = Optional.ofNullable(nameField) |
| 469 | + .map(AnnotationValue::asString) |
| 470 | + .filter(Predicate.not(String::isBlank)) |
| 471 | + .orElse(DependentResource.defaultNameFor(dependentClass)); |
| 472 | + dependentResources.put(name, new QuarkusDependentResourceSpec(dependentClass, cfg, name)); |
| 473 | + |
| 474 | + additionalBeans.produce( |
| 475 | + AdditionalBeanBuildItem.builder() |
| 476 | + .addBeanClass(dependentTypeName) |
| 477 | + .setUnremovable() |
| 478 | + .setDefaultScope(APPLICATION_SCOPED) |
| 479 | + .build()); |
| 480 | + } |
| 481 | + } |
| 482 | + } |
| 483 | + return dependentResources; |
| 484 | + } |
| 485 | + |
468 | 486 | private String getFullResourceName(Class<? extends HasMetadata> crClass) {
|
469 | 487 | return ReconcilerUtils.getResourceTypeName(crClass);
|
470 | 488 | }
|
|
0 commit comments