Skip to content

Commit 10998f1

Browse files
committed
feat: log when a configuration is not found or created automatically
1 parent c62d624 commit 10998f1

File tree

5 files changed

+84
-8
lines changed

5 files changed

+84
-8
lines changed

operator-framework-core/pom.xml

-1
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@
8585
<dependency>
8686
<groupId>org.apache.logging.log4j</groupId>
8787
<artifactId>log4j-slf4j-impl</artifactId>
88-
<version>2.13.3</version>
8988
<scope>test</scope>
9089
</dependency>
9190
<dependency>

operator-framework-core/src/main/java/io/javaoperatorsdk/operator/api/config/AbstractConfigurationService.java

+18-1
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@
77
import java.util.Set;
88
import java.util.concurrent.ConcurrentHashMap;
99
import java.util.stream.Stream;
10+
import org.slf4j.Logger;
11+
import org.slf4j.LoggerFactory;
1012

1113
public abstract class AbstractConfigurationService implements ConfigurationService {
1214

15+
public static final String LOGGER_NAME = "Default ConfigurationService implementation";
16+
protected static final Logger log = LoggerFactory.getLogger(LOGGER_NAME);
17+
1318
private final Map<String, ControllerConfiguration> configurations = new ConcurrentHashMap<>();
1419
private final Version version;
1520

@@ -52,7 +57,19 @@ protected void throwExceptionOnNameCollision(
5257
@Override
5358
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
5459
ResourceController<R> controller) {
55-
return configurations.get(keyFor(controller));
60+
final var key = keyFor(controller);
61+
final var configuration = configurations.get(key);
62+
if (configuration == null) {
63+
log.warn(
64+
"Configuration for controller '{}' was not found. {}", key, getControllersNameMessage());
65+
}
66+
return configuration;
67+
}
68+
69+
private String getControllersNameMessage() {
70+
return "Known controllers: "
71+
+ getKnownControllerNames().stream().reduce((s, s2) -> s + ", " + s2).orElse("None")
72+
+ ".";
5673
}
5774

5875
protected String keyFor(ResourceController controller) {

operator-framework/pom.xml

+6
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,12 @@
5555
<artifactId>junit-jupiter-engine</artifactId>
5656
<scope>test</scope>
5757
</dependency>
58+
<dependency>
59+
<groupId>ch.qos.logback</groupId>
60+
<artifactId>logback-classic</artifactId>
61+
<version>1.2.3</version>
62+
<scope>test</scope>
63+
</dependency>
5864
<dependency>
5965
<groupId>org.assertj</groupId>
6066
<artifactId>assertj-core</artifactId>

operator-framework/src/main/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationService.java

+16-6
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,40 @@
33
import io.fabric8.kubernetes.client.CustomResource;
44
import io.javaoperatorsdk.operator.api.ResourceController;
55
import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
6-
import io.javaoperatorsdk.operator.api.config.ConfigurationService;
76
import io.javaoperatorsdk.operator.api.config.ControllerConfiguration;
87
import io.javaoperatorsdk.operator.api.config.Utils;
98

109
public class DefaultConfigurationService extends AbstractConfigurationService {
1110

12-
private static final ConfigurationService instance = new DefaultConfigurationService();
11+
private static final DefaultConfigurationService instance = new DefaultConfigurationService();
1312

1413
private DefaultConfigurationService() {
1514
super(Utils.loadFromProperties());
1615
}
1716

18-
public static ConfigurationService instance() {
17+
public static DefaultConfigurationService instance() {
1918
return instance;
2019
}
2120

2221
@Override
2322
public <R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
2423
ResourceController<R> controller) {
24+
return getConfigurationFor(controller, true);
25+
}
26+
27+
<R extends CustomResource> ControllerConfiguration<R> getConfigurationFor(
28+
ResourceController<R> controller, boolean createIfNeeded) {
2529
var config = super.getConfigurationFor(controller);
2630
if (config == null) {
27-
// create the the configuration on demand and register it
28-
config = new AnnotationConfiguration(controller);
29-
register(config);
31+
if (createIfNeeded) {
32+
// create the the configuration on demand and register it
33+
config = new AnnotationConfiguration(controller);
34+
register(config);
35+
log.info(
36+
"Created configuration for controller {} with name {}",
37+
controller.getClass().getName(),
38+
config.getName());
39+
}
3040
} else {
3141
// check that we don't have a controller name collision
3242
final var newControllerClassName = controller.getClass().getCanonicalName();

operator-framework/src/test/java/io/javaoperatorsdk/operator/config/runtime/DefaultConfigurationServiceTest.java

+44
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,12 @@
33
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
44
import static org.junit.jupiter.api.Assertions.assertEquals;
55
import static org.junit.jupiter.api.Assertions.assertFalse;
6+
import static org.junit.jupiter.api.Assertions.assertNull;
7+
import static org.junit.jupiter.api.Assertions.assertTrue;
68

9+
import ch.qos.logback.classic.Logger;
10+
import ch.qos.logback.classic.spi.ILoggingEvent;
11+
import ch.qos.logback.core.read.ListAppender;
712
import io.fabric8.kubernetes.client.CustomResource;
813
import io.fabric8.kubernetes.model.annotation.Group;
914
import io.fabric8.kubernetes.model.annotation.Version;
@@ -12,12 +17,39 @@
1217
import io.javaoperatorsdk.operator.api.Controller;
1318
import io.javaoperatorsdk.operator.api.ResourceController;
1419
import io.javaoperatorsdk.operator.api.UpdateControl;
20+
import io.javaoperatorsdk.operator.api.config.AbstractConfigurationService;
1521
import org.junit.jupiter.api.Test;
22+
import org.slf4j.LoggerFactory;
1623

1724
public class DefaultConfigurationServiceTest {
1825

1926
public static final String CUSTOM_FINALIZER_NAME = "a.custom/finalizer";
2027

28+
@Test
29+
void attemptingToRetrieveAnUnknownControllerShouldLogWarning() {
30+
final var logger = (Logger) LoggerFactory.getLogger(AbstractConfigurationService.LOGGER_NAME);
31+
final var appender = new ListAppender<ILoggingEvent>();
32+
logger.addAppender(appender);
33+
appender.start();
34+
try {
35+
final var config =
36+
DefaultConfigurationService.instance()
37+
.getConfigurationFor(new NotAutomaticallyCreated(), false);
38+
assertNull(config);
39+
assertEquals(1, appender.list.size());
40+
assertTrue(
41+
appender.list.stream()
42+
.allMatch(
43+
e -> {
44+
final var message = e.getFormattedMessage();
45+
return message.contains(NotAutomaticallyCreated.NAME)
46+
&& message.contains("not found");
47+
}));
48+
} finally {
49+
logger.detachAndStopAllAppenders();
50+
}
51+
}
52+
2153
@Test
2254
public void returnsValuesFromControllerAnnotationFinalizer() {
2355
final var controller = new TestCustomResourceController();
@@ -65,6 +97,18 @@ public UpdateControl<TestCustomFinalizerController.InnerCustomResource> createOr
6597
}
6698
}
6799

100+
@Controller(name = NotAutomaticallyCreated.NAME)
101+
static class NotAutomaticallyCreated implements ResourceController<TestCustomResource> {
102+
103+
public static final String NAME = "should-be-logged";
104+
105+
@Override
106+
public UpdateControl<TestCustomResource> createOrUpdateResource(
107+
TestCustomResource resource, Context<TestCustomResource> context) {
108+
return null;
109+
}
110+
}
111+
68112
@Controller(generationAwareEventProcessing = false, name = "test")
69113
static class TestCustomResourceController implements ResourceController<TestCustomResource> {
70114

0 commit comments

Comments
 (0)