Skip to content

Commit 154d739

Browse files
authored
Merge pull request #1284 from yue9944882/feat/spring-controller-factory-bean
Provide a factory bean approach to configure the informer/reconcilers in spring context
2 parents 833b9f3 + 3314fa3 commit 154d739

File tree

8 files changed

+136
-21
lines changed

8 files changed

+136
-21
lines changed

examples/src/main/java/io/kubernetes/client/examples/SpringControllerExample.java

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
import io.kubernetes.client.openapi.models.V1NodeList;
2525
import io.kubernetes.client.openapi.models.V1Pod;
2626
import io.kubernetes.client.openapi.models.V1PodList;
27+
import io.kubernetes.client.spring.extended.controller.KubernetesInformerConfigurer;
28+
import io.kubernetes.client.spring.extended.controller.KubernetesReconcilerConfigurer;
2729
import io.kubernetes.client.spring.extended.controller.annotation.*;
2830
import io.kubernetes.client.util.ClientBuilder;
2931
import java.io.IOException;
@@ -33,7 +35,6 @@
3335
import org.springframework.boot.SpringApplication;
3436
import org.springframework.boot.autoconfigure.SpringBootApplication;
3537
import org.springframework.context.annotation.Bean;
36-
import org.springframework.context.annotation.ComponentScan;
3738
import org.springframework.context.annotation.Configuration;
3839

3940
@SpringBootApplication
@@ -44,11 +45,6 @@ public static void main(String[] args) {
4445
}
4546

4647
@Configuration
47-
@ComponentScan(
48-
basePackages = "io.kubernetes.client.spring.extended.controller") // Scanning beans under this
49-
// package is
50-
// *REQUIRED* for informers/reconciler
51-
// injections.
5248
public static class AppConfig {
5349

5450
@Bean
@@ -64,6 +60,21 @@ public CommandLineRunner commandLineRunner(
6460
};
6561
}
6662

63+
// *REQUIRED*
64+
// Configurer components that registers informers to the informer-factory in the context.
65+
@Bean
66+
public KubernetesInformerConfigurer kubernetesInformerConfigurer(ApiClient apiClient) {
67+
return new KubernetesInformerConfigurer(apiClient);
68+
}
69+
70+
// *REQUIRED*
71+
// Configurer components that registers reconciler to the controller-manager in the context.
72+
@Bean
73+
public KubernetesReconcilerConfigurer kubernetesReconcilerConfigurer(
74+
SharedInformerFactory sharedInformerFactory) {
75+
return new KubernetesReconcilerConfigurer(sharedInformerFactory);
76+
}
77+
6778
// *OPTIONAL*
6879
// Injecting and customize your ApiClient, if not specified, fallbacks to {@link
6980
// io.kubernetes.client.util.ClientBuilder#standard}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.spring.extended.controller;
14+
15+
import io.kubernetes.client.openapi.ApiClient;
16+
import org.springframework.beans.factory.FactoryBean;
17+
18+
/**
19+
* KubernetesInformerConfigurer will register a {@link KubernetesInformerFactoryProcessor} into the
20+
* context.
21+
*/
22+
public class KubernetesInformerConfigurer
23+
implements FactoryBean<KubernetesInformerFactoryProcessor> {
24+
25+
private final ApiClient apiClient;
26+
27+
public KubernetesInformerConfigurer(ApiClient apiClient) {
28+
this.apiClient = apiClient;
29+
}
30+
31+
@Override
32+
public KubernetesInformerFactoryProcessor getObject() throws Exception {
33+
return new KubernetesInformerFactoryProcessor(apiClient);
34+
}
35+
36+
@Override
37+
public Class<?> getObjectType() {
38+
return KubernetesInformerFactoryProcessor.class;
39+
}
40+
}

spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesInformerFactoryProcessor.java

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ public class KubernetesInformerFactoryProcessor
5757

5858
private BeanDefinitionRegistry beanDefinitionRegistry;
5959

60+
private ApiClient apiClient = null;
61+
62+
public KubernetesInformerFactoryProcessor(ApiClient apiClient) {
63+
this.apiClient = apiClient;
64+
}
65+
6066
@Override
6167
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
6268
throws BeansException {
@@ -80,20 +86,22 @@ public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
8086
return;
8187
}
8288

