Skip to content

Commit 1905e27

Browse files
committed
Support overwrite values from existing sidecar containers
Related to #1196 (review)
1 parent 0d5da08 commit 1905e27

File tree

8 files changed

+248
-1
lines changed

8 files changed

+248
-1
lines changed

core/src/main/java/io/dekorate/kubernetes/decorator/AddInitContainerDecorator.java

+4
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ private void update(PodSpecBuilder podSpec, io.fabric8.kubernetes.api.model.Cont
5858
matching.withImage(resource.getImage());
5959
}
6060

61+
if (resource.getImagePullPolicy() != null) {
62+
matching.withImagePullPolicy(resource.getImagePullPolicy());
63+
}
64+
6165
if (resource.getWorkingDir() != null) {
6266
matching.withWorkingDir(resource.getWorkingDir());
6367
}

core/src/main/java/io/dekorate/kubernetes/decorator/AddSidecarDecorator.java

+55-1
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,10 @@
1818
import io.dekorate.doc.Description;
1919
import io.dekorate.kubernetes.adapter.ContainerAdapter;
2020
import io.dekorate.kubernetes.config.Container;
21+
import io.fabric8.kubernetes.api.model.ContainerBuilder;
2122
import io.fabric8.kubernetes.api.model.ObjectMeta;
2223
import io.fabric8.kubernetes.api.model.PodSpecBuilder;
24+
import io.fabric8.kubernetes.api.model.PodSpecFluent;
2325

