slight changes in info contributor (#699)

* slight changes

* rename and test

* junit5 + rename + get rid of unused code

* added an inside test
This commit is contained in:
erabii
2020-12-19 20:50:04 -05:00
committed by GitHub
parent 955022b62b
commit c3bce72fcb
3 changed files with 175 additions and 27 deletions

View File

@@ -16,7 +16,7 @@
package org.springframework.cloud.kubernetes.fabric8;
import java.util.HashMap;
import java.util.Collections;
import java.util.Map;
import io.fabric8.kubernetes.api.model.Pod;
@@ -24,6 +24,7 @@ import io.fabric8.kubernetes.api.model.Pod;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.cloud.kubernetes.commons.AbstractKubernetesInfoContributor;
import org.springframework.cloud.kubernetes.commons.PodUtils;
import org.springframework.util.CollectionUtils;
/**
* Kubernetes implementation of {@link InfoContributor}.
@@ -32,7 +33,7 @@ import org.springframework.cloud.kubernetes.commons.PodUtils;
*/
public class Fabric8InfoContributor extends AbstractKubernetesInfoContributor {
private PodUtils<Pod> utils;
private final PodUtils<Pod> utils;
public Fabric8InfoContributor(PodUtils<Pod> utils) {
this.utils = utils;
@@ -41,18 +42,19 @@ public class Fabric8InfoContributor extends AbstractKubernetesInfoContributor {
@Override
public Map<String, Object> getDetails() {
Pod current = this.utils.currentPod().get();
Map<String, Object> details = new HashMap<>();
boolean inside = current != null;
details.put(INSIDE, inside);
if (inside) {
if (current != null) {
Map<String, Object> details = CollectionUtils.newHashMap(7);
details.put(INSIDE, true);
details.put(NAMESPACE, current.getMetadata().getNamespace());
details.put(POD_NAME, current.getMetadata().getName());
details.put(POD_IP, current.getStatus().getPodIP());
details.put(SERVICE_ACCOUNT, current.getSpec().getServiceAccountName());
details.put(NODE_NAME, current.getSpec().getNodeName());
details.put(HOST_IP, current.getStatus().getHostIP());
return details;
}
return details;
return Collections.singletonMap(INSIDE, false);
}
}

View File

@@ -0,0 +1,134 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed 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
*
* https://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 org.springframework.cloud.kubernetes;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.fabric8.kubernetes.api.model.Pod;
import io.fabric8.kubernetes.api.model.PodBuilder;
import io.fabric8.kubernetes.api.model.PodSpec;
import io.fabric8.kubernetes.api.model.PodStatus;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.kubernetes.commons.PodUtils;
import org.springframework.cloud.kubernetes.example.App;
import org.springframework.cloud.kubernetes.fabric8.Fabric8InfoContributor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.context.annotation.Primary;
import org.springframework.http.MediaType;
import org.springframework.test.web.reactive.server.WebTestClient;
/**
* @author wind57
*
* test proper fields being set in /actuator/info
*/
@Import(Fabric8InsideInfoContributorTest.InfoContributorTestConfig.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class,
properties = { "management.endpoint.health.show-details=always", "management.info.kubernetes.enabled=false" })
public class Fabric8InsideInfoContributorTest {
@Autowired
private WebTestClient webClient;
@Value("${local.server.port}")
private int port;
@Test
public void test() {
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON)
.exchange().expectStatus().isOk().expectBody(String.class)
.value(Fabric8InsideInfoContributorTest::validateInfo);
}
private static Pod stubPod() {
PodStatus status = new PodStatus();
status.setPodIP("10.1.1.1");
status.setHostIP("192.160.10.3");
PodSpec spec = new PodSpec();
spec.setServiceAccountName("serviceAccountName");
spec.setNodeName("nodeName");
return new PodBuilder().withNewMetadata().withName("pod").withNamespace("namespace").endMetadata()
.withStatus(status).withSpec(spec).build();
}
/**
* <pre>
* {
* "kubernetes": {
* "nodeName": "nodeName",
* "podIp": "10.1.1.1",
* "hostIp": "192.160.10.3",
* "namespace": "namespace",
* "podName": "pod",
* "serviceAccount": "serviceAccountName",
* "inside": true
* }
* }
* </pre>
*/
@SuppressWarnings("unchecked")
private static void validateInfo(String input) {
try {
Map<String, Object> map = new ObjectMapper().readValue(input, new TypeReference<Map<String, Object>>() {
});
Map<String, Object> infoProperties = (Map<String, Object>) map.get("kubernetes");
Assertions.assertEquals("nodeName", infoProperties.get("nodeName"));
Assertions.assertEquals("10.1.1.1", infoProperties.get("podIp"));
Assertions.assertEquals("192.160.10.3", infoProperties.get("hostIp"));
Assertions.assertEquals("namespace", infoProperties.get("namespace"));
Assertions.assertEquals("pod", infoProperties.get("podName"));
Assertions.assertEquals("serviceAccountName", infoProperties.get("serviceAccount"));
Assertions.assertTrue((Boolean) infoProperties.get("inside"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
@Configuration
static class InfoContributorTestConfig {
@Bean
@Primary
public Fabric8InfoContributor testInfoContributor() {
@SuppressWarnings("unchecked")
PodUtils<Pod> utils = Mockito.mock(PodUtils.class);
Mockito.when(utils.currentPod()).thenReturn(Fabric8InsideInfoContributorTest::stubPod);
return new Fabric8InfoContributor(utils);
}
}
}

View File

@@ -16,29 +16,28 @@
package org.springframework.cloud.kubernetes;
import io.fabric8.kubernetes.client.Config;
import java.util.Map;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import io.fabric8.kubernetes.client.KubernetesClient;
import io.fabric8.kubernetes.server.mock.KubernetesServer;
import org.junit.BeforeClass;
import org.junit.ClassRule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.cloud.kubernetes.example.App;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.web.reactive.server.WebTestClient;
import static org.hamcrest.Matchers.containsString;
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT, classes = App.class)
public class InfoContributorTest {
public class Fabric8NotInsideInfoContributorTest {
@ClassRule
public static KubernetesServer server = new KubernetesServer();
private static KubernetesClient mockClient;
@@ -49,23 +48,36 @@ public class InfoContributorTest {
@Value("${local.server.port}")
private int port;
@BeforeClass
@BeforeAll
public static void setUpBeforeClass() {
server.before();
mockClient = server.getClient();
}
// Configure the kubernetes master url to point to the mock server
System.setProperty(Config.KUBERNETES_MASTER_SYSTEM_PROPERTY, mockClient.getConfiguration().getMasterUrl());
System.setProperty(Config.KUBERNETES_TRUST_CERT_SYSTEM_PROPERTY, "true");
System.setProperty(Config.KUBERNETES_AUTH_TRYKUBECONFIG_SYSTEM_PROPERTY, "false");
System.setProperty(Config.KUBERNETES_AUTH_TRYSERVICEACCOUNT_SYSTEM_PROPERTY, "false");
System.setProperty(Config.KUBERNETES_NAMESPACE_SYSTEM_PROPERTY, "test");
System.setProperty(Config.KUBERNETES_HTTP2_DISABLE, "true");
@AfterAll
public static void afterAll() {
server.after();
}
@Test
public void infoEndpointShouldContainKubernetes() {
this.webClient.get().uri("http://localhost:{port}/actuator/info", this.port).accept(MediaType.APPLICATION_JSON)
.exchange().expectStatus().isOk().expectBody(String.class).value(containsString("kubernetes"));
.exchange().expectStatus().isOk().expectBody(String.class).value(this::validateInfo);
}
// {"kubernetes":{"inside":false}}
@SuppressWarnings("unchecked")
private void validateInfo(String input) {
try {
Map<String, Object> map = new ObjectMapper().readValue(input, new TypeReference<Map<String, Object>>() {
});
Map<String, Object> kubernetesProperties = (Map<String, Object>) map.get("kubernetes");
Assertions.assertFalse((Boolean) kubernetesProperties.get("inside"));
}
catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}