Skip to content

Commit

Permalink
fix: Add default /metrics path for prometheus.io/path annotation
Browse files Browse the repository at this point in the history
Signed-off-by: Marc Nuri <[email protected]>
  • Loading branch information
manusa committed Aug 19, 2020
1 parent fd86bc9 commit a0440eb
Show file tree
Hide file tree
Showing 4 changed files with 134 additions and 152 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ Usage:
* Fix #332: OpenShift build resources are deleted (as long as build config manifest is available)
* Fix #350: Prevents default docker configuration overwriting XML assembly configuration
* Fix #340: Exclude the main artifact from Docker build when Fat Jar is detected (JavaExecGenerator)
* Fix #341: JKube doesn't add ImageChange triggers in DC when merging from a deployment fragment
* Fix #341: JKube doesn't add ImageChange triggers in DC when merging from a deployment fragment
* Fix #326: Add default `/metrics` path for `prometheus.io/path` annotation
(Sort of [redundant](https://prometheus.io/docs/prometheus/latest/configuration/configuration/#scrape_config), this makes it explicit)

### 1.0.0-rc-1 (2020-07-23)
* Fix #252: Replace Quarkus Native Base image with ubi-minimal (same as in `Dockerfile.native`)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,36 +18,38 @@
import java.util.Map;
import java.util.stream.Collectors;

import io.fabric8.kubernetes.api.builder.TypedVisitor;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.common.Configs;
import org.eclipse.jkube.kit.common.util.MapUtil;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration;
import org.eclipse.jkube.kit.config.resource.PlatformMode;
import org.eclipse.jkube.kit.enricher.api.BaseEnricher;
import org.eclipse.jkube.kit.enricher.api.JKubeEnricherContext;

import io.fabric8.kubernetes.api.builder.TypedVisitor;
import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import lombok.AllArgsConstructor;
import lombok.Getter;
import org.apache.commons.lang3.StringUtils;

public class PrometheusEnricher extends BaseEnricher {

static final String ANNOTATION_PROMETHEUS_PORT = "prometheus.io/port";
static final String ANNOTATION_PROMETHEUS_SCRAPE = "prometheus.io/scrape";
static final String ANNOTATION_PROMETHEUS_PATH = "prometheus.io/path";
private static final String ANNOTATION_PROMETHEUS_PORT = "prometheus.io/port";
private static final String ANNOTATION_PROMETHEUS_SCRAPE = "prometheus.io/scrape";
private static final String ANNOTATION_PROMETHEUS_PATH = "prometheus.io/path";

static final String ENRICHER_NAME = "jkube-prometheus";
static final String PROMETHEUS_PORT = "9779";
private static final String ENRICHER_NAME = "jkube-prometheus";
private static final String PROMETHEUS_PORT = "9779";

@AllArgsConstructor
private enum Config implements Configs.Config {
PROMETHEUS_PORT("prometheusPort"),
PROMETHEUS_PATH("prometheusPath");
PROMETHEUS_PORT("prometheusPort", null),
PROMETHEUS_PATH("prometheusPath", "/metrics");

@Getter
protected String key;
@Getter
protected String defaultValue;
}

public PrometheusEnricher(JKubeEnricherContext buildContext) {
Expand All @@ -61,15 +63,10 @@ public void create(PlatformMode platformMode, KubernetesListBuilder builder) {
public void visit(ServiceBuilder serviceBuilder) {
String prometheusPort = findPrometheusPort();
if (StringUtils.isNotBlank(prometheusPort)) {

Map<String, String> annotations = new HashMap<>();
MapUtil.putIfAbsent(annotations, ANNOTATION_PROMETHEUS_PORT, prometheusPort);
MapUtil.putIfAbsent(annotations, ANNOTATION_PROMETHEUS_SCRAPE, "true");
String prometheusPath = getConfig(Config.PROMETHEUS_PATH);
if (StringUtils.isNotBlank(prometheusPath)) {
MapUtil.putIfAbsent(annotations, ANNOTATION_PROMETHEUS_PATH, prometheusPath);
}

final Map<String, String> annotations = new HashMap<>();
annotations.put(ANNOTATION_PROMETHEUS_PORT, prometheusPort);
annotations.put(ANNOTATION_PROMETHEUS_SCRAPE, "true");
annotations.put(ANNOTATION_PROMETHEUS_PATH, getConfig(Config.PROMETHEUS_PATH));
log.verbose("Adding prometheus.io annotations: %s",
annotations.entrySet()
.stream()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,146 +13,128 @@
*/
package org.eclipse.jkube.kit.enricher.specific;

import java.util.Arrays;
import java.util.Collections;
import java.util.Map;

import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration;
import org.eclipse.jkube.kit.config.image.ImageConfiguration;
import org.eclipse.jkube.kit.config.image.build.BuildConfiguration;
import org.eclipse.jkube.kit.config.resource.PlatformMode;
import org.eclipse.jkube.kit.config.resource.ProcessorConfig;
import org.eclipse.jkube.kit.enricher.api.JKubeEnricherContext;
import org.eclipse.jkube.kit.enricher.api.model.Configuration;

import io.fabric8.kubernetes.api.model.KubernetesListBuilder;
import io.fabric8.kubernetes.api.model.ServiceBuilder;
import mockit.Expectations;
import mockit.Mocked;
import org.junit.Before;
import org.junit.Test;

import static junit.framework.TestCase.assertNull;
import static org.junit.Assert.assertEquals;
import static org.assertj.core.api.Assertions.assertThat;

@SuppressWarnings("unused")
public class PrometheusEnricherTest {

@Mocked
private JKubeEnricherContext context;
@Mocked
ImageConfiguration imageConfiguration;

@Test
public void testCustomPrometheusPort() {
final ProcessorConfig config = new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.singletonMap("prometheusPort","1234")));

// Setup mock behaviour
new Expectations() {{
context.getConfiguration(); result = Configuration.builder().processorConfig(config).build();
}};

KubernetesListBuilder builder = new KubernetesListBuilder().withItems(new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build());
PrometheusEnricher enricher = new PrometheusEnricher(context);
enricher.create(PlatformMode.kubernetes, builder);
Map<String, String> annotations = builder.buildFirstItem().getMetadata().getAnnotations();

assertEquals(2, annotations.size());
assertEquals("1234", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_PORT));
assertEquals("true", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_SCRAPE));
}

@Test
public void testDetectPrometheusPort() {
final ProcessorConfig config = new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.emptyMap()));

final BuildConfiguration imageConfig = BuildConfiguration.builder()
.ports(Collections.singletonList(PrometheusEnricher.PROMETHEUS_PORT))
.build();


// Setup mock behaviour
new Expectations() {{
context.getConfiguration();
result = Configuration.builder()
.processorConfig(config)
.image(imageConfiguration)
.build();

imageConfiguration.getBuildConfiguration(); result = imageConfig;
}};

KubernetesListBuilder builder = new KubernetesListBuilder().withItems(new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build());
PrometheusEnricher enricher = new PrometheusEnricher(context);
enricher.create(PlatformMode.kubernetes, builder);
Map<String, String> annotations = builder.buildFirstItem().getMetadata().getAnnotations();

assertEquals(2, annotations.size());
assertEquals("9779", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_PORT));
assertEquals("true", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_SCRAPE));
}

@Test
public void testNoDefinedPrometheusPort() {
final ProcessorConfig config = new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.emptyMap()));

