Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CRD Generator maven plugin fails to detect CustomResources that are located in test sources #6683

Open
metacosm opened this issue Nov 29, 2024 · 2 comments

Comments

@metacosm
Copy link
Collaborator

Describe the bug

I have tests that rely on being able to deploy the CRD associated with test custom resources. However, this currently doesn't work with the maven plugin. I've tried to use the

<configuration>
    <classpath>WITH_ALL_DEPENDENCIES_AND_TESTS</classpath>
</configuration>

configuration option but this didn't change anything. Looking at the code of the plugin, it seems as if the classpath only takes effect for loading the custom resource classes, not when indexing, which means that the classes are never detected. I've tried to change the plugin code but the tests are now failing in an obscure way and that's about as far as I got tonight 😅

That's the modification I made:

 public CustomResourceCollector withClasspathElements(Collection<String> classpathElements) {
    if (classpathElements != null) {
      withFilesToScan(classpathElements.stream()
        .map(File::new)
        .filter(File::exists)
        .collect(Collectors.toList()));
    }
    this.customResourceClassLoader.withClasspathElements(classpathElements);
    return this;
  }

the idea being that if a user wants to change the lookup classpath, then the corresponding elements should probably also be indexed.

This actually raises another issue (for which I might create a separate ticket but still mentioning it here): we need another scope that includes only the runtime and test scopes instead of forcing everything just to get the test scope.

/cc @baloo42

Fabric8 Kubernetes Client version

SNAPSHOT

Steps to reproduce

You can see an example of the failure at operator-framework/java-operator-sdk#2540

Expected behavior

CRDs should also be generated for test classes if requested (and it should be easy to configure the plugin to also consider test classes).

Runtime

Kubernetes (vanilla)

Kubernetes API Server version

next (development version)

Environment

macOS

Fabric8 Kubernetes Client Logs

No response

Additional context

No response

@baloo42
Copy link
Contributor

baloo42 commented Nov 30, 2024

Ok looks like you ran directly into the most tricky part.^^

First some background, details can be found here:
https://github.com/baloo42/crd-generator-v2-docs/blob/main/crd-generator-maven-plugin.md

  • There is the classpath and the scan-scope to consider.
  • The scan-scope must be always part of the classpath
    because CustomResource classes must be loaded so that the CRD-Generator can process them.
  • But not all classpath elements must be in the scan-scope:
    Only the intended CustomResource classes must be in the scan-scope, so that they can be found.
  • Scanning is slow compared to class loading:
    If no jandex index can be found in a scan element (directory, Jar file), then the collector will create first an in-memory index for the whole element. Then the actual lookup for CustomResource classes happens.
    Loading a few classes from a classpath which contains many elements is compared to the index-creation fast.
  • Because of this, we have avoided to default to settings where the scan-scope equals to the classpath. It would be otherwise a bottleneck which slows down bigger projects by default.

In your case, if you want to generate CRDs for CustomResource classes from your test classes only, you have to configure the maven plugin in the following way:

      <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>crd-generator-maven-plugin</artifactId>
        <version>${fabric8-client.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
            <phase>process-test-classes</phase>
            <configuration>
              <classesToScan>${project.build.testOutputDirectory}</classesToScan>
              <classpath>WITH_ALL_DEPENDENCIES_AND_TESTS</classpath>
            </configuration>
          </execution>
        </executions>
      </plugin>
  • The phase must be set to process-test-classes. (Default: process-classes)
    The process-classes phase is executed before test-compile. This means test classes won't be detected by default (...on a fresh build with mvn clean package)
  • classesToScan must be set to ${project.build.testOutputDirectory}
  • classpath must be set to WITH_ALL_DEPENDENCIES_AND_TESTS

Please note that this will output the CRDs in target/classes/META-INF/fabric8, which seems to be intended in your case. If not, the output directory can be overriden with outputDirectory:

      <plugin>
        <groupId>io.fabric8</groupId>
        <artifactId>crd-generator-maven-plugin</artifactId>
        <version>${fabric8-client.version}</version>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
            <phase>process-test-classes</phase>
            <configuration>
              <classesToScan>${project.build.testOutputDirectory}</classesToScan>
              <classpath>WITH_ALL_DEPENDENCIES_AND_TESTS</classpath>
              <outputDirectory>${project.build.testOutputDirectory}</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>

@baloo42
Copy link
Contributor

baloo42 commented Nov 30, 2024

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants