io.micronaut.kubernetes.discovery.KubernetesDiscoveryClient Maven / Gradle / Ivy
/*
* Copyright 2017-2020 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
*
* 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 io.micronaut.kubernetes.discovery;
import io.micronaut.context.annotation.Requires;
import io.micronaut.context.env.Environment;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.core.async.publisher.Publishers;
import io.micronaut.core.util.StringUtils;
import io.micronaut.discovery.DiscoveryClient;
import io.micronaut.discovery.ServiceInstance;
import io.micronaut.kubernetes.KubernetesConfiguration;
import io.micronaut.kubernetes.client.reactor.CoreV1ApiReactorClient;
import jakarta.inject.Inject;
import jakarta.inject.Singleton;
import org.reactivestreams.Publisher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import reactor.core.publisher.Flux;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* A {@link DiscoveryClient} implementation for Kubernetes using the API.
*
* @author Álvaro Sánchez-Mariscal
* @since 1.0.0
*/
@Singleton
@Requires(env = Environment.KUBERNETES)
@Requires(property = KubernetesConfiguration.KubernetesDiscoveryConfiguration.PREFIX + ".enabled", notEquals = StringUtils.FALSE, defaultValue = StringUtils.TRUE)
@SuppressWarnings("WeakerAccess")
public class KubernetesDiscoveryClient implements DiscoveryClient {
public static final String SERVICE_ID = "kubernetes";
protected static final Logger LOG = LoggerFactory.getLogger(KubernetesDiscoveryClient.class);
private final CoreV1ApiReactorClient client;
private final KubernetesConfiguration configuration;
private final KubernetesConfiguration.KubernetesDiscoveryConfiguration discoveryConfiguration;
private final Map serviceConfigurations;
private final Map instanceProviders;
private final KubernetesServiceInstanceList instanceList;
/**
* Creates discovery client that supports the discovery modes.
*
* @param client An HTTP Client to query the Kubernetes API.
* @param configuration The configuration properties
* @param discoveryConfiguration The discovery configuration properties
* @param serviceConfigurations The manual service discovery configurations
* @param instanceProviders The service instance provider implementations
* @param instanceList The {@link KubernetesServiceInstanceList}
*/
@Inject
public KubernetesDiscoveryClient(CoreV1ApiReactorClient client,
KubernetesConfiguration configuration,
KubernetesConfiguration.KubernetesDiscoveryConfiguration discoveryConfiguration,
List serviceConfigurations,
List instanceProviders,
KubernetesServiceInstanceList instanceList) {
this.client = client;
this.configuration = configuration;
this.discoveryConfiguration = discoveryConfiguration;
this.serviceConfigurations = serviceConfigurations.stream()
.collect(Collectors.toMap(KubernetesServiceConfiguration::getServiceId, Function.identity()));
this.instanceProviders = instanceProviders.stream()
.collect(Collectors.toMap(KubernetesServiceInstanceProvider::getMode, Function.identity()));
this.instanceList = instanceList;
}
@Override
public Publisher> getInstances(String serviceId) {
if (!discoveryConfiguration.isEnabled()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Discovery configuration is not enabled");
}
return Publishers.just(Collections.emptyList());
}
if (SERVICE_ID.equals(serviceId)) {
return Publishers.just(instanceList.getInstances());
} else {
KubernetesServiceConfiguration serviceConfiguration = serviceConfigurations.computeIfAbsent(
serviceId, key -> new KubernetesServiceConfiguration(key, false));
if (!serviceConfiguration.getNamespace().isPresent()) {
serviceConfiguration.setNamespace(configuration.getNamespace());
}
if (!serviceConfiguration.getName().isPresent()) {
serviceConfiguration.setName(serviceId);
}
if (!serviceConfiguration.getMode().isPresent()) {
serviceConfiguration.setMode(configuration.getDiscovery().getMode());
}
String mode = serviceConfiguration.getMode().get();
if (!instanceProviders.containsKey(mode)) {
if (LOG.isErrorEnabled()) {
LOG.error("Unrecognized kubernetes discovery mode: [" + mode +
"], out of supported ones: [ " + String.join(",", instanceProviders.keySet()) + "]");
}
return Publishers.just(Collections.emptyList());
} else {
return instanceProviders.get(mode).getInstances(serviceConfiguration);
}
}
}
/**
* @return A list of services metadata's name.
*/
@Override
public Publisher> getServiceIds() {
final String namespace = configuration.getNamespace();
final KubernetesServiceInstanceProvider instanceProvider = instanceProviders.get(discoveryConfiguration.getMode());
return Flux.merge(
Flux.fromIterable(serviceConfigurations.keySet()),
instanceProvider.getServiceIds(namespace)
)
.distinct().collectList();
}
@Override
public @NonNull
String getDescription() {
return SERVICE_ID;
}
@Override
public void close() {
//no op
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy