Skip to content

Commit

Permalink
Make K8s secrets watchable (#680) (#767)
Browse files Browse the repository at this point in the history
Extracts common watch functionality for secrets and config-maps into abstract base classes and implement those for the dedicated sub types, so that watch config looks the same for both types and has the same base implementation.
  • Loading branch information
mhartmann-jaconi authored Oct 28, 2024
1 parent 5ec5eb4 commit 930db80
Show file tree
Hide file tree
Showing 12 changed files with 571 additions and 243 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
*/
package io.micronaut.kubernetes;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import io.micronaut.context.annotation.BootstrapContextCompatible;
import io.micronaut.context.annotation.ConfigurationProperties;
Expand All @@ -24,12 +29,6 @@
import io.micronaut.discovery.DiscoveryConfiguration;
import io.micronaut.kubernetes.client.NamespaceResolver;

import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

/**
* Encapsulates constants for Kubernetes configuration.
*
Expand Down Expand Up @@ -250,30 +249,15 @@ public void setExceptionOnPodLabelsMissing(boolean exceptionOnPodLabelsMissing)
}

/**
* Kubernetes secrets configuration properties.
* Base class for config-maps and secrets.
*/
@ConfigurationProperties(KubernetesSecretsConfiguration.PREFIX)
@BootstrapContextCompatible
public static class KubernetesSecretsConfiguration extends AbstractKubernetesConfiguration {

static final String PREFIX = "secrets";

static final boolean DEFAULT_ENABLED = false;

private boolean enabled = DEFAULT_ENABLED;
public abstract static class AbstractConfigConfiguration extends AbstractKubernetesConfiguration {
private Collection<String> paths;
private boolean useApi;
private boolean watch;

@Override
public boolean isEnabled() {
return enabled;
}

/**
* @param enabled enabled flag.
*/
public void setEnabled(boolean enabled) {
this.enabled = enabled;
AbstractConfigConfiguration(boolean defaultWatch) {
watch = defaultWatch;
}

/**
Expand Down Expand Up @@ -306,64 +290,65 @@ public boolean isUseApi() {
public void setUseApi(boolean useApi) {
this.useApi = useApi;
}
}

/**
* Kubernetes config maps configuration properties.
*/
@ConfigurationProperties(KubernetesConfigMapsConfiguration.PREFIX)
@BootstrapContextCompatible
public static class KubernetesConfigMapsConfiguration extends AbstractKubernetesConfiguration {
public static final String PREFIX = "config-maps";
static final boolean DEFAULT_WATCH = true;

private Collection<String> paths;
private boolean useApi;
private boolean watch = DEFAULT_WATCH;

/**
* @return paths where config maps are mounted
* @return whether to enable watching for the ConfigMap changes.
*/
public Collection<String> getPaths() {
if (paths == null) {
return Collections.emptySet();
}
return paths;
public boolean isWatch() {
return watch;
}

/**
* @param paths where config maps are mounted
* @param watch flag to watch for the ConfigMap changes.
*/
public void setPaths(Collection<String> paths) {
this.paths = paths;
public void setWatch(boolean watch) {
this.watch = watch;
}
}

/**
* @return whether to use the API to read config maps when {@link #paths} is used.
*/
public boolean isUseApi() {
return useApi;
/**
* Kubernetes secrets configuration properties.
*/
@ConfigurationProperties(KubernetesSecretsConfiguration.PREFIX)
@BootstrapContextCompatible
public static class KubernetesSecretsConfiguration extends AbstractConfigConfiguration {

static final String PREFIX = "secrets";

static final boolean DEFAULT_ENABLED = false;
static final boolean DEFAULT_WATCH = false;

private boolean enabled = DEFAULT_ENABLED;

public KubernetesSecretsConfiguration() {
super(DEFAULT_WATCH);
}

/**
* @param useApi whether to use the API to read config maps when {@link #paths} is used.
*/
public void setUseApi(boolean useApi) {
this.useApi = useApi;
@Override
public boolean isEnabled() {
return enabled;
}

/**
* @return whether to enable watching for the ConfigMap changes. Defaults to {@value DEFAULT_WATCH}.
* @param enabled enabled flag.
*/
public boolean isWatch() {
return watch;
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
}

/**
* @param watch flag to watch for the ConfigMap changes.
*/
public void setWatch(boolean watch) {
this.watch = watch;
/**
* Kubernetes config maps configuration properties.
*/
@ConfigurationProperties(KubernetesConfigMapsConfiguration.PREFIX)
@BootstrapContextCompatible
public static class KubernetesConfigMapsConfiguration extends AbstractConfigConfiguration {
public static final String PREFIX = "config-maps";

static final boolean DEFAULT_WATCH = true;

public KubernetesConfigMapsConfiguration() {
super(DEFAULT_WATCH);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2017-2021 original authors
* Copyright 2017-2024 original authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -15,48 +15,44 @@
*/
package io.micronaut.kubernetes.configuration;

import io.micronaut.context.annotation.Requires;
import io.micronaut.context.env.Environment;
import io.micronaut.kubernetes.KubernetesConfiguration;
import io.micronaut.kubernetes.client.reactor.CoreV1ApiReactorClient;
import io.micronaut.kubernetes.util.KubernetesUtils;
import jakarta.inject.Singleton;
import java.util.Map;
import java.util.function.Supplier;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Map;
import java.util.function.Supplier;
import io.micronaut.kubernetes.KubernetesConfiguration;
import io.micronaut.kubernetes.client.reactor.CoreV1ApiReactorClient;
import io.micronaut.kubernetes.util.KubernetesUtils;

/**
* Based on configuration dynamically evaluates the label selector.
*
* @author Pavol Gressa
* @since 3.1
*/
@Singleton
@Requires(env = Environment.KUBERNETES)
public class ConfigMapLabelSupplier implements Supplier<String> {

private static final Logger LOG = LoggerFactory.getLogger(ConfigMapLabelSupplier.class);
abstract class AbstractKubernetesConfigLabelSupplier implements Supplier<String> {
private static final Logger LOG = LoggerFactory.getLogger(AbstractKubernetesConfigLabelSupplier.class);

protected final KubernetesConfiguration configuration;
private final CoreV1ApiReactorClient coreV1ApiReactorClient;
private final KubernetesConfiguration configuration;

public ConfigMapLabelSupplier(CoreV1ApiReactorClient coreV1ApiReactorClient, KubernetesConfiguration configuration) {
AbstractKubernetesConfigLabelSupplier(CoreV1ApiReactorClient coreV1ApiReactorClient, KubernetesConfiguration configuration) {
this.coreV1ApiReactorClient = coreV1ApiReactorClient;
this.configuration = configuration;
}

@Override
public String get() {
Map<String, String> labels = configuration.getConfigMaps().getLabels();
Map<String, String> labels = getConfig().getLabels();
String labelSelector = KubernetesUtils.computePodLabelSelector(coreV1ApiReactorClient,
configuration.getConfigMaps().getPodLabels(), configuration.getNamespace(), labels,
configuration.getDiscovery().isExceptionOnPodLabelsMissing())
.block();
getConfig().getPodLabels(), configuration.getNamespace(), labels,
configuration.getDiscovery().isExceptionOnPodLabelsMissing())
.block();
if (LOG.isInfoEnabled()) {
LOG.info("Computed kubernetes configuration discovery config map label selector: {}", labelSelector);
LOG.info("Computed kubernetes configuration discovery config label selector: {}", labelSelector);
}
return labelSelector;
}

abstract KubernetesConfiguration.AbstractConfigConfiguration getConfig();
}
Loading

0 comments on commit 930db80

Please sign in to comment.