From 60bef18eaab1ea07b41442f3852eb4450e19b8b1 Mon Sep 17 00:00:00 2001 From: Chris Laprun Date: Fri, 22 Nov 2024 18:09:03 +0100 Subject: [PATCH] feat: make it possible to revert to using the v1 CRD generator Note that this should only be used if a blocking issue is found with the v2 generator because the v1 version won't be supported moving forward. Signed-off-by: Chris Laprun --- core/deployment/pom.xml | 4 ++ .../operatorsdk/deployment/CRDGeneration.java | 24 ++-------- .../operatorsdk/deployment/CRDGenerator.java | 14 ++++++ .../deployment/CRDGeneratorV1.java | 46 +++++++++++++++++++ .../deployment/CRDGeneratorV2.java | 46 +++++++++++++++++++ .../operatorsdk/runtime/CRDConfiguration.java | 16 +++++++ 6 files changed, 130 insertions(+), 20 deletions(-) create mode 100644 core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGenerator.java create mode 100644 core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV1.java create mode 100644 core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV2.java diff --git a/core/deployment/pom.xml b/core/deployment/pom.xml index c318a8b6b..ec3472580 100644 --- a/core/deployment/pom.xml +++ b/core/deployment/pom.xml @@ -50,6 +50,10 @@ io.fabric8 crd-generator-api-v2 + + io.fabric8 + crd-generator-api + org.semver4j semver4j diff --git a/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneration.java b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneration.java index 59c48251c..280d68979 100644 --- a/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneration.java +++ b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneration.java @@ -11,8 +11,6 @@ import org.jboss.logging.Logger; -import io.fabric8.crdv2.generator.CRDGenerator; -import io.fabric8.crdv2.generator.CustomResourceInfo; import io.fabric8.kubernetes.client.CustomResource; import io.quarkiverse.operatorsdk.common.CustomResourceAugmentedClassInfo; import io.quarkiverse.operatorsdk.common.FileUtils; @@ -79,21 +77,7 @@ CRDGenerationInfo generate(OutputTargetBuildItem outputTarget, FileUtils.ensureDirectoryExists(outputDir); // generate CRDs with detailed information - final var info = generator.forCRDVersions(crdConfiguration.versions()).inOutputDir(outputDir).detailedGenerate(); - final var crdDetailsPerNameAndVersion = info.getCRDDetailsPerNameAndVersion(); - - crdDetailsPerNameAndVersion.forEach((crdName, initialVersionToCRDInfoMap) -> { - log.infov("Generated {0} CRD:", crdName); - generated.add(crdName); - - initialVersionToCRDInfoMap - .forEach((crdSpecVersion, crdInfo) -> { - final var filePath = crdInfo.getFilePath(); - log.infov(" - {0} -> {1}", crdSpecVersion, filePath); - converted.addCRDInfo(new CRDInfo(crdName, - crdSpecVersion, filePath, crdInfo.getDependentClassNames())); - }); - }); + generator.generate(crdConfiguration.versions(), outputDir, generated, converted); } return new CRDGenerationInfo(shouldApply(), validateCustomResources, converted, generated); } @@ -145,10 +129,10 @@ void withCustomResource(Class> crClass, String as // generator MUST be initialized before we start processing classes as initializing it // will reset the types information held by the generator if (generator == null) { - generator = new CRDGenerator().withParallelGenerationEnabled(crdConfiguration.generateInParallel()); + generator = crdConfiguration.useV1CRDGenerator() ? new CRDGeneratorV1(crdConfiguration.generateInParallel()) + : new CRDGeneratorV2(crdConfiguration.generateInParallel()); } - final var info = CustomResourceInfo.fromClass(crClass); - generator.customResources(info); + generator.scheduleForGeneration(crClass); needGeneration = true; } catch (Exception e) { throw new IllegalArgumentException("Cannot process " + crClass.getName() + " custom resource" diff --git a/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGenerator.java b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGenerator.java new file mode 100644 index 000000000..659307a5e --- /dev/null +++ b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGenerator.java @@ -0,0 +1,14 @@ +package io.quarkiverse.operatorsdk.deployment; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import io.fabric8.kubernetes.client.CustomResource; +import io.quarkiverse.operatorsdk.runtime.CRDInfos; + +interface CRDGenerator { + void generate(List crdSpecVersions, File outputDir, Set generated, CRDInfos converted); + + void scheduleForGeneration(Class> crClass); +} diff --git a/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV1.java b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV1.java new file mode 100644 index 000000000..f183c6884 --- /dev/null +++ b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV1.java @@ -0,0 +1,46 @@ +package io.quarkiverse.operatorsdk.deployment; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.jboss.logging.Logger; + +import io.fabric8.crd.generator.CustomResourceInfo; +import io.fabric8.kubernetes.client.CustomResource; +import io.quarkiverse.operatorsdk.runtime.CRDInfo; +import io.quarkiverse.operatorsdk.runtime.CRDInfos; + +class CRDGeneratorV1 implements CRDGenerator { + private static final Logger log = Logger.getLogger(CRDGeneratorV1.class.getName()); + private final io.fabric8.crd.generator.CRDGenerator generator; + + public CRDGeneratorV1(boolean parallelGeneration) { + this.generator = new io.fabric8.crd.generator.CRDGenerator().withParallelGenerationEnabled(parallelGeneration); + } + + @Override + public void generate(List crdSpecVersions, File outputDir, Set generated, CRDInfos converted) { + final var info = generator.forCRDVersions(crdSpecVersions).inOutputDir(outputDir).detailedGenerate(); + final var crdDetailsPerNameAndVersion = info.getCRDDetailsPerNameAndVersion(); + + crdDetailsPerNameAndVersion.forEach((crdName, initialVersionToCRDInfoMap) -> { + log.infov("Generated {0} CRD:", crdName); + generated.add(crdName); + + initialVersionToCRDInfoMap + .forEach((crdSpecVersion, crdInfo) -> { + final var filePath = crdInfo.getFilePath(); + log.infov(" - {0} -> {1}", crdSpecVersion, filePath); + converted.addCRDInfo(new CRDInfo(crdName, + crdSpecVersion, filePath, crdInfo.getDependentClassNames())); + }); + }); + } + + @Override + public void scheduleForGeneration(Class> crClass) { + final var info = CustomResourceInfo.fromClass(crClass); + generator.customResources(info); + } +} diff --git a/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV2.java b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV2.java new file mode 100644 index 000000000..bdee1e4e7 --- /dev/null +++ b/core/deployment/src/main/java/io/quarkiverse/operatorsdk/deployment/CRDGeneratorV2.java @@ -0,0 +1,46 @@ +package io.quarkiverse.operatorsdk.deployment; + +import java.io.File; +import java.util.List; +import java.util.Set; + +import org.jboss.logging.Logger; + +import io.fabric8.crdv2.generator.CustomResourceInfo; +import io.fabric8.kubernetes.client.CustomResource; +import io.quarkiverse.operatorsdk.runtime.CRDInfo; +import io.quarkiverse.operatorsdk.runtime.CRDInfos; + +class CRDGeneratorV2 implements CRDGenerator { + private static final Logger log = Logger.getLogger(CRDGeneratorV2.class.getName()); + private final io.fabric8.crdv2.generator.CRDGenerator generator; + + public CRDGeneratorV2(boolean parallelGeneration) { + this.generator = new io.fabric8.crdv2.generator.CRDGenerator().withParallelGenerationEnabled(parallelGeneration); + } + + @Override + public void generate(List crdSpecVersions, File outputDir, Set generated, CRDInfos converted) { + final var info = generator.forCRDVersions(crdSpecVersions).inOutputDir(outputDir).detailedGenerate(); + final var crdDetailsPerNameAndVersion = info.getCRDDetailsPerNameAndVersion(); + + crdDetailsPerNameAndVersion.forEach((crdName, initialVersionToCRDInfoMap) -> { + log.infov("Generated {0} CRD:", crdName); + generated.add(crdName); + + initialVersionToCRDInfoMap + .forEach((crdSpecVersion, crdInfo) -> { + final var filePath = crdInfo.getFilePath(); + log.infov(" - {0} -> {1}", crdSpecVersion, filePath); + converted.addCRDInfo(new CRDInfo(crdName, + crdSpecVersion, filePath, crdInfo.getDependentClassNames())); + }); + }); + } + + @Override + public void scheduleForGeneration(Class> crClass) { + final var info = CustomResourceInfo.fromClass(crClass); + generator.customResources(info); + } +} diff --git a/core/runtime/src/main/java/io/quarkiverse/operatorsdk/runtime/CRDConfiguration.java b/core/runtime/src/main/java/io/quarkiverse/operatorsdk/runtime/CRDConfiguration.java index bd0ca5e9c..313169dcc 100644 --- a/core/runtime/src/main/java/io/quarkiverse/operatorsdk/runtime/CRDConfiguration.java +++ b/core/runtime/src/main/java/io/quarkiverse/operatorsdk/runtime/CRDConfiguration.java @@ -6,6 +6,7 @@ import io.fabric8.kubernetes.client.CustomResource; import io.quarkus.runtime.annotations.ConfigGroup; import io.smallrye.config.WithDefault; +import io.smallrye.config.WithName; @ConfigGroup public interface CRDConfiguration { @@ -13,6 +14,7 @@ public interface CRDConfiguration { String DEFAULT_OUTPUT_DIRECTORY = "kubernetes"; String DEFAULT_VALIDATE = "true"; String DEFAULT_VERSIONS = "v1"; + String DEFAULT_USE_V1_CRD_GENERATOR = "false"; /** * Whether the operator should check that the CRD is properly deployed and that the associated @@ -78,4 +80,18 @@ public interface CRDConfiguration { * @since 6.8.4 */ Optional> externalCRDLocations(); + + /** + * Whether or not to use the v1 version of the CRD generator. Note that this should only be used if a compatibility issue is + * found with the v2 generator, which is the default one and the one that is actively maintained. + * + * @return {@code true} if the v1 version of the CRD generator should be used + * @since 6.9.1 + * @deprecated using this method should be reserved for blocking situations, please open an issue reporting the problem + * you're facing with the v2 generator before reverting to use the v1 version + */ + @Deprecated(forRemoval = true) + @WithDefault(DEFAULT_USE_V1_CRD_GENERATOR) + @WithName("use-deprecated-v1-crd-generator") + Boolean useV1CRDGenerator(); }