2426
/**
2527
* A decorator that adds an init container to a pod template.
@@ -40,7 +42,59 @@ public AddSidecarDecorator(String deployment, Container container) {
4042

4143
@Override
4244
public void andThenVisit(PodSpecBuilder podSpec, ObjectMeta resourceMeta) {
43-
podSpec.addToContainers(ContainerAdapter.adapt(container));
45+
io.fabric8.kubernetes.api.model.Container resource = ContainerAdapter.adapt(container);
46+
if (podSpec.hasMatchingContainer(this::existsContainerByName)) {
47+
update(podSpec, resource);
48+
} else {
49+
add(podSpec, resource);
50+
}
51+
}
52+
53+
private void add(PodSpecBuilder podSpec, io.fabric8.kubernetes.api.model.Container resource) {
54+
podSpec.addToContainers(resource);
55+
}
56+
57+
private void update(PodSpecBuilder podSpec, io.fabric8.kubernetes.api.model.Container resource) {
58+
PodSpecFluent.ContainersNested<PodSpecBuilder> matching = podSpec.editMatchingContainer(this::existsContainerByName);
59+
60+
if (resource.getImage() != null) {
61+
matching.withImage(resource.getImage());
62+
}
63+
64+
if (resource.getImagePullPolicy() != null) {
65+
matching.withImagePullPolicy(resource.getImagePullPolicy());
66+
}
67+
68+
if (resource.getWorkingDir() != null) {
69+
matching.withWorkingDir(resource.getWorkingDir());
70+
}
71+
72+
if (resource.getCommand() != null && !resource.getCommand().isEmpty()) {
73+
matching.withCommand(resource.getCommand());
74+
}
75+
76+
if (resource.getArgs() != null && !resource.getArgs().isEmpty()) {
77+
matching.withArgs(resource.getArgs());
78+
}
79+
80+
if (resource.getReadinessProbe() != null) {
81+
matching.withReadinessProbe(resource.getReadinessProbe());
82+
}
83+
84+
if (resource.getLivenessProbe() != null) {
85+
matching.withLivenessProbe(resource.getLivenessProbe());
86+
}
87+
88+
matching.addAllToEnv(resource.getEnv());
89+
if (resource.getPorts() != null && !resource.getPorts().isEmpty()) {
90+
matching.withPorts(resource.getPorts());
91+
}
92+
93+
matching.endContainer();
94+
}
95+
96+
private boolean existsContainerByName(ContainerBuilder containerBuilder) {
97+
return containerBuilder.getName().equals(container.getName());
4498
}
4599

46100
public Class<? extends Decorator>[] after() {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
3+
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4+
<modelVersion>4.0.0</modelVersion>
5+
6+
<parent>
7+
<artifactId>dekorate-tests</artifactId>
8+
<groupId>io.dekorate</groupId>
9+
<version>3.6-SNAPSHOT</version>
10+
<relativePath>../</relativePath>
11+
</parent>
12+
13+
<groupId>io.dekorate</groupId>
14+
<artifactId>feat-overwrite-sidecar-containers</artifactId>
15+
<name>Dekorate :: Tests :: Annotations :: Allow to overwrite existing sidecar container</name>
16+
17+
<dependencies>
18+
<dependency>
19+
<groupId>io.dekorate</groupId>
20+
<artifactId>kubernetes-annotations</artifactId>
21+
<version>${project.version}</version>
22+
</dependency>
23+
<dependency>
24+
<groupId>io.dekorate</groupId>
25+
<artifactId>dekorate-spring-boot</artifactId>
26+
<version>${project.version}</version>
27+
</dependency>
28+
<dependency>
29+
<groupId>org.springframework.boot</groupId>
30+
<artifactId>spring-boot-starter-web</artifactId>
31+
<version>${version.spring-boot}</version>
32+
</dependency>
33+
34+
<!-- Testing -->
35+
<dependency>
36+
<groupId>org.junit.jupiter</groupId>
37+
<artifactId>junit-jupiter-api</artifactId>
38+
<version>${version.junit-jupiter}</version>
39+
<scope>test</scope>
40+
</dependency>
41+
<dependency>
42+
<groupId>org.junit.jupiter</groupId>
43+
<artifactId>junit-jupiter-engine</artifactId>
44+
<version>${version.junit-jupiter}</version>
45+
<scope>test</scope>
46+
</dependency>
47+
</dependencies>
48+
49+
<build>
50+
<resources>
51+
<resource>
52+
<directory>src/main/resources</directory>
53+
<filtering>true</filtering>
54+
</resource>
55+
</resources>
56+
<plugins>
57+
<plugin>
58+
<groupId>org.apache.maven.plugins</groupId>
59+
<artifactId>maven-surefire-plugin</artifactId>
60+
<inherited>true</inherited>
61+
<configuration>
62+
<useSystemClassLoader>false</useSystemClassLoader>
63+
</configuration>
64+
</plugin>
65+
<plugin>
66+
<groupId>org.springframework.boot</groupId>
67+
<artifactId>spring-boot-maven-plugin</artifactId>
68+
<version>${version.spring-boot}</version>
69+
</plugin>
70+
</plugins>
71+
</build>
72+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/**
2+
* Copyright 2018 The original 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+
* http://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+
package io.dekorate.annotationless;
17+
18+
import org.springframework.boot.SpringApplication;
19+
import org.springframework.boot.autoconfigure.SpringBootApplication;
20+
21+
@SpringBootApplication
22+
public class DemoApplication {
23+
24+
public static void main(String[] args) {
25+
SpringApplication.run(DemoApplication.class, args);
26+
}
27+
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/**
2+
* Copyright 2018 The original 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+
* http://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+
18+
package io.dekorate.annotationless;
19+
20+
import org.springframework.web.bind.annotation.RequestMapping;
21+
import org.springframework.web.bind.annotation.RestController;
22+
23+
@RestController
24+
public class HelloController {
25+
26+
private static final String HELLO = "hello world!";
27+
28+
@RequestMapping("/")
29+
public String hello() {
30+
return HELLO;
31+
}
32+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
dekorate.kubernetes.sidecars[0].name=foo
2+
dekorate.kubernetes.sidecars[1].name=foo
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright 2018 The original 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+
* http://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+
18+
package io.dekorate.example;
19+
20+
import static org.junit.jupiter.api.Assertions.assertEquals;
21+
import static org.junit.jupiter.api.Assertions.assertNotNull;
22+
import static org.junit.jupiter.api.Assertions.assertTrue;
23+
24+
import java.util.Optional;
25+
26+
import org.junit.jupiter.api.Test;
27+
28+
import io.dekorate.utils.Serialization;
29+
import io.fabric8.kubernetes.api.model.HasMetadata;
30+
import io.fabric8.kubernetes.api.model.KubernetesList;
31+
import io.fabric8.kubernetes.api.model.apps.Deployment;
32+
33+
public class FeatOverwriteSidecarContainersTest {
34+
35+
private static final String NAME = "feat-overwrite-sidecar-containers";
36+
37+
@Test
38+
public void shouldContainOnlyOneSidecarContainer() {
39+
KubernetesList list = Serialization
40+
.unmarshalAsList(getClass().getClassLoader().getResourceAsStream("META-INF/dekorate/kubernetes.yml"));
41+
assertNotNull(list);
42+
Deployment s = findFirst(list, Deployment.class).orElseThrow(() -> new IllegalStateException());
43+
assertEquals(NAME, s.getMetadata().getName());
44+
assertEquals(2, s.getSpec().getTemplate().getSpec().getContainers().size());
45+
assertTrue(s.getSpec().getTemplate().getSpec().getContainers().stream().anyMatch(c -> c.getName().equals("foo")));
46+
assertTrue(s.getSpec().getTemplate().getSpec().getContainers().stream().anyMatch(c -> c.getName().equals(NAME)));
47+
}
48+
49+
<T extends HasMetadata> Optional<T> findFirst(KubernetesList list, Class<T> t) {
50+
return (Optional<T>) list.getItems().stream()
51+
.filter(i -> t.isInstance(i))
52+
.findFirst();
53+
}
54+
}

tests/pom.xml

+1
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@
9696
<module>feat-openshift-secure-routes</module>
9797
<module>issue-knative-probes-helm</module>
9898
<module>feat-overwrite-init-containers</module>
99+
<module>feat-overwrite-sidecar-containers</module>
99100
</modules>
100101

101102
</project>

0 commit comments

Comments
 (0)