final BuildConfiguration imageConfig = BuildConfiguration.builder()
.build();

// Setup mock behaviour
new Expectations() {{
context.getConfiguration();
result = Configuration.builder()
.processorConfig(config)
.image(imageConfiguration)
.build();

imageConfiguration.getBuildConfiguration(); result = imageConfig;
}};

KubernetesListBuilder builder = new KubernetesListBuilder().withItems(new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build());
PrometheusEnricher enricher = new PrometheusEnricher(context);
enricher.create(PlatformMode.kubernetes, builder);
Map<String, String> annotations = builder.buildFirstItem().getMetadata().getAnnotations();

assertNull(annotations);
}

@Test
public void testCustomPrometheusPath() {
final ProcessorConfig config = new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.singletonMap("prometheusPath","/prometheus")));;

final BuildConfiguration imageConfig = BuildConfiguration.builder()
.ports(Collections.singletonList(PrometheusEnricher.PROMETHEUS_PORT))
.build();


// Setup mock behaviour
new Expectations() {{
context.getConfiguration();
result = Configuration.builder()
.processorConfig(config)
.image(imageConfiguration)
.build();

imageConfiguration.getBuildConfiguration(); result = imageConfig;
}};

KubernetesListBuilder builder = new KubernetesListBuilder().withItems(new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build());
PrometheusEnricher enricher = new PrometheusEnricher(context);
enricher.create(PlatformMode.kubernetes, builder);
Map<String, String> annotations = builder.buildFirstItem().getMetadata().getAnnotations();

