Skip to content
This repository was archived by the owner on Jun 19, 2024. It is now read-only.

Commit 7a15adc

Browse files
Merge pull request #1292 from nicolaferraro/master
PR merged! Thanks!
2 parents b6a8f02 + efc9739 commit 7a15adc

File tree

7 files changed

+463
-6
lines changed

7 files changed

+463
-6
lines changed

CHANGELOG.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,11 @@ We use semantic versioning in some slight variation until our feature set has st
99
* The `PATCH_LEVEL` is used for regular CD releases which add new features and bug fixes.
1010

1111
After this we will switch probably to real [Semantic Versioning 2.0.0](http://semver.org/)
12-
###3.5.40
13-
* Feature 1293: Added support to create pullSecret in buildConfig when pulling from private registry in Openshift.
1412

1513
###3.5.40
1614
* Feature 1264: Added `osio` profile, with enricher to apply OpenShift.io space labels to resources
15+
* Feature 1291: Added ImageStream triggers for StatefulSets, ReplicaSets and DaemonSets
16+
* Feature 1293: Added support to create pullSecret in buildConfig when pulling from private registry in Openshift.
1717
* Fix 1265: WildFly Swarm health check enricher now supports detecting MicroProfile Health
1818
* Fix 1298: WildFly Swarm was renamed to Thorntail
1919

core/src/main/java/io/fabric8/maven/core/util/JSONUtil.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,17 @@
3030
*/
3131
public class JSONUtil {
3232

33+
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
34+
35+
public static ObjectMapper mapper() {
36+
return OBJECT_MAPPER;
37+
}
38+
3339
public static boolean equals(JSONObject first, JSONObject second) {
34-
final ObjectMapper mapper = new ObjectMapper();
3540

3641
try {
37-
final JsonNode tree1 = mapper.readTree(first.toString());
38-
final JsonNode tree2 = mapper.readTree(second.toString());
42+
final JsonNode tree1 = OBJECT_MAPPER.readTree(first.toString());
43+
final JsonNode tree2 = OBJECT_MAPPER.readTree(second.toString());
3944
return tree1.equals(tree2);
4045
} catch (IOException e) {
4146
return false;

doc/src/main/asciidoc/inc/_enricher.adoc

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,9 @@ fabric8-maven-plugin comes with a set of enrichers which are enabled by default.
9696

9797
| <<fmp-revision-history-enricher>>
9898
| Add revision history limit (https://kubernetes.io/docs/concepts/workloads/controllers/deployment/#revision-history-limit[Kubernetes doc]) as a deployment spec property to the Kubernetes/OpenShift resources.
99+
100+
| <<fmp-triggers-annotation>>
101+
| Add ImageStreamTag change triggers on Kubernetes resources such as StatefulSets, ReplicaSets and DaemonSets using the `image.openshift.io/triggers` annotation.
99102
|===
100103

101104
[[enrichers-standard]]
@@ -759,6 +762,26 @@ metadata:
759762
...
760763
----
761764

765+
[[fmp-triggers-annotation]]
766+
==== fmp-triggers-annotation
767+
768+
This enricher adds ImageStreamTag change triggers on Kubernetes resources that support the `image.openshift.io/triggers` annotation, such as StatefulSets, ReplicaSets and DaemonSets.
769+
770+
The trigger is added to all containers that apply, but can be restricted to a limited set of containers using the following configuration:
771+
772+
[source,xml]
773+
----
774+
...
775+
<enricher>
776+
<config>
777+
<fmp-triggers-annotation>
778+
<containers>container-name-1,c2</containers>
779+
</fmp-triggers-annotation>
780+
</config>
781+
</enricher>
782+
...
783+
----
784+
762785
== Enricher API
763786

764787
_howto write your own enricher and install them_
Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
/*
2+
* Copyright 2016 Red Hat, Inc.
3+
*
4+
* Red Hat licenses this file to you under the Apache License, version
5+
* 2.0 (the "License"); you may not use this file except in compliance
6+
* with the License. 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
13+
* implied. See the License for the specific language governing
14+
* permissions and limitations under the License.
15+
*/
16+
17+
package io.fabric8.maven.enricher.standard;
18+
19+
import com.fasterxml.jackson.core.JsonProcessingException;
20+
import io.fabric8.kubernetes.api.builder.TypedVisitor;
21+
import io.fabric8.kubernetes.api.builder.Visitable;
22+
import io.fabric8.kubernetes.api.builder.VisitableBuilder;
23+
import io.fabric8.kubernetes.api.model.Container;
24+
import io.fabric8.kubernetes.api.model.ContainerBuilder;
25+
import io.fabric8.kubernetes.api.model.HasMetadata;
26+
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
27+
import io.fabric8.kubernetes.api.model.ObjectMeta;
28+
import io.fabric8.kubernetes.api.model.ObjectMetaBuilder;
29+
import io.fabric8.kubernetes.api.model.extensions.DaemonSet;
30+
import io.fabric8.kubernetes.api.model.extensions.DaemonSetBuilder;
31+
import io.fabric8.kubernetes.api.model.extensions.ReplicaSet;
32+
import io.fabric8.kubernetes.api.model.extensions.ReplicaSetBuilder;
33+
import io.fabric8.kubernetes.api.model.extensions.StatefulSet;
34+
import io.fabric8.kubernetes.api.model.extensions.StatefulSetBuilder;
35+
import io.fabric8.maven.core.util.Configs;
36+
import io.fabric8.maven.core.util.JSONUtil;
37+
import io.fabric8.maven.docker.util.ImageName;
38+
import io.fabric8.maven.enricher.api.BaseEnricher;
39+
import io.fabric8.maven.enricher.api.EnricherContext;
40+
import io.fabric8.openshift.api.model.ImageChangeTrigger;
41+
import io.fabric8.openshift.api.model.ImageChangeTriggerBuilder;
42+
43+
import java.util.*;
44+
45+
/**
46+
* This adds a `image.openshift.io/triggers` tag to all kubernetes resources in order to make them run on Openshift when using ImageStreams.
47+
*
48+
* @author nicola
49+
* @since 10/05/18
50+
*/
51+
public class TriggersAnnotationEnricher extends BaseEnricher {
52+
53+
private static final String TRIGGERS_ANNOTATION = "image.openshift.io/triggers";
54+
55+
// Available configuration keys
56+
private enum Config implements Configs.Key {
57+
58+
/**
59+
* Comma-separated list of container names that should be enriched (default all that apply)
60+
*/
61+
containers;
62+
63+
protected String d; public String def() {
64+
return d;
65+
}
66+
}
67+
68+
69+
public TriggersAnnotationEnricher(EnricherContext buildContext) {
70+
super(buildContext, "fmp-triggers-annotation");
71+
}
72+
73+
@Override
74+
public void adapt(KubernetesListBuilder builder) {
75+
76+
builder.accept(new TypedVisitor<StatefulSetBuilder>() {
77+
@Override
78+
public void visit(StatefulSetBuilder o) {
79+
StatefulSet s = o.build();
80+
if (canWriteTriggers(s)) {
81+
o.withMetadata(getMetaEnrichedWithTriggers(s.getMetadata(), o));
82+
}
83+
}
84+
});
85+
86+
builder.accept(new TypedVisitor<ReplicaSetBuilder>() {
87+
@Override
88+
public void visit(ReplicaSetBuilder o) {
89+
ReplicaSet s = o.build();
90+
if (canWriteTriggers(s)) {
91+
o.withMetadata(getMetaEnrichedWithTriggers(s.getMetadata(), o));
92+
}
93+
}
94+
});
95+
96+
builder.accept(new TypedVisitor<DaemonSetBuilder>() {
97+
@Override
98+
public void visit(DaemonSetBuilder o) {
99+
DaemonSet s = o.build();
100+
if (canWriteTriggers(s)) {
101+
o.withMetadata(getMetaEnrichedWithTriggers(s.getMetadata(), o));
102+
}
103+
}
104+
});
105+
106+
}
107+
108+
protected ObjectMeta getMetaEnrichedWithTriggers(ObjectMeta meta, VisitableBuilder<?, ?> o) {
109+
ObjectMetaBuilder metaBuilder;
110+
if (meta != null) {
111+
metaBuilder = new ObjectMetaBuilder(meta);
112+
} else {
113+
metaBuilder = new ObjectMetaBuilder();
114+
}
115+
116+
return metaBuilder
117+
.addToAnnotations(TRIGGERS_ANNOTATION, createAnnotation(o))
118+
.build();
119+
}
120+
121+
protected boolean canWriteTriggers(HasMetadata res) {
122+
return res.getMetadata() == null ||
123+
res.getMetadata().getAnnotations() == null ||
124+
!res.getMetadata().getAnnotations().containsKey(TRIGGERS_ANNOTATION);
125+
}
126+
127+
protected String createAnnotation(Visitable<?> builder) {
128+
final List<ImageChangeTrigger> triggerList = new ArrayList<>();
129+
builder.accept(new TypedVisitor<ContainerBuilder>() {
130+
@Override
131+
public void visit(ContainerBuilder cb) {
132+
Container container = cb.build();
133+
String containerName = container.getName();
134+
String containerImage = container.getImage();
135+
ImageName image = new ImageName(containerImage);
136+
if (isContainerAllowed(containerName) && image.getRegistry() == null && image.getUser() == null) {
137+
// Imagestreams used as trigger are in the same namespace
138+
String tag = image.getTag() != null ? image.getTag() : "latest";
139+
140+
ImageChangeTrigger trigger = new ImageChangeTriggerBuilder()
141+
.withNewFrom()
142+
.withKind("ImageStreamTag")
143+
.withName(image.getSimpleName() + ":" + tag)
144+
.endFrom()
145+
.build();
146+
147+
trigger.setAdditionalProperty("fieldPath", "spec.template.spec.containers[?(@.name==\"" + containerName + "\")].image");
148+
triggerList.add(trigger);
149+
}
150+
}
151+
});
152+
153+
try {
154+
return JSONUtil.mapper().writeValueAsString(triggerList);
155+
} catch (JsonProcessingException e) {
156+
getLog().error("Error while creating ImageStreamTag triggers for Kubernetes resources: %s", e);
157+
return "[]";
158+
}
159+
}
160+
161+
protected boolean isContainerAllowed(String containerName) {
162+
String namesStr = this.getConfig(Config.containers);
163+
Set<String> allowedNames = new HashSet<>();
164+
if (namesStr != null) {
165+
for (String name : namesStr.split(",")) {
166+
allowedNames.add(name.trim());
167+
}
168+
}
169+
170+
return allowedNames.isEmpty() || allowedNames.contains(containerName);
171+
}
172+
173+
}

enricher/standard/src/main/resources/META-INF/fabric8/enricher-default

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,3 +63,6 @@ io.fabric8.maven.enricher.standard.DockerRegistrySecretEnricher
6363

6464
# Add an enricher for adding revision history limit for deployment resources
6565
io.fabric8.maven.enricher.standard.RevisionHistoryEnricher
66+
67+
# Add an enricher for adding trigger annotations to Kubernetes resources
68+
io.fabric8.maven.enricher.standard.TriggersAnnotationEnricher

0 commit comments

Comments
 (0)