83-
ApiClient apiClient;
84-
try {
85-
apiClient = beanFactory.getBean(ApiClient.class);
86-
} catch (NoSuchBeanDefinitionException e) {
87-
log.info("No ApiClient bean found, falling-back to default initialization..");
89+
if (this.apiClient == null) {
8890
try {
89-
apiClient = ClientBuilder.standard().build();
90-
} catch (IOException ex) {
91-
log.error("failed initializing ApiClient", ex);
92-
return;
91+
this.apiClient = beanFactory.getBean(ApiClient.class);
92+
} catch (NoSuchBeanDefinitionException e) {
93+
log.info("No ApiClient bean found, falling-back to default initialization..");
94+
try {
95+
this.apiClient = ClientBuilder.standard().build();
96+
} catch (IOException ex) {
97+
log.error("failed initializing ApiClient", ex);
98+
return;
99+
}
93100
}
94101
}
95-
apiClient.setHttpClient(
96-
apiClient.getHttpClient().newBuilder().readTimeout(Duration.ZERO).build());
102+
103+
this.apiClient.setHttpClient(
104+
this.apiClient.getHttpClient().newBuilder().readTimeout(Duration.ZERO).build());
97105

98106
SharedInformerFactory sharedInformerFactory = beanFactory.getBean(SharedInformerFactory.class);
99107
KubernetesInformers kubernetesInformers =
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*
2+
Copyright 2020 The Kubernetes Authors.
3+
Licensed under the Apache License, Version 2.0 (the "License");
4+
you may not use this file except in compliance with the License.
5+
You may obtain a copy of the License at
6+
http://www.apache.org/licenses/LICENSE-2.0
7+
Unless required by applicable law or agreed to in writing, software
8+
distributed under the License is distributed on an "AS IS" BASIS,
9+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10+
See the License for the specific language governing permissions and
11+
limitations under the License.
12+
*/
13+
package io.kubernetes.client.spring.extended.controller;
14+
15+
import io.kubernetes.client.informer.SharedInformerFactory;
16+
import org.springframework.beans.factory.FactoryBean;
17+
18+
/**
19+
* KubernetesReconcilerConfigurer will register a {@link KubernetesReconcilerProcessor} into the
20+
* context.
21+
*/
22+
public class KubernetesReconcilerConfigurer implements FactoryBean<KubernetesReconcilerProcessor> {
23+
24+
private final SharedInformerFactory sharedInformerFactory;
25+
26+
public KubernetesReconcilerConfigurer(SharedInformerFactory sharedInformerFactory) {
27+
this.sharedInformerFactory = sharedInformerFactory;
28+
}
29+
30+
@Override
31+
public KubernetesReconcilerProcessor getObject() throws Exception {
32+
return new KubernetesReconcilerProcessor(sharedInformerFactory);
33+
}
34+
35+
@Override
36+
public Class<?> getObjectType() {
37+
return KubernetesReconcilerProcessor.class;
38+
}
39+
}

spring/src/main/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerProcessor.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,12 @@ public class KubernetesReconcilerProcessor implements BeanFactoryPostProcessor,
6565

6666
private ExecutorService controllerManagerDaemon = Executors.newSingleThreadExecutor();
6767

68+
private SharedInformerFactory sharedInformerFactory;
69+
70+
public KubernetesReconcilerProcessor(SharedInformerFactory sharedInformerFactory) {
71+
this.sharedInformerFactory = sharedInformerFactory;
72+
}
73+
6874
@Override
6975
public int getOrder() {
7076
return KubernetesInformerFactoryProcessor.ORDER + 1;
@@ -73,14 +79,16 @@ public int getOrder() {
7379
@Override
7480
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
7581
throws BeansException {
76-
SharedInformerFactory sharedInformerFactory = beanFactory.getBean(SharedInformerFactory.class);
82+
if (this.sharedInformerFactory == null) {
83+
this.sharedInformerFactory = beanFactory.getBean(SharedInformerFactory.class);
84+
}
7785
String[] names = beanFactory.getBeanNamesForType(Reconciler.class);
7886
for (String name : names) {
7987
Reconciler reconciler = (Reconciler) beanFactory.getBean(name);
8088
KubernetesReconciler kubernetesReconciler =
8189
reconciler.getClass().getAnnotation(KubernetesReconciler.class);
8290
String reconcilerName = kubernetesReconciler.value();
83-
Controller controller = buildController(sharedInformerFactory, reconciler);
91+
Controller controller = buildController(this.sharedInformerFactory, reconciler);
8492
beanFactory.registerSingleton(reconcilerName, controller);
8593
}
8694
}

spring/src/test/java/io/kubernetes/client/spring/extended/controller/KubernetesInformerCreatorTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ public SharedInformerFactory sharedInformerFactory() {
7070
return new TestSharedInformerFactory();
7171
}
7272

73+
@Bean
74+
public KubernetesInformerConfigurer kubernetesInformerConfigurer(ApiClient apiClient) {
75+
return new KubernetesInformerConfigurer(apiClient);
76+
}
77+
7378
@KubernetesInformers({
7479
@KubernetesInformer(
7580
apiTypeClass = V1Pod.class,

spring/src/test/java/io/kubernetes/client/spring/extended/controller/KubernetesReconcilerCreatorTest.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ public TestReconciler podReconciler(
7171
Lister<V1ConfigMap> configMapLister) {
7272
return new TestReconciler(podInformer, podLister, configMapLister);
7373
}
74+
75+
@Bean
76+
public KubernetesReconcilerConfigurer kubernetesReconcilerConfigurer(
77+
SharedInformerFactory sharedInformerFactory) {
78+
return new KubernetesReconcilerConfigurer(sharedInformerFactory);
79+
}
7480
}
7581

7682
@KubernetesReconciler(

spring/src/test/java/io/kubernetes/client/spring/extended/controller/TestApplication.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313
package io.kubernetes.client.spring.extended.controller;
1414

1515
import org.springframework.boot.SpringBootConfiguration;
16-
import org.springframework.context.annotation.ComponentScan;
1716

1817
@SpringBootConfiguration
19-
@ComponentScan("io.kubernetes.client.spring.extended.controller")
2018
public class TestApplication {}

0 commit comments

Comments
 (0)