Skip to content

Commit 4e3c62f

Browse files
authored
feat: allow loading resources as builders (#1335)
1 parent a55fbcb commit 4e3c62f

File tree

4 files changed

+73
-0
lines changed

4 files changed

+73
-0
lines changed
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
2+
package io.javaoperatorsdk.operator;
3+
4+
import java.lang.reflect.Constructor;
5+
import java.lang.reflect.InvocationTargetException;
6+
import java.lang.reflect.Method;
7+
8+
public final class BuilderUtils {
9+
10+
// prevent instantiation of util class
11+
private BuilderUtils() {}
12+
13+
public static final <T, B> B newBuilder(Class<B> builderType, T item) {
14+
Class<T> builderTargetType = builderTargetType(builderType);
15+
try {
16+
Constructor<B> constructor = builderType.getDeclaredConstructor(builderTargetType);
17+
return constructor.newInstance(item);
18+
} catch (NoSuchMethodException | SecurityException | InstantiationException
19+
| IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
20+
throw new OperatorException(
21+
"Failied to instantiate builder: " + builderType.getCanonicalName() + " using: " + item,
22+
e);
23+
}
24+
}
25+
26+
public static final <T, B> Class<T> builderTargetType(Class<B> builderType) {
27+
try {
28+
Method method = builderType.getDeclaredMethod("build");
29+
return (Class<T>) method.getReturnType();
30+
} catch (NoSuchMethodException | SecurityException e) {
31+
throw new OperatorException(
32+
"Failied to determine target type for builder: " + builderType.getCanonicalName(), e);
33+
}
34+
}
35+
}

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/ReconcilerUtils.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import java.util.regex.Pattern;
1111
import java.util.stream.Collectors;
1212

13+
import io.fabric8.kubernetes.api.builder.Builder;
1314
import io.fabric8.kubernetes.api.model.HasMetadata;
1415
import io.fabric8.kubernetes.client.KubernetesClientException;
1516
import io.fabric8.kubernetes.client.utils.Serialization;
@@ -114,6 +115,10 @@ public static Object setSpec(HasMetadata resource, Object spec) {
114115

115116
public static <T> T loadYaml(Class<T> clazz, Class loader, String yaml) {
116117
try (InputStream is = loader.getResourceAsStream(yaml)) {
118+
if (Builder.class.isAssignableFrom(clazz)) {
119+
return BuilderUtils.newBuilder(clazz,
120+
Serialization.unmarshal(is, BuilderUtils.builderTargetType(clazz)));
121+
}
117122
return Serialization.unmarshal(is, clazz);
118123
} catch (IOException ex) {
119124
throw new IllegalStateException("Cannot find yaml on classpath: " + yaml);

operator-framework-core/src/test/java/io/javaoperatorsdk/operator/ReconcilerUtilsTest.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,14 @@
22

33
import org.junit.jupiter.api.Test;
44

5+
import io.fabric8.kubernetes.api.model.ContainerBuilder;
56
import io.fabric8.kubernetes.api.model.HasMetadata;
67
import io.fabric8.kubernetes.api.model.Namespaced;
78
import io.fabric8.kubernetes.api.model.Pod;
89
import io.fabric8.kubernetes.api.model.PodSpec;
910
import io.fabric8.kubernetes.api.model.PodTemplateSpec;
1011
import io.fabric8.kubernetes.api.model.apps.Deployment;
12+
import io.fabric8.kubernetes.api.model.apps.DeploymentBuilder;
1113
import io.fabric8.kubernetes.api.model.apps.DeploymentSpec;
1214
import io.fabric8.kubernetes.client.CustomResource;
1315
import io.fabric8.kubernetes.client.KubernetesClientException;
@@ -88,6 +90,16 @@ void setsSpecWithReflection() {
8890
assertThat(deployment.getSpec().getReplicas()).isEqualTo(1);
8991
}
9092

93+
@Test
94+
void loadYamlAsBuilder() {
95+
DeploymentBuilder builder =
96+
ReconcilerUtils.loadYaml(DeploymentBuilder.class, getClass(), "deployment.yaml");
97+
builder.accept(ContainerBuilder.class, c -> c.withImage("my-image"));
98+
99+
Deployment deployment = builder.editMetadata().withName("my-deployment").and().build();
100+
assertThat(deployment.getMetadata().getName()).isEqualTo("my-deployment");
101+
}
102+
91103
private Deployment createTestDeployment() {
92104
Deployment deployment = new Deployment();
93105
deployment.setSpec(new DeploymentSpec());
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
2+
kind: Deployment
3+
metadata:
4+
name: ""
5+
spec:
6+
progressDeadlineSeconds: 600
7+
revisionHistoryLimit: 10
8+
selector:
9+
matchLabels:
10+
app: "test"
11+
replicas: 1
12+
template:
13+
metadata:
14+
labels:
15+
app: "test"
16+
spec:
17+
containers:
18+
- name: nginx
19+
image: nginx:1.17.0
20+
ports:
21+
- containerPort: 80

0 commit comments

Comments
 (0)