Skip to content

Native compilation improvements #297

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

Merged
merged 8 commits into from
Jan 14, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
import io.quarkus.deployment.builditem.FeatureBuildItem;
import io.quarkus.deployment.builditem.GeneratedClassBuildItem;
import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
import io.quarkus.gizmo.ClassCreator;
import io.quarkus.gizmo.ClassOutput;
import io.quarkus.gizmo.MethodCreator;
import io.quarkus.gizmo.MethodDescriptor;
import io.quarkus.kubernetes.client.spi.KubernetesClientBuildItem;
import java.lang.reflect.Modifier;
import java.util.List;
import java.util.Optional;
Expand Down Expand Up @@ -63,21 +63,24 @@ void indexSDKDependencies(BuildProducer<IndexDependencyBuildItem> indexDependenc
}

@BuildStep
@Record(ExecutionTime.RUNTIME_INIT)
@Record(ExecutionTime.STATIC_INIT)
void createConfigurationServiceAndOperator(
CombinedIndexBuildItem combinedIndexBuildItem,
BuildProducer<GeneratedClassBuildItem> generatedClass,
BuildProducer<SyntheticBeanBuildItem> syntheticBeanBuildItemBuildProducer,
BuildProducer<AdditionalBeanBuildItem> additionalBeans,
KubernetesClientBuildItem clientBuildItem,
BuildProducer<ReflectiveClassBuildItem> reflectionClasses,
ConfigurationServiceRecorder recorder) {
final var index = combinedIndexBuildItem.getIndex();
final var resourceControllers = index.getAllKnownImplementors(RESOURCE_CONTROLLER);

final var classOutput = new GeneratedClassGizmoAdaptor(generatedClass, true);
final List<ControllerConfiguration> controllerConfigs =
resourceControllers.stream()
.map(ci -> createControllerConfiguration(ci, classOutput, additionalBeans))
.map(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ouch.. did the fmt plugin do this?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep… 😞

ci ->
createControllerConfiguration(
ci, classOutput, additionalBeans, reflectionClasses))
.collect(Collectors.toList());

final var supplier = recorder.configurationServiceSupplier(controllerConfigs);
Expand All @@ -95,7 +98,8 @@ void createConfigurationServiceAndOperator(
private ControllerConfiguration createControllerConfiguration(
ClassInfo info,
ClassOutput classOutput,
BuildProducer<AdditionalBeanBuildItem> additionalBeans) {
BuildProducer<AdditionalBeanBuildItem> additionalBeans,
BuildProducer<ReflectiveClassBuildItem> reflectionClasses) {
// first retrieve the custom resource class
final var rcInterface =
info.interfaceTypes().stream()
Expand Down Expand Up @@ -147,9 +151,18 @@ private ControllerConfiguration createControllerConfiguration(
+ Controller.class.getCanonicalName()
+ " annotation");
}

// load CR class
final Class<CustomResource> crClass = (Class<CustomResource>) loadClass(crType);

// register CR class for introspection
reflectionClasses.produce(new ReflectiveClassBuildItem(true, true, crClass));

final var crdName =
valueOrDefault(
controllerAnnotation, "crdName", AnnotationValue::asString, EXCEPTION_SUPPLIER);

// create the configuration
final var configuration =
new QuarkusControllerConfiguration(
resourceControllerClassName,
Expand Down Expand Up @@ -193,4 +206,12 @@ private <T> T valueOrDefault(
Supplier<T> defaultValue) {
return Optional.ofNullable(annotation.value(name)).map(converter).orElseGet(defaultValue);
}

private Class<?> loadClass(String className) {
try {
return Thread.currentThread().getContextClassLoader().loadClass(className);
} catch (ClassNotFoundException e) {
throw new IllegalArgumentException("Couldn't find class " + className);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,17 @@ public static Set<String> asSet(String[] namespaces) {
: Set.of(namespaces);
}

// Needed for Quarkus to find the associated constructor parameter
public String getCrdName() {
return getCRDName();
}

// Needed for Quarkus to find the associated constructor parameter
public String getCrClass() {
return crClass;
}

// Needed for Quarkus to find the associated constructor parameter
public String getDoneableClassName() {
return doneableClassName;
}
Expand Down
48 changes: 48 additions & 0 deletions operator-framework-quarkus-extension/tests/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@
<artifactId>quarkus-junit5-internal</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.rest-assured</groupId>
<artifactId>rest-assured</artifactId>
Expand Down Expand Up @@ -70,6 +75,9 @@
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/Native*.java</exclude>
</excludes>
<systemPropertyVariables>
<java.util.logging.manager>
org.jboss.logmanager.LogManager
Expand All @@ -80,4 +88,44 @@
</plugin>
</plugins>
</build>


<profiles>
<profile>
<id>native</id>
<properties>
<quarkus.package.type>native</quarkus.package.type>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven.surefire.version}</version>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
<goal>verify</goal>
</goals>
<configuration>
<systemPropertyVariables>
<native.image.path>
${project.build.directory}/${project.build.finalName}-runner
</native.image.path>
<java.util.logging.manager>
org.jboss.logmanager.LogManager
</java.util.logging.manager>
<maven.home>${maven.home}</maven.home>
</systemPropertyVariables>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>


</project>
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
package io.javaoperatorsdk.quarkus.it;

import com.fasterxml.jackson.annotation.JsonProperty;
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
import io.javaoperatorsdk.operator.api.config.RetryConfiguration;
import java.util.Set;
import javax.inject.Inject;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
Expand All @@ -22,8 +25,64 @@ public boolean getController(@PathParam("name") String name) {

@GET
@Path("{name}/config")
public ControllerConfiguration getConfig(@PathParam("name") String name) {
final var config = configurationService.getConfigurationFor(controller);
return name.equals(config.getName()) ? config : null;
public JSONControllerConfiguration getConfig(@PathParam("name") String name) {
var config = configurationService.getConfigurationFor(controller);
if (config == null) {
return null;
}
return name.equals(config.getName()) ? new JSONControllerConfiguration(config) : null;
}

static class JSONControllerConfiguration {
private final ControllerConfiguration conf;

public JSONControllerConfiguration(ControllerConfiguration conf) {
this.conf = conf;
}

public String getName() {
return conf.getName();
}

@JsonProperty("crdName")
public String getCRDName() {
return conf.getCRDName();
}

public String getFinalizer() {
return conf.getFinalizer();
}

public boolean isGenerationAware() {
return conf.isGenerationAware();
}

public String getCustomResourceClass() {
return conf.getCustomResourceClass().getCanonicalName();
}

public String getAssociatedControllerClassName() {
return conf.getAssociatedControllerClassName();
}

public String getDoneableClass() {
return conf.getDoneableClass().getCanonicalName();
}

public boolean isClusterScoped() {
return conf.isClusterScoped();
}

public Set<String> getNamespaces() {
return conf.getNamespaces();
}

public boolean watchAllNamespaces() {
return conf.watchAllNamespaces();
}

public RetryConfiguration getRetryConfiguration() {
return conf.getRetryConfiguration();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package io.javaoperatorsdk.quarkus.it;

import io.quarkus.test.junit.NativeImageTest;

@NativeImageTest
public class NativeQuarkusExtensionProcessorIT extends QuarkusExtensionProcessorTest {}