Skip to content

Commit 3e7c7e3

Browse files
authored
Admission Webhook Sample (#69)
Signed-off-by: Attila Mészáros <[email protected]>
1 parent 74e8028 commit 3e7c7e3

File tree

15 files changed

+278
-16
lines changed

15 files changed

+278
-16
lines changed

.github/workflows/pr.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,5 +56,5 @@ jobs:
5656
- name: Run E2E tests
5757
run: |
5858
eval $(minikube -p minikube docker-env)
59-
./mvnw clean install -DskipTests -Dquarkus.container-image.build=true -Dquarkus.kubernetes.namespace=default
59+
./mvnw clean install -DskipTests -Dquarkus.container-image.build=true
6060
./mvnw test -Pe2e-tests

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ jobs:
2424
QUARKUS_CONTAINER_IMAGE_PASSWORD: ${{ secrets.GITHUB_TOKEN }}
2525
run: |
2626
./mvnw versions:set -DnewVersion="${RELEASE_VERSION}" versions:commit
27-
./mvnw clean install -DskipTests -Dquarkus.container-image.build=true -Dquarkus.kubernetes.namespace=default -Dquarkus.container-image.push=true
27+
./mvnw clean install -DskipTests -Dquarkus.container-image.build=true -Dquarkus.container-image.push=true
2828
./mvnw ${MAVEN_ARGS} -q build-helper:parse-version versions:set -DnewVersion=\${parsedVersion.majorVersion}.\${parsedVersion.minorVersion}.\${parsedVersion.nextIncrementalVersion}-SNAPSHOT versions:commit
2929
git config --local user.email "[email protected]"
3030
git config --local user.name "GitHub Action"

src/main/java/io/csviri/operator/resourceglue/conditions/PodsReadyCondition.java renamed to src/main/java/io/csviri/operator/resourceglue/conditions/ReadyCondition.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,13 @@
77
import io.javaoperatorsdk.operator.api.reconciler.dependent.DependentResource;
88
import io.javaoperatorsdk.operator.processing.dependent.workflow.Condition;
99

10-
public class PodsReadyCondition<R extends HasMetadata> implements Condition<R, Glue> {
10+
public class ReadyCondition<R extends HasMetadata> implements Condition<R, Glue> {
1111

1212
private final Readiness readiness = Readiness.getInstance();
1313

1414
private final boolean negated;
1515

16-
public PodsReadyCondition(boolean negated) {
16+
public ReadyCondition(boolean negated) {
1717
this.negated = negated;
1818
}
1919

src/main/java/io/csviri/operator/resourceglue/customresource/glue/condition/ConditionSpec.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
use = JsonTypeInfo.Id.NAME,
88
property = "type")
99
@JsonSubTypes({
10-
@JsonSubTypes.Type(value = PodsReadyConditionSpec.class, name = "PodsReady"),
10+
@JsonSubTypes.Type(value = ReadyConditionSpec.class, name = "ReadyCondition"),
1111
@JsonSubTypes.Type(value = JavaScriptConditionSpec.class, name = "JSCondition")
1212
})
1313
public class ConditionSpec {
Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
package io.csviri.operator.resourceglue.customresource.glue.condition;
22

3-
public class PodsReadyConditionSpec extends ConditionSpec {
3+
public class ReadyConditionSpec extends ConditionSpec {
44

55
private final boolean negated;
66

7-
public PodsReadyConditionSpec(boolean negated) {
7+
public ReadyConditionSpec(boolean negated) {
88
this.negated = negated;
99
}
1010

11-
public PodsReadyConditionSpec() {
11+
public ReadyConditionSpec() {
1212
this(false);
1313
}
1414

src/main/java/io/csviri/operator/resourceglue/reconciler/glue/GlueReconciler.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@
77

88
import io.csviri.operator.resourceglue.Utils;
99
import io.csviri.operator.resourceglue.conditions.JavaScripCondition;
10-
import io.csviri.operator.resourceglue.conditions.PodsReadyCondition;
10+
import io.csviri.operator.resourceglue.conditions.ReadyCondition;
1111
import io.csviri.operator.resourceglue.customresource.glue.DependentResourceSpec;
1212
import io.csviri.operator.resourceglue.customresource.glue.Glue;
1313
import io.csviri.operator.resourceglue.customresource.glue.condition.ConditionSpec;
1414
import io.csviri.operator.resourceglue.customresource.glue.condition.JavaScriptConditionSpec;
15-
import io.csviri.operator.resourceglue.customresource.glue.condition.PodsReadyConditionSpec;
15+
import io.csviri.operator.resourceglue.customresource.glue.condition.ReadyConditionSpec;
1616
import io.csviri.operator.resourceglue.dependent.GCGenericDependentResource;
1717
import io.csviri.operator.resourceglue.dependent.GenericDependentResource;
1818
import io.csviri.operator.resourceglue.dependent.GenericResourceDiscriminator;
@@ -148,10 +148,11 @@ private void createAndAddDependentToWorkflow(Glue primary, Context<Glue> context
148148
Map<String, GenericDependentResource> genericDependentResourceMap,
149149
WorkflowBuilder<Glue> builder, boolean leafDependent) {
150150

151+
// todo test processing ns not as template
151152
// todo test processing ns as template
152153
// name can reference related resources todo doc
153154
var targetNamespace = Utils.getNamespace(spec).map(ns -> genericTemplateHandler
154-
.processTemplate(Utils.getName(spec), primary, context));
155+
.processTemplate(ns, primary, context));
155156
var resourceInSameNamespaceAsPrimary =
156157
targetNamespace.map(n -> n.trim().equals(primary.getMetadata().getNamespace().trim()))
157158
.orElse(true);
@@ -197,8 +198,8 @@ private static GenericDependentResource createDependentResource(DependentResourc
197198

198199
@SuppressWarnings({"rawtypes"})
199200
private Condition toCondition(ConditionSpec condition) {
200-
if (condition instanceof PodsReadyConditionSpec readyConditionSpec) {
201-
return new PodsReadyCondition(readyConditionSpec.isNegated());
201+
if (condition instanceof ReadyConditionSpec readyConditionSpec) {
202+
return new ReadyCondition(readyConditionSpec.isNegated());
202203
} else if (condition instanceof JavaScriptConditionSpec jsCondition) {
203204
return new JavaScripCondition(jsCondition.getScript());
204205
}

src/main/resources/application.properties

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ quarkus.jib.jvm-additional-arguments=-Dpolyglot.engine.WarnInterpreterOnly=false
99
# To inherit visibility from the repo
1010
quarkus.container-image.labels."org.opencontainers.image.source"=https://github.com/csviri/resource-glue-operator
1111
quarkus.container-image.labels."org.opencontainers.image.documentation"=https://github.com/csviri/resource-glue-operator?tab=readme-ov-file#documentation
12+
# Generate apply-able cluster role bindings
13+
quarkus.kubernetes.namespace=default

src/test/java/io/csviri/operator/resourceglue/TestUtils.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package io.csviri.operator.resourceglue;
22

33
import java.io.*;
4+
import java.net.URL;
45
import java.nio.charset.StandardCharsets;
56
import java.util.Arrays;
67
import java.util.List;
@@ -144,4 +145,11 @@ public static void applyAndWait(KubernetesClient client, InputStream is,
144145
applyAndWait(client, resources, transformer);
145146
}
146147

148+
public static void applyAndWait(KubernetesClient client, URL url) {
149+
try (InputStream is = url.openStream()) {
150+
applyAndWait(client, is);
151+
} catch (IOException e) {
152+
throw new RuntimeException(e);
153+
}
154+
}
147155
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
package io.csviri.operator.resourceglue.sample.mutation;
2+
3+
import java.net.MalformedURLException;
4+
import java.net.URI;
5+
import java.net.URISyntaxException;
6+
import java.time.Duration;
7+
8+
import org.junit.jupiter.api.BeforeEach;
9+
import org.junit.jupiter.api.Test;
10+
11+
import io.csviri.operator.resourceglue.TestUtils;
12+
import io.csviri.operator.resourceglue.customresource.glue.Glue;
13+
import io.csviri.operator.resourceglue.customresource.operator.GlueOperator;
14+
import io.fabric8.kubernetes.api.model.*;
15+
import io.fabric8.kubernetes.client.KubernetesClient;
16+
import io.fabric8.kubernetes.client.KubernetesClientBuilder;
17+
import io.fabric8.kubernetes.client.dsl.NonDeletingOperation;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
import static org.awaitility.Awaitility.await;
21+
22+
public class MutationWebhookDeploymentE2E {
23+
24+
public static final String TEST_POD_NAME = "testpod";
25+
private final KubernetesClient client = new KubernetesClientBuilder().build();
26+
27+
@BeforeEach
28+
void applyCRDs() throws MalformedURLException, URISyntaxException {
29+
TestUtils.applyCrd(client, Glue.class, GlueOperator.class);
30+
TestUtils.applyAndWait(client,
31+
new URI(
32+
"https://github.com/cert-manager/cert-manager/releases/download/v1.14.4/cert-manager.yaml")
33+
.toURL());
34+
TestUtils.applyAndWait(client, "target/kubernetes/kubernetes.yml");
35+
TestUtils.applyAndWait(client, "src/test/resources/sample/mutation/related.resource.yaml");
36+
}
37+
38+
@Test
39+
void testMutationHookDeployment() {
40+
client.resource(TestUtils.load("/sample/mutation/mutation.glue.yaml"))
41+
.createOr(NonDeletingOperation::update);
42+
43+
await().atMost(Duration.ofMinutes(5)).untilAsserted(() -> {
44+
var conf = client.admissionRegistration().v1().mutatingWebhookConfigurations()
45+
.withName("pod-mutating-webhook").get();
46+
var deployment = client.apps().deployments().withName("pod-mutating-hook").get();
47+
assertThat(conf).isNotNull();
48+
assertThat(deployment.getStatus().getReadyReplicas()).isGreaterThan(0);
49+
});
50+
51+
var pod = client.resource(testPod()).create();
52+
assertThat(pod.getMetadata().getAnnotations()).containsEntry("sample.annotation.present",
53+
"true");
54+
}
55+
56+
Pod testPod() {
57+
return new PodBuilder()
58+
.withNewMetadata()
59+
.withName(TEST_POD_NAME)
60+
.endMetadata()
61+
.withNewSpec()
62+
.withContainers(new ContainerBuilder()
63+
.withName("nginx")
64+
.withImage("nginx:1.14.2")
65+
.withPorts(new ContainerPortBuilder()
66+
.withContainerPort(80)
67+
.build())
68+
.build())
69+
.endSpec()
70+
.build();
71+
}
72+
73+
}

src/test/java/io/csviri/operator/resourceglue/sample/webpage/WebPageE2E.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ void applyCRDs() {
3030
}
3131

3232
@Test
33-
void testDeployment() {
33+
void testWebPageCRUDOperations() {
3434
client.resource(TestUtils.load("/sample/webpage/webpage.operator.yaml"))
3535
.createOr(NonDeletingOperation::update);
3636
var webPage = TestUtils.load("/sample/webpage/webpage.sample.yaml", WebPage.class);

0 commit comments

Comments
 (0)