Skip to content

Commit

Permalink
Fix fabric8io#1019: Custom Liveness/Readiness probes are not being cr…
Browse files Browse the repository at this point in the history
…eated

Added CustomProbeEnricher for adding probes via XML config
  • Loading branch information
rohanKanojia committed Nov 28, 2018
1 parent 2f95153 commit 26d7d2f
Show file tree
Hide file tree
Showing 8 changed files with 214 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ After this we will switch probably to real [Semantic Versioning 2.0.0](http://se

### 4.0.0-M2-SNAPSHOT
* Fix 1326: Fixes overridding of Selector Label by the project enrichers entries.
* Fix 1019: Custom liveness/readiness probes are not being created

### 3.5-SNAPSHOT
* Fix 1021: Avoids empty deployment selector value in generated yaml resource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ public Builder withConfigMap(ConfigMap configMap) {
return this;
}

public Builder withLiveness(ProbeConfig liveness) {
config.liveness = liveness;
return this;
}

public Builder withReadiness(ProbeConfig readiness) {
config.readiness = readiness;
return this;
}

public ResourceConfig build() {
return config;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,11 @@ private HTTPGetAction getHTTPGetAction(String getUrl) {
}
try {
URL url = new URL(getUrl);
return new HTTPGetAction(url.getHost(),
null /* headers */,
url.getPath(),
new IntOrString(url.getPort()),
url.getProtocol());
return new HTTPGetAction(url.getHost(),
null /* headers */,
url.getPath(),
new IntOrString(url.getPort()),
url.getProtocol().toUpperCase());
} catch (MalformedURLException e) {
throw new IllegalArgumentException("Invalid URL " + getUrl + " given for HTTP GET readiness check");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public void getHTTPProbeWithHTTPURLTest() {
assertEquals(null,probe.getHttpGet().getHttpHeaders());
assertEquals("/healthz",probe.getHttpGet().getPath());
assertEquals(8080,probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("http",probe.getHttpGet().getScheme());
assertEquals("HTTP",probe.getHttpGet().getScheme());
assertNull(probe.getExec());
assertNull(probe.getTcpSocket());
}
Expand Down Expand Up @@ -199,7 +199,7 @@ public void getTCPProbeWithHTTPURLAndPortTest() {
assertEquals(null,probe.getHttpGet().getHttpHeaders());
assertEquals("/healthz",probe.getHttpGet().getPath());
assertEquals(8080,probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("http",probe.getHttpGet().getScheme());
assertEquals("HTTP",probe.getHttpGet().getScheme());
}

@Test
Expand Down Expand Up @@ -265,7 +265,7 @@ public void getTCPWithHTTPURLAndWithoutPort() {
assertEquals(null,probe.getHttpGet().getHttpHeaders());
assertEquals("/healthz",probe.getHttpGet().getPath());
assertEquals(8080,probe.getHttpGet().getPort().getIntVal().intValue());
assertEquals("http",probe.getHttpGet().getScheme());
assertEquals("HTTP",probe.getHttpGet().getScheme());
}

@Test
Expand Down Expand Up @@ -293,4 +293,4 @@ public void getTCPProbeWithInvalidURLTest() {

probe = probeHandler.getProbe(probeConfig);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
/**
* Copyright 2016 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/

package io.fabric8.maven.enricher.standard;

import io.fabric8.kubernetes.api.builder.TypedVisitor;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.Probe;
import io.fabric8.maven.core.config.ProbeConfig;
import io.fabric8.maven.core.config.ResourceConfig;
import io.fabric8.maven.core.handler.ProbeHandler;
import io.fabric8.maven.enricher.api.BaseEnricher;
import io.fabric8.maven.enricher.api.MavenEnricherContext;

import java.util.NoSuchElementException;

public class CustomProbeEnricher extends BaseEnricher {
public CustomProbeEnricher(MavenEnricherContext buildContext) {
super(buildContext, "fmp-customprobe");
}

@Override
public void addMissingResources(KubernetesListBuilder builder) {
builder.accept(new TypedVisitor<ContainerBuilder>() {
@Override
public void visit(ContainerBuilder containerBuilder) {
try {
ResourceConfig resourceConfig = getConfiguration().getResource().get();

containerBuilder.withReadinessProbe(getProbe(resourceConfig.getReadiness()));
containerBuilder.withLivenessProbe(getProbe(resourceConfig.getLiveness()));
} catch (NoSuchElementException ex) {
// In this case resource is not being configured for plugin, let's just ignore.
}
}
});
}

private Probe getProbe(ProbeConfig pc) {
ProbeHandler probeHandler = new ProbeHandler();
if(pc != null) {
return probeHandler.getProbe(pc);
}
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,6 @@ io.fabric8.maven.enricher.standard.openshift.RouteEnricher

# Add an "expose" label to every service (TODO: Combine this with a Route/Ingress enricher)
io.fabric8.maven.enricher.standard.openshift.ExposeEnricher

# Add custom liveliness/readiness probes to every container via XML config
io.fabric8.maven.enricher.standard.CustomProbeEnricher
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
/**
* Copyright 2016 Red Hat, Inc.
*
* Red Hat licenses this file to you under the Apache License, version
* 2.0 (the "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package io.fabric8.maven.enricher.standard;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.jayway.jsonpath.matchers.JsonPathMatchers;
import io.fabric8.kubernetes.api.model.Container;
import io.fabric8.kubernetes.api.model.ContainerBuilder;
import io.fabric8.kubernetes.api.model.ContainerPortBuilder;
import io.fabric8.kubernetes.api.model.KubernetesList;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.PodTemplateBuilder;
import io.fabric8.maven.core.config.ProbeConfig;
import io.fabric8.maven.core.config.ProcessorConfig;
import io.fabric8.maven.core.config.ResourceConfig;
import io.fabric8.maven.core.model.Configuration;
import io.fabric8.maven.core.util.ResourceUtil;
import io.fabric8.maven.docker.config.ImageConfiguration;
import io.fabric8.maven.enricher.api.MavenEnricherContext;
import mockit.Expectations;
import mockit.Mocked;
import org.hamcrest.Matchers;
import org.junit.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.TreeMap;

import static org.junit.Assert.assertThat;

public class CustomProbeEnricherTest {
@Mocked
private MavenEnricherContext context;

@Mocked
ImageConfiguration imageConfiguration;

@Test
public void testReadinessProbeEnrichment() throws JsonProcessingException {
final TreeMap controllerConfig = new TreeMap();
controllerConfig.put("type", "LoadBalancer");
ResourceConfig resourceConfig = new ResourceConfig.Builder()
.withReadiness(new ProbeConfig.Builder().getUrl("http://192.168.42.20:8443/").build())
.build();

setupExpectations(controllerConfig, resourceConfig);

// Enrich
CustomProbeEnricher enricher = new CustomProbeEnricher(context);
KubernetesListBuilder builder = getPodTemplateList();
enricher.addMissingResources(builder);

// Validate that the generated resource contains
KubernetesList list = builder.build();

String json = ResourceUtil.toJson(list.getItems().get(0));
assertThat(json, JsonPathMatchers.isJson());
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].readinessProbe.httpGet.host", Matchers.equalTo("192.168.42.20")));
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].readinessProbe.httpGet.port", Matchers.equalTo(8443)));
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].readinessProbe.httpGet.path", Matchers.equalTo("/")));
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].readinessProbe.httpGet.scheme", Matchers.equalTo("HTTP")));
}

@Test
public void testLivenessProbeEnrichment() throws JsonProcessingException {
final TreeMap controllerConfig = new TreeMap();
controllerConfig.put("type", "LoadBalancer");
ResourceConfig resourceConfig = new ResourceConfig.Builder()
.withLiveness(new ProbeConfig.Builder().initialDelaySeconds(5).exec("cat /tmp/probe").build())
.build();

setupExpectations(controllerConfig, resourceConfig);

// Enrich
CustomProbeEnricher enricher = new CustomProbeEnricher(context);
KubernetesListBuilder builder = getPodTemplateList();
enricher.addMissingResources(builder);

// Validate that the generated resources contain desired enrichments
KubernetesList list = builder.build();

String json = ResourceUtil.toJson(list.getItems().get(0));
assertThat(json, JsonPathMatchers.isJson());
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].livenessProbe.initialDelaySeconds", Matchers.equalTo(5)));
assertThat(json, JsonPathMatchers.hasJsonPath("$.template.spec.containers[0].livenessProbe.exec.command[0]", Matchers.equalTo("cat")));
}

private KubernetesListBuilder getPodTemplateList() {
Container container = new ContainerBuilder()
.withName("test-port-enricher")
.withImage("test-image")
.withPorts(new ContainerPortBuilder().withContainerPort(80).withProtocol("TCP").build())
.build();
PodTemplateBuilder ptb = new PodTemplateBuilder()
.withNewMetadata().withName("test-pod")
.endMetadata()
.withNewTemplate()
.withNewSpec()
.withContainers(container)
.endSpec()
.endTemplate();
return new KubernetesListBuilder().addToPodTemplateItems(ptb.build());
}

private void setupExpectations(final TreeMap controllerConfig, ResourceConfig resourceConfig) {
new Expectations() {{

Configuration config = new Configuration.Builder()
.images(Arrays.asList(imageConfiguration))
.processorConfig(new ProcessorConfig(null, null, Collections.singletonMap("fmp-customprobe", controllerConfig)))
.resource(resourceConfig).build();

context.getConfiguration();
result = config;
}};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
- fmp-remove-build-annotations
- fmp-volume-permission
- fmp-configmap-file
- fmp-customprobe

# Route exposure
- fmp-openshift-service-expose
Expand Down

0 comments on commit 26d7d2f

Please sign in to comment.