Skip to content

Commit a4990c8

Browse files
committed
fix: support GraalVM native image for Fabric8 Spring Cloud Kubernetes
Remove @ConstructorBinding from ConfigMapConfigProperties and SecretsConfigProperties as it is not needed in this case. Register both classes in Fabric8RuntimeHints with INVOKE_DECLARED_CONSTRUCTORS to ensure GraalVM can construct them at runtime. Add unit tests for Fabric8RuntimeHints covering reflection hint registrations for Fabric8 client classes, Kubernetes API resources, and config properties. Signed-off-by: Abu Hena Mostafa Kamal <kamalcis@gmail.com>
1 parent ac9fd36 commit a4990c8

3 files changed

Lines changed: 88 additions & 4 deletions

File tree

spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/ConfigMapConfigProperties.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.Map;
2121

2222
import org.springframework.boot.context.properties.ConfigurationProperties;
23-
import org.springframework.boot.context.properties.bind.ConstructorBinding;
2423
import org.springframework.boot.context.properties.bind.DefaultValue;
2524

2625
/**
@@ -37,7 +36,6 @@ public final class ConfigMapConfigProperties extends SourceConfigProperties {
3736
*/
3837
public static final String PREFIX = "spring.cloud.kubernetes.config";
3938

40-
@ConstructorBinding
4139
public ConfigMapConfigProperties(@DefaultValue("true") boolean enabled, @DefaultValue List<Source> sources,
4240
@DefaultValue Map<String, String> labels, String name, String namespace, boolean useNameAsPrefix,
4341
@DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast,

spring-cloud-kubernetes-commons/src/main/java/org/springframework/cloud/kubernetes/commons/config/SecretsConfigProperties.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
import java.util.Map;
2121

2222
import org.springframework.boot.context.properties.ConfigurationProperties;
23-
import org.springframework.boot.context.properties.bind.ConstructorBinding;
2423
import org.springframework.boot.context.properties.bind.DefaultValue;
2524

2625
/**
@@ -38,7 +37,6 @@ public final class SecretsConfigProperties extends SourceConfigProperties {
3837
*/
3938
public static final String PREFIX = "spring.cloud.kubernetes.secrets";
4039

41-
@ConstructorBinding
4240
public SecretsConfigProperties(@DefaultValue("false") boolean enabled, @DefaultValue List<Source> sources,
4341
@DefaultValue Map<String, String> labels, String name, String namespace, boolean useNameAsPrefix,
4442
@DefaultValue("true") boolean includeProfileSpecificSources, boolean failFast,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
/*
2+
* Copyright 2013-present the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.cloud.kubernetes.fabric8;
18+
19+
import io.fabric8.kubernetes.api.model.ConfigMap;
20+
import io.fabric8.kubernetes.api.model.ConfigMapList;
21+
import io.fabric8.kubernetes.api.model.ObjectMeta;
22+
import io.fabric8.kubernetes.api.model.Secret;
23+
import io.fabric8.kubernetes.api.model.SecretList;
24+
import io.fabric8.kubernetes.client.Config;
25+
import io.fabric8.kubernetes.client.ConfigBuilder;
26+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
27+
import io.fabric8.kubernetes.client.impl.KubernetesClientImpl;
28+
import org.junit.jupiter.api.Test;
29+
30+
import org.springframework.aot.hint.RuntimeHints;
31+
import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
32+
import org.springframework.cloud.kubernetes.commons.config.ConfigMapConfigProperties;
33+
import org.springframework.cloud.kubernetes.commons.config.SecretsConfigProperties;
34+
35+
import static org.assertj.core.api.Assertions.assertThat;
36+
37+
/**
38+
* Tests for {@link Fabric8RuntimeHints}.
39+
*
40+
* @author Abu Hena Mostafa Kamal
41+
* @since 5.0.3
42+
*/
43+
class Fabric8RuntimeHintsTests {
44+
45+
private final Fabric8RuntimeHints hintsRegistrar = new Fabric8RuntimeHints();
46+
47+
@Test
48+
void fabric8ClientClassesShouldBeRegistered() {
49+
RuntimeHints hints = new RuntimeHints();
50+
hintsRegistrar.registerHints(hints, null);
51+
52+
assertThat(RuntimeHintsPredicates.reflection().onType(KubernetesClientImpl.class)).accepts(hints);
53+
assertThat(RuntimeHintsPredicates.reflection().onType(KubernetesClientBuilder.class)).accepts(hints);
54+
assertThat(RuntimeHintsPredicates.reflection().onType(Config.class)).accepts(hints);
55+
assertThat(RuntimeHintsPredicates.reflection().onType(ConfigBuilder.class)).accepts(hints);
56+
}
57+
58+
@Test
59+
void kubernetesResourcesShouldBeRegistered() {
60+
RuntimeHints hints = new RuntimeHints();
61+
hintsRegistrar.registerHints(hints, null);
62+
63+
assertThat(RuntimeHintsPredicates.reflection().onType(ConfigMap.class)).accepts(hints);
64+
assertThat(RuntimeHintsPredicates.reflection().onType(ConfigMapList.class)).accepts(hints);
65+
assertThat(RuntimeHintsPredicates.reflection().onType(ObjectMeta.class)).accepts(hints);
66+
assertThat(RuntimeHintsPredicates.reflection().onType(Secret.class)).accepts(hints);
67+
assertThat(RuntimeHintsPredicates.reflection().onType(SecretList.class)).accepts(hints);
68+
}
69+
70+
@Test
71+
void configPropertiesShouldBeRegistered() {
72+
RuntimeHints hints = new RuntimeHints();
73+
hintsRegistrar.registerHints(hints, null);
74+
75+
assertThat(RuntimeHintsPredicates.reflection().onType(ConfigMapConfigProperties.class)).accepts(hints);
76+
assertThat(RuntimeHintsPredicates.reflection().onType(SecretsConfigProperties.class)).accepts(hints);
77+
}
78+
79+
@Test
80+
void unrelatedClassesShouldNotBeRegistered() {
81+
RuntimeHints hints = new RuntimeHints();
82+
hintsRegistrar.registerHints(hints, null);
83+
84+
assertThat(RuntimeHintsPredicates.reflection().onType(String.class)).rejects(hints);
85+
assertThat(RuntimeHintsPredicates.reflection().onType(Integer.class)).rejects(hints);
86+
}
87+
88+
}

0 commit comments

Comments
 (0)