/
KubernetesInformerFactoryProcessor.java
139 lines (127 loc) · 6.15 KB
/
KubernetesInformerFactoryProcessor.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
Copyright 2020 The Kubernetes 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.kubernetes.client.spring.extended.controller;
import io.kubernetes.client.common.KubernetesObject;
import io.kubernetes.client.informer.SharedIndexInformer;
import io.kubernetes.client.informer.SharedInformer;
import io.kubernetes.client.informer.SharedInformerFactory;
import io.kubernetes.client.informer.cache.Lister;
import io.kubernetes.client.openapi.ApiClient;
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
import io.kubernetes.client.util.generic.GenericKubernetesApi;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.core.Ordered;
import org.springframework.core.ResolvableType;
import org.springframework.core.annotation.AnnotatedElementUtils;
/**
* The type Kubernetes informer factory processor which basically does the following things:
*
* <p>1. By-pass further processing if there's no SharedInformerFactory registered. 2. Instansiate a
* new ApiClient if there's no user-specified one for override. 3. By reading from {@link
* io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers}, instantiates and
* injects informers to spring context with the underlying constructing process hidden from users.
*/
public class KubernetesInformerFactoryProcessor
implements BeanDefinitionRegistryPostProcessor, Ordered {
public static final int ORDER = 0;
private ConfigurableListableBeanFactory beanFactory;
@Override
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
throws BeansException {
this.beanFactory = beanFactory;
}
@Override
public int getOrder() {
return 0;
}
@Override
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
throws BeansException {
if (registry instanceof BeanFactory) {
for (String name : registry.getBeanDefinitionNames()) {
Class<?> cls = ((BeanFactory) registry).getType(name);
if (cls != null) {
KubernetesInformers kubernetesInformers =
AnnotatedElementUtils.getMergedAnnotation(cls, KubernetesInformers.class);
if (kubernetesInformers != null && kubernetesInformers.value().length > 0) {
for (KubernetesInformer kubernetesInformer : kubernetesInformers.value()) {
registerInformer(registry, kubernetesInformer);
registerLister(registry, kubernetesInformer);
}
}
}
}
}
}
private void registerInformer(
BeanDefinitionRegistry registry, KubernetesInformer kubernetesInformer) {
RootBeanDefinition informerBean =
(RootBeanDefinition)
BeanDefinitionBuilder.rootBeanDefinition(SharedInformer.class).getBeanDefinition();
informerBean.setInstanceSupplier(
() -> informer(kubernetesInformer.apiTypeClass(), kubernetesInformer));
ResolvableType informerType =
ResolvableType.forClassWithGenerics(
SharedIndexInformer.class, kubernetesInformer.apiTypeClass());
informerBean.setTargetType(informerType);
registry.registerBeanDefinition(
getInformerBeanName(kubernetesInformer.apiTypeClass()), informerBean);
}
private String getInformerBeanName(Class<?> type) {
return type.getName() + "Informer";
}
private void registerLister(
BeanDefinitionRegistry registry, KubernetesInformer kubernetesInformer) {
RootBeanDefinition listerBean =
(RootBeanDefinition)
BeanDefinitionBuilder.rootBeanDefinition(Lister.class).getBeanDefinition();
listerBean.setInstanceSupplier(() -> lister(kubernetesInformer.apiTypeClass()));
ResolvableType listerType =
ResolvableType.forClassWithGenerics(Lister.class, kubernetesInformer.apiTypeClass());
listerBean.setTargetType(listerType);
registry.registerBeanDefinition(listerType.toString(), listerBean);
}
@SuppressWarnings({"unchecked", "rawtypes"})
private <T extends KubernetesObject> Lister<T> lister(Class<T> type) {
SharedIndexInformer sharedInformer =
this.beanFactory.getBean(getInformerBeanName(type), SharedIndexInformer.class);
Lister<T> lister = new Lister<>(sharedInformer.getIndexer());
return lister;
}
@SuppressWarnings({"unchecked", "rawtypes"})
private <T extends KubernetesObject> SharedInformer<T> informer(
Class<T> type, KubernetesInformer kubernetesInformer) {
ApiClient apiClient = this.beanFactory.getBean(ApiClient.class);
SharedInformerFactory sharedInformerFactory =
this.beanFactory.getBean(SharedInformerFactory.class);
final GenericKubernetesApi api =
new GenericKubernetesApi(
kubernetesInformer.apiTypeClass(),
kubernetesInformer.apiListTypeClass(),
kubernetesInformer.groupVersionResource().apiGroup(),
kubernetesInformer.groupVersionResource().apiVersion(),
kubernetesInformer.groupVersionResource().resourcePlural(),
apiClient);
SharedIndexInformer<T> sharedIndexInformer =
sharedInformerFactory.sharedIndexInformerFor(
api, type, kubernetesInformer.resyncPeriodMillis(), kubernetesInformer.namespace());
return sharedIndexInformer;
}
}