Skip to content

Commit 2676f2d

Browse files
author
Dave Syer
committed
Re-instate annotations but mark them as deprecated
1 parent 3f32573 commit 2676f2d

16 files changed

+1360
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
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.common.KubernetesObject;
16+
import io.kubernetes.client.informer.SharedIndexInformer;
17+
import io.kubernetes.client.informer.SharedInformer;
18+
import io.kubernetes.client.informer.SharedInformerFactory;
19+
import io.kubernetes.client.informer.cache.Lister;
20+
import io.kubernetes.client.openapi.ApiClient;
21+
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformer;
22+
import io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers;
23+
import io.kubernetes.client.spring.extended.controller.config.KubernetesInformerProperties;
24+
import io.kubernetes.client.util.generic.GenericKubernetesApi;
25+
import org.slf4j.Logger;
26+
import org.slf4j.LoggerFactory;
27+
import org.springframework.beans.BeansException;
28+
import org.springframework.beans.factory.BeanFactory;
29+
import org.springframework.beans.factory.BeanFactoryAware;
30+
import org.springframework.beans.factory.annotation.Autowired;
31+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
32+
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
33+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
34+
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
35+
import org.springframework.beans.factory.support.RootBeanDefinition;
36+
import org.springframework.core.Ordered;
37+
import org.springframework.core.ResolvableType;
38+
import org.springframework.core.annotation.AnnotatedElementUtils;
39+
40+
/**
41+
* The type Kubernetes informer factory processor which basically does the following things:
42+
*
43+
* <p>1. By-pass further processing if there's no SharedInformerFactory registered. 2. Instansiate a
44+
* new ApiClient if there's no user-specified one for override. 3. By reading from {@link
45+
* io.kubernetes.client.spring.extended.controller.annotation.KubernetesInformers}, instantiates and
46+
* injects informers to spring context with the underlying constructing process hidden from users.
47+
*
48+
* @deprecated instead of declaring via the annotation create the informers manually as {@link
49+
* org.springframework.context.annotation.Bean @Beans}
50+
*/
51+
@Deprecated
52+
public class KubernetesInformerFactoryProcessor
53+
implements BeanDefinitionRegistryPostProcessor, BeanFactoryAware, Ordered {
54+
55+
private static final Logger log =
56+
LoggerFactory.getLogger(KubernetesInformerFactoryProcessor.class);
57+
58+
public static final int ORDER = 0;
59+
60+
@Autowired private KubernetesInformerProperties informerProperties;
61+
62+
private ConfigurableListableBeanFactory beanFactory;
63+
64+
@Override
65+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory)
66+
throws BeansException {}
67+
68+
@Override
69+
public int getOrder() {
70+
return 0;
71+
}
72+
73+
@Override
74+
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry)
75+
throws BeansException {
76+
if (!(registry instanceof BeanFactory)) {
77+
return;
78+
}
79+
for (String name : registry.getBeanDefinitionNames()) {
80+
KubernetesInformers kubernetesInformers = null;
81+
Class<?> cls = ((BeanFactory) registry).getType(name);
82+
if (cls != null) {
83+
kubernetesInformers =
84+
AnnotatedElementUtils.getMergedAnnotation(cls, KubernetesInformers.class);
85+
}
86+
if (kubernetesInformers == null) {
87+
kubernetesInformers = beanFactory.findAnnotationOnBean(name, KubernetesInformers.class);
88+
}
89+
if (kubernetesInformers == null) {
90+
continue;
91+
}
92+
if (kubernetesInformers.value().length > 0) {
93+
for (KubernetesInformer kubernetesInformer : kubernetesInformers.value()) {
94+
registerInformer(registry, kubernetesInformer);
95+
registerLister(registry, kubernetesInformer);
96+
}
97+
}
98+
}
99+
}
100+
101+
private void registerInformer(
102+
BeanDefinitionRegistry registry, KubernetesInformer kubernetesInformer) {
103+
RootBeanDefinition informerBean =
104+
(RootBeanDefinition)
105+
BeanDefinitionBuilder.rootBeanDefinition(SharedInformer.class).getBeanDefinition();
106+
informerBean.setInstanceSupplier(
107+
() -> informer(kubernetesInformer.apiTypeClass(), kubernetesInformer));
108+
ResolvableType informerType =
109+
ResolvableType.forClassWithGenerics(
110+
SharedIndexInformer.class, kubernetesInformer.apiTypeClass());
111+
informerBean.setTargetType(informerType);
112+
registry.registerBeanDefinition(
113+
getInformerBeanName(kubernetesInformer.apiTypeClass()), informerBean);
114+
}
115+
116+
private String getInformerBeanName(Class<?> type) {
117+
return type.getName() + "Informer";
118+
}
119+
120+
private void registerLister(
121+
BeanDefinitionRegistry registry, KubernetesInformer kubernetesInformer) {
122+
RootBeanDefinition listerBean =
123+
(RootBeanDefinition)
124+
BeanDefinitionBuilder.rootBeanDefinition(Lister.class).getBeanDefinition();
125+
listerBean.setInstanceSupplier(() -> lister(kubernetesInformer.apiTypeClass()));
126+
ResolvableType listerType =
127+
ResolvableType.forClassWithGenerics(Lister.class, kubernetesInformer.apiTypeClass());
128+
listerBean.setTargetType(listerType);
129+
registry.registerBeanDefinition(listerType.toString(), listerBean);
130+
}
131+
132+
@SuppressWarnings({"unchecked", "rawtypes"})
133+
private <T extends KubernetesObject> Lister<T> lister(Class<T> type) {
134+
SharedIndexInformer sharedInformer =
135+
this.beanFactory.getBean(getInformerBeanName(type), SharedIndexInformer.class);
136+
Lister<T> lister = new Lister<>(sharedInformer.getIndexer());
137+
return lister;
138+
}
139+
140+
@SuppressWarnings({"unchecked", "rawtypes"})
141+
private <T extends KubernetesObject> SharedInformer<T> informer(
142+
Class<T> type, KubernetesInformer kubernetesInformer) {
143+
ApiClient apiClient = this.beanFactory.getBean(ApiClient.class);
144+
145+
if (apiClient.getHttpClient().readTimeoutMillis() > 0) {
146+
log.warn(
147+
"Enforcing read-timeout of the ApiClient {} to {} so that the watch connection won't abort from client-side",
148+
apiClient,
149+
informerProperties.getClientReadTimeout());
150+
apiClient.setHttpClient(
151+
apiClient
152+
.getHttpClient()
153+
.newBuilder()
154+
.readTimeout(informerProperties.getClientReadTimeout())
155+
.build());
156+
}
157+
158+
SharedInformerFactory sharedInformerFactory =
159+
this.beanFactory.getBean(SharedInformerFactory.class);
160+
final GenericKubernetesApi api =
161+
new GenericKubernetesApi(
162+
kubernetesInformer.apiTypeClass(),
163+
kubernetesInformer.apiListTypeClass(),
164+
kubernetesInformer.groupVersionResource().apiGroup(),
165+
kubernetesInformer.groupVersionResource().apiVersion(),
166+
kubernetesInformer.groupVersionResource().resourcePlural(),
167+
apiClient);
168+
SharedIndexInformer<T> sharedIndexInformer =
169+
sharedInformerFactory.sharedIndexInformerFor(
170+
api, type, kubernetesInformer.resyncPeriodMillis(), kubernetesInformer.namespace());
171+
return sharedIndexInformer;
172+
}
173+
174+
@Override
175+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
176+
this.beanFactory = (ConfigurableListableBeanFactory) beanFactory;
177+
}
178+
}
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
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 static org.springframework.util.Assert.notNull;
16+
17+
import io.kubernetes.client.extended.controller.reconciler.Reconciler;
18+
import io.kubernetes.client.informer.SharedInformerFactory;
19+
import io.kubernetes.client.spring.extended.controller.factory.KubernetesControllerFactory;
20+
import java.util.function.Supplier;
21+
import org.springframework.beans.factory.config.BeanDefinition;
22+
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
23+
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
24+
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
25+
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
26+
import org.springframework.core.Ordered;
27+
28+
/**
29+
* Scans and processes {@link
30+
* io.kubernetes.client.spring.extended.controller.annotation.KubernetesReconciler}.
31+
*
32+
* <p>It will create a {@link io.kubernetes.client.extended.controller.Controller} for every
33+
* reconciler instances registered in the spring bean-factory.
34+
*
35+
* @deprecated instead of declaring via the annotation create the controller manually as a {@link
36+
* org.springframework.context.annotation.Bean @Bean}
37+
*/
38+
@Deprecated
39+
public class KubernetesReconcilerProcessor implements BeanDefinitionRegistryPostProcessor, Ordered {
40+
41+
public static final String DEFAULT_SHARED_INFORMER_FACTORY_BEAN_NAME = "sharedInformerFactory";
42+
43+
private final String sharedInformerFactoryBeanName;
44+
45+
private BeanDefinitionRegistry beanDefinitionRegistry;
46+
47+
public KubernetesReconcilerProcessor() {
48+
this(DEFAULT_SHARED_INFORMER_FACTORY_BEAN_NAME);
49+
}
50+
51+
public KubernetesReconcilerProcessor(String sharedInformerFactoryBeanName) {
52+
notNull(sharedInformerFactoryBeanName, "SharedInformerFactory bean name is required");
53+
this.sharedInformerFactoryBeanName = sharedInformerFactoryBeanName;
54+
}
55+
56+
@Override
57+
public int getOrder() {
58+
return KubernetesInformerFactoryProcessor.ORDER + 1;
59+
}
60+
61+
@Override
62+
public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) {
63+
this.beanDefinitionRegistry = registry;
64+
}
65+
66+
@Override
67+
public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
68+
for (String reconcilerName : beanFactory.getBeanNamesForType(Reconciler.class)) {
69+
70+
Supplier<KubernetesControllerFactory> kubernetesControllerFactorySupplier =
71+
() ->
72+
new KubernetesControllerFactory(
73+
beanFactory.getBean(sharedInformerFactoryBeanName, SharedInformerFactory.class),
74+
beanFactory.getBean(reconcilerName, Reconciler.class));
75+
76+
BeanDefinition controllerFactoryBeanDefinition =
77+
BeanDefinitionBuilder.genericBeanDefinition(
78+
KubernetesControllerFactory.class, kubernetesControllerFactorySupplier)
79+
.getBeanDefinition();
80+
81+
beanDefinitionRegistry.registerBeanDefinition(
82+
reconcilerName + "Controller", controllerFactoryBeanDefinition);
83+
}
84+
}
85+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
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.annotation;
14+
15+
import io.kubernetes.client.common.KubernetesObject;
16+
import java.lang.annotation.ElementType;
17+
import java.lang.annotation.Retention;
18+
import java.lang.annotation.RetentionPolicy;
19+
import java.lang.annotation.Target;
20+
21+
/**
22+
* Indicates that the method is a filter for {@link io.kubernetes.client.informer.EventType#ADDED}
23+
* from watches.
24+
*
25+
* <p>A add-event filter must have the signature as {@link java.util.function.Predicate<ApiType>}
26+
*
27+
* @deprecated register the watcher via the {@link
28+
* io.kubernetes.client.extended.controller.builder.ControllerBuilder} API
29+
*/
30+
@Deprecated
31+
@Target({ElementType.METHOD})
32+
@Retention(RetentionPolicy.RUNTIME)
33+
public @interface AddWatchEventFilter {
34+
Class<? extends KubernetesObject> apiTypeClass();
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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.annotation;
14+
15+
import io.kubernetes.client.common.KubernetesObject;
16+
import java.lang.annotation.ElementType;
17+
import java.lang.annotation.Retention;
18+
import java.lang.annotation.RetentionPolicy;
19+
import java.lang.annotation.Target;
20+
21+
/**
22+
* Indicates that the method is a filter for {@link
23+
* io.kubernetes.client.informer.EventType#MODIFIED} from watches.
24+
*
25+
* <p>A update-event filter must have the signature as {@link
26+
* java.util.function.BiPredicate<ApiType, Boolean>} where the 1st parameter is the
27+
* "before-deletion" state of the resource and the 2nd indicates whether the cache entry for the
28+
* resource is stale.
29+
*
30+
* @deprecated register the watcher via the {@link
31+
* io.kubernetes.client.extended.controller.builder.ControllerBuilder} API
32+
*/
33+
@Deprecated
34+
@Target({ElementType.METHOD})
35+
@Retention(RetentionPolicy.RUNTIME)
36+
public @interface DeleteWatchEventFilter {
37+
Class<? extends KubernetesObject> apiTypeClass();
38+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
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.annotation;
14+
15+
import java.lang.annotation.ElementType;
16+
import java.lang.annotation.Retention;
17+
import java.lang.annotation.RetentionPolicy;
18+
import java.lang.annotation.Target;
19+
20+
/**
21+
* The standard Kubernetes group-version-resource.
22+
*
23+
* @deprecated use the {@link io.kubernetes.client.util.generic.GenericKubernetesApi} instead
24+
*/
25+
@Deprecated
26+
@Target({ElementType.TYPE})
27+
@Retention(RetentionPolicy.RUNTIME)
28+
public @interface GroupVersionResource {
29+
30+
/**
31+
* Api group string. e.g. "batch"
32+
*
33+
* @return the string
34+
*/
35+
String apiGroup() default "";
36+
37+
/**
38+
* Api version string. e.g. "v1"
39+
*
40+
* @return the string
41+
*/
42+
String apiVersion() default "v1";
43+
44+
/**
45+
* Resource plural string. e.g. "jobs"
46+
*
47+
* @return the string
48+
*/
49+
String resourcePlural() default "namespaces";
50+
}

0 commit comments

Comments
 (0)