Add a profile listener that will automatically add the kubernetes profile when running inside kubernetes.
This commit is contained in:
@@ -80,10 +80,18 @@ public class KubernetesAutoConfiguration {
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KubernetesHealthIndicator kubernetesHealthIndicator(KubernetesClient client) {
|
||||
return new KubernetesHealthIndicator(client);
|
||||
StandardPodUtils kubernetesPodUtils(KubernetesClient client) {
|
||||
return new StandardPodUtils(client);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public KubernetesHealthIndicator kubernetesHealthIndicator(KubernetesClient client, StandardPodUtils podUtils) {
|
||||
return new KubernetesHealthIndicator(client, podUtils);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static <D> D or(D dis, D dat) {
|
||||
if (dis != null) {
|
||||
return dis;
|
||||
|
||||
@@ -17,61 +17,37 @@
|
||||
package io.fabric8.spring.cloud.kubernetes;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
import org.springframework.boot.actuate.health.AbstractHealthIndicator;
|
||||
import org.springframework.boot.actuate.health.Health;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class KubernetesHealthIndicator extends AbstractHealthIndicator {
|
||||
|
||||
private static final String HOSTNAME = "HOSTNAME";
|
||||
|
||||
private String hostName;
|
||||
private KubernetesClient client;
|
||||
private PodUtils utils;
|
||||
|
||||
public KubernetesHealthIndicator(KubernetesClient client) {
|
||||
public KubernetesHealthIndicator(KubernetesClient client, PodUtils utils) {
|
||||
this.client = client;
|
||||
this.hostName = System.getenv(HOSTNAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doHealthCheck(Health.Builder builder) throws Exception {
|
||||
try {
|
||||
Pod current = getCurrentPod();
|
||||
Pod current = utils.currentPod().get();
|
||||
if (current != null) {
|
||||
builder.up()
|
||||
.withDetail("internal", true)
|
||||
.withDetail("podName", hostName)
|
||||
.withDetail("inside", true)
|
||||
.withDetail("podName", current.getMetadata().getName())
|
||||
.withDetail("podIp", current.getStatus().getPodIP())
|
||||
.withDetail("serviceAccount", current.getSpec().getServiceAccountName())
|
||||
.withDetail("nodeName", current.getSpec().getNodeName())
|
||||
.withDetail("hostIp", current.getStatus().getHostIP());
|
||||
} else {
|
||||
builder.up()
|
||||
.withDetail("internal", false);
|
||||
.withDetail("inside", false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
builder.down(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private Pod getCurrentPod() {
|
||||
if (isServiceAccountFound() && isHostNameEnvVarPresent()) {
|
||||
return client.pods().withName(hostName).get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHostNameEnvVarPresent() {
|
||||
return hostName != null && !hostName.isEmpty();
|
||||
}
|
||||
|
||||
private boolean isServiceAccountFound() {
|
||||
return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists() &&
|
||||
Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (C) 2016 to the original 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
|
||||
*
|
||||
* 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.spring.cloud.kubernetes;
|
||||
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class LazilyInstantiate<T> implements Supplier<T> {
|
||||
|
||||
public static <T> LazilyInstantiate<T> using(Supplier<T> supplier) {
|
||||
return new LazilyInstantiate<T>(supplier);
|
||||
}
|
||||
|
||||
public synchronized T get() {
|
||||
return current.get();
|
||||
}
|
||||
|
||||
private LazilyInstantiate(Supplier supplier) {
|
||||
this.supplier = supplier;
|
||||
this.current = () -> swapper();
|
||||
}
|
||||
|
||||
private final Supplier<T> supplier;
|
||||
private Supplier<T> current;
|
||||
|
||||
private T swapper() {
|
||||
T obj = supplier.get();
|
||||
current = () -> obj;
|
||||
return obj;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (C) 2016 to the original 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
|
||||
*
|
||||
* 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.spring.cloud.kubernetes;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface PodUtils {
|
||||
|
||||
/**
|
||||
* @return A supplier of the currentPod {@link Pod}. The supplier will hold the currentPod {@Pod} if inside Kubernetes
|
||||
* or false, otherwise.
|
||||
*/
|
||||
Supplier<Pod> currentPod();
|
||||
|
||||
/**
|
||||
* @return true if called from within Kubernetes, false otherwise.
|
||||
*/
|
||||
Boolean isInsideKubernetes();
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (C) 2016 to the original 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
|
||||
*
|
||||
* 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.spring.cloud.kubernetes;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.kubernetes.client.Config;
|
||||
import io.fabric8.kubernetes.client.KubernetesClient;
|
||||
|
||||
import java.nio.file.Paths;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class StandardPodUtils implements PodUtils {
|
||||
|
||||
public static final String HOSTNAME = "HOSTNAME";
|
||||
|
||||
private final KubernetesClient client;
|
||||
private final String hostName;
|
||||
private Supplier<Pod> current;
|
||||
|
||||
public StandardPodUtils(KubernetesClient client) {
|
||||
this.client = client;
|
||||
this.hostName = System.getenv(HOSTNAME);
|
||||
this.current = LazilyInstantiate.using(() -> internalGetPod());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<Pod> currentPod() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Boolean isInsideKubernetes() {
|
||||
return currentPod().get() != null;
|
||||
}
|
||||
|
||||
private synchronized Pod internalGetPod() {
|
||||
if (isServiceAccountFound() && isHostNameEnvVarPresent()) {
|
||||
return client.pods().withName(hostName).get();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isHostNameEnvVarPresent() {
|
||||
return hostName != null && !hostName.isEmpty();
|
||||
}
|
||||
|
||||
private boolean isServiceAccountFound() {
|
||||
return Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_TOKEN_PATH).toFile().exists() &&
|
||||
Paths.get(Config.KUBERNETES_SERVICE_ACCOUNT_CA_CRT_PATH).toFile().exists();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (C) 2016 to the original 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
|
||||
*
|
||||
* 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.spring.cloud.kubernetes.profile;
|
||||
|
||||
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
|
||||
import io.fabric8.spring.cloud.kubernetes.PodUtils;
|
||||
import io.fabric8.spring.cloud.kubernetes.StandardPodUtils;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.Ordered;
|
||||
|
||||
public class KubernetesApplicationContextInitializer implements
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
|
||||
|
||||
private final KubernetesProfileApplicationListener listener;
|
||||
private static final int ORDER = 100;
|
||||
|
||||
public KubernetesApplicationContextInitializer() {
|
||||
//If we are inside Kubernetes this should be perfectly valid.
|
||||
//If not then we won't add the Kubernetes profile anyway.
|
||||
this(new StandardPodUtils(new DefaultKubernetesClient()));
|
||||
}
|
||||
|
||||
public KubernetesApplicationContextInitializer(PodUtils utils) {
|
||||
this(new KubernetesProfileApplicationListener(utils));
|
||||
}
|
||||
|
||||
public KubernetesApplicationContextInitializer(KubernetesProfileApplicationListener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return ORDER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialize(ConfigurableApplicationContext applicationContext) {
|
||||
listener.addKubernetesProfile(applicationContext.getEnvironment());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (C) 2016 to the original 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
|
||||
*
|
||||
* 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.spring.cloud.kubernetes.profile;
|
||||
|
||||
import io.fabric8.kubernetes.api.model.Pod;
|
||||
import io.fabric8.spring.cloud.kubernetes.PodUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
|
||||
import org.springframework.context.ApplicationListener;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
public class KubernetesProfileApplicationListener implements ApplicationListener<ApplicationEnvironmentPreparedEvent>, Ordered {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(KubernetesProfileApplicationListener.class);
|
||||
|
||||
private static final String KUBERNETES_PROFILE = "kubernetes";
|
||||
private static final int OFFSET = 1;
|
||||
private static final int ORDER = Ordered.HIGHEST_PRECEDENCE + OFFSET;
|
||||
private final PodUtils utils;
|
||||
|
||||
public KubernetesProfileApplicationListener(PodUtils utils) {
|
||||
this.utils = utils;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
|
||||
ConfigurableEnvironment environment = event.getEnvironment();
|
||||
addKubernetesProfile(environment);
|
||||
}
|
||||
|
||||
void addKubernetesProfile(ConfigurableEnvironment environment) {
|
||||
Pod current = utils.currentPod().get();
|
||||
if (current != null) {
|
||||
if (!hasKubernetesProfile(environment)) {
|
||||
environment.addActiveProfile(KUBERNETES_PROFILE);
|
||||
}
|
||||
}
|
||||
|
||||
if (utils.isInsideKubernetes()) {
|
||||
if (hasKubernetesProfile(environment)) {
|
||||
LOGGER.debug("'kubernetes' already in list of active profiles");
|
||||
} else {
|
||||
LOGGER.debug("Adding 'kubernetes' to list of active profiles");
|
||||
environment.addActiveProfile(KUBERNETES_PROFILE);
|
||||
}
|
||||
} else {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.warn("Not running inside kubernetes. Skipping 'kuberntes' profile activation.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean hasKubernetesProfile(Environment environment) {
|
||||
for (String activeProfile : environment.getActiveProfiles()) {
|
||||
if (KUBERNETES_PROFILE.equalsIgnoreCase(activeProfile)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getOrder() {
|
||||
return ORDER;
|
||||
}
|
||||
}
|
||||
@@ -1,2 +1,5 @@
|
||||
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
|
||||
io.fabric8.spring.cloud.kubernetes.KubernetesAutoConfiguration
|
||||
io.fabric8.spring.cloud.kubernetes.KubernetesAutoConfiguration
|
||||
|
||||
org.springframework.context.ApplicationContextInitializer=\
|
||||
io.fabric8.spring.cloud.kubernetes.profile.KubernetesApplicationContextInitializer
|
||||
|
||||
Reference in New Issue
Block a user