assertEquals(3, annotations.size());
assertEquals("9779", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_PORT));
assertEquals("true", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_SCRAPE));
assertEquals("/prometheus", annotations.get(PrometheusEnricher.ANNOTATION_PROMETHEUS_PATH));
}
@Mocked
private JKubeEnricherContext context;
private PrometheusEnricher prometheusEnricher;

@Before
public void setUp() {
prometheusEnricher = new PrometheusEnricher(context);
}
@SuppressWarnings("ResultOfMethodCallIgnored")
private void initContext(ProcessorConfig config, ImageConfiguration imageConfiguration) {
// @formatter:off
new Expectations() {{
context.getConfiguration(); result = Configuration.builder().processorConfig(config).image(imageConfiguration).build();
}};
// @formatter:on
}

@Test
public void testCustomPrometheusPort() {
// Given
initContext(new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.singletonMap("prometheusPort", "1234"))),
null);
final KubernetesListBuilder builder = new KubernetesListBuilder().withItems(
new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build()
);
// When
prometheusEnricher.create(PlatformMode.kubernetes, builder);
// Then
assertThat(builder.buildFirstItem().getMetadata().getAnnotations())
.hasSize(3)
.containsEntry("prometheus.io/port", "1234")
.containsEntry("prometheus.io/scrape", "true")
.containsEntry("prometheus.io/path", "/metrics");
}

@Test
public void testDetectPrometheusPort() {
// Given
initContext(null,
ImageConfiguration.builder().build(
BuildConfiguration.builder()
.ports(Arrays.asList("1337", null, " ", "9779", null))
.build())
.build());
final KubernetesListBuilder builder = new KubernetesListBuilder().withItems(
new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build()
);
// When
prometheusEnricher.create(PlatformMode.kubernetes, builder);
// Then
assertThat(builder.buildFirstItem().getMetadata().getAnnotations())
.hasSize(3)
.containsEntry("prometheus.io/port", "9779")
.containsEntry("prometheus.io/scrape", "true")
.containsEntry("prometheus.io/path", "/metrics");
}

@Test
public void testNoDefinedPrometheusPort() {
// Given
initContext(null,
ImageConfiguration.builder().build(
BuildConfiguration.builder()
.ports(Collections.emptyList())
.build())
.build());
final KubernetesListBuilder builder = new KubernetesListBuilder().withItems(
new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build()
);
// When
prometheusEnricher.create(PlatformMode.kubernetes, builder);
// Then
assertThat(builder.buildFirstItem().getMetadata().getAnnotations()).isNull();
}

@Test
public void testCustomPrometheusPath() {
// Given
initContext(new ProcessorConfig(
null,
null,
Collections.singletonMap("jkube-prometheus", Collections.singletonMap("prometheusPath", "/prometheus"))),
ImageConfiguration.builder().build(
BuildConfiguration.builder()
.ports(Arrays.asList("1337", null, " ", "9779", null))
.build())
.build());
final KubernetesListBuilder builder = new KubernetesListBuilder().withItems(
new ServiceBuilder().withNewMetadata().withName("foo").endMetadata().build()
);
// When
prometheusEnricher.create(PlatformMode.kubernetes, builder);
// Then
assertThat(builder.buildFirstItem().getMetadata().getAnnotations())
.hasSize(3)
.containsEntry("prometheus.io/port", "9779")
.containsEntry("prometheus.io/scrape", "true")
.containsEntry("prometheus.io/path", "/prometheus");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ items:
annotations:
prometheus.io/scrape: "true"
prometheus.io/port: 9779
prometheus.io/path: "/metrics"
----

By default the enricher inspects the images' BuildConfiguration and add the annotations if the port 9779 is listed.
Expand Down

0 comments on commit a0440eb

Please sign in to comment.