|
16 | 16 |
|
17 | 17 | package org.springframework.cloud.kubernetes.client.discovery; |
18 | 18 |
|
| 19 | +import java.util.ArrayList; |
| 20 | +import java.util.List; |
| 21 | + |
19 | 22 | import io.kubernetes.client.informer.SharedIndexInformer; |
20 | 23 | import io.kubernetes.client.informer.SharedInformerFactory; |
21 | 24 | import io.kubernetes.client.informer.cache.Lister; |
|
37 | 40 | import org.springframework.cloud.client.discovery.simple.SimpleDiscoveryClientAutoConfiguration; |
38 | 41 | import org.springframework.cloud.kubernetes.client.KubernetesClientAutoConfiguration; |
39 | 42 | import org.springframework.cloud.kubernetes.commons.KubernetesNamespaceProvider; |
40 | | -import org.springframework.cloud.kubernetes.commons.config.NamespaceResolutionFailedException; |
41 | 43 | import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnBlockingOrReactiveDiscoveryEnabled; |
42 | 44 | import org.springframework.cloud.kubernetes.commons.discovery.ConditionalOnKubernetesDiscoveryEnabled; |
43 | 45 | import org.springframework.cloud.kubernetes.commons.discovery.KubernetesDiscoveryProperties; |
|
48 | 50 | import org.springframework.core.log.LogAccessor; |
49 | 51 |
|
50 | 52 | import static io.kubernetes.client.util.Namespaces.NAMESPACE_ALL; |
51 | | -import static io.kubernetes.client.util.Namespaces.NAMESPACE_DEFAULT; |
52 | 53 | import static org.springframework.cloud.kubernetes.client.KubernetesClientUtils.getApplicationNamespace; |
53 | 54 |
|
54 | 55 | /** |
|
59 | 60 | @ConditionalOnKubernetesDiscoveryEnabled |
60 | 61 | @ConditionalOnBlockingOrReactiveDiscoveryEnabled |
61 | 62 | @ConditionalOnCloudPlatform(CloudPlatform.KUBERNETES) |
62 | | -@Conditional(ConditionalOnSelectiveNamespacesMissing.class) |
63 | 63 | @AutoConfigureBefore({ SimpleDiscoveryClientAutoConfiguration.class, CommonsClientAutoConfiguration.class }) |
64 | 64 | @AutoConfigureAfter({ KubernetesClientAutoConfiguration.class, KubernetesDiscoveryPropertiesAutoConfiguration.class }) |
65 | 65 | final class KubernetesClientInformerAutoConfiguration { |
66 | 66 |
|
67 | 67 | private static final LogAccessor LOG = new LogAccessor( |
68 | | - LogFactory.getLog(KubernetesClientInformerAutoConfiguration.class)); |
| 68 | + LogFactory.getLog(KubernetesClientInformerAutoConfiguration.class)); |
69 | 69 |
|
| 70 | + // we rely on the order of namespaces to enable listers, as such provide a bean of |
| 71 | + // namespaces as a list, instead of the incoming Set. |
70 | 72 | @Bean |
71 | | - @ConditionalOnMissingBean |
72 | | - SharedInformerFactory sharedInformerFactory(ApiClient client) { |
73 | | - LOG.debug(() -> "registering sharedInformerFactory for non-selective namespaces"); |
74 | | - return new SharedInformerFactory(client); |
75 | | - } |
| 73 | + List<String> k8sDiscoveryClientNamespaces(KubernetesDiscoveryProperties properties, |
| 74 | + KubernetesNamespaceProvider provider) { |
76 | 75 |
|
77 | | - @Bean |
78 | | - String kubernetesClientNamespace(KubernetesDiscoveryProperties properties, KubernetesNamespaceProvider provider) { |
79 | | - String namespace; |
80 | 76 | if (properties.allNamespaces()) { |
81 | | - namespace = NAMESPACE_ALL; |
82 | 77 | LOG.debug(() -> "serviceSharedInformer will use all-namespaces"); |
| 78 | + return List.of(NAMESPACE_ALL); |
83 | 79 | } |
84 | | - else { |
85 | | - try { |
86 | | - namespace = getApplicationNamespace(null, "kubernetes client discovery", provider); |
87 | | - } |
88 | | - catch (NamespaceResolutionFailedException ex) { |
89 | | - LOG.warn(() -> "failed to resolve namespace, defaulting to :" + NAMESPACE_DEFAULT |
90 | | - + ". This will fail in a future release."); |
91 | | - namespace = NAMESPACE_DEFAULT; |
92 | | - } |
93 | | - LOG.debug("serviceSharedInformer will use namespace : " + namespace); |
| 80 | + |
| 81 | + if (properties.namespaces() != null && !properties.namespaces().isEmpty()) { |
| 82 | + List<String> selectiveNamespaces = properties.namespaces().stream().sorted().toList(); |
| 83 | + LOG.debug(() -> "serviceSharedInformers will use selective namespaces : " + selectiveNamespaces); |
| 84 | + return selectiveNamespaces; |
94 | 85 | } |
95 | 86 |
|
96 | | - return namespace; |
| 87 | + String namespace = getApplicationNamespace(null, "kubernetes client discovery", provider); |
| 88 | + LOG.debug(() -> "using namespace : " + namespace); |
| 89 | + return List.of(namespace); |
97 | 90 | } |
98 | 91 |
|
99 | 92 | @Bean |
100 | | - @ConditionalOnMissingBean(value = V1Service.class, parameterizedContainer = SharedIndexInformer.class) |
101 | | - SharedIndexInformer<V1Service> servicesSharedIndexInformer(SharedInformerFactory sharedInformerFactory, |
102 | | - ApiClient apiClient, String kubernetesClientNamespace) { |
| 93 | + @ConditionalOnMissingBean(value = SharedInformerFactory.class, parameterizedContainer = List.class) |
| 94 | + List<SharedInformerFactory> sharedInformerFactories(ApiClient apiClient, List<String> selectiveNamespaces) { |
103 | 95 |
|
104 | | - GenericKubernetesApi<V1Service, V1ServiceList> servicesApi = new GenericKubernetesApi<>(V1Service.class, |
105 | | - V1ServiceList.class, "", "v1", "services", apiClient); |
106 | | - |
107 | | - return sharedInformerFactory.sharedIndexInformerFor(servicesApi, V1Service.class, 0L, |
108 | | - kubernetesClientNamespace); |
| 96 | + int howManyNamespaces = selectiveNamespaces.size(); |
| 97 | + List<SharedInformerFactory> sharedInformerFactories = new ArrayList<>(howManyNamespaces); |
| 98 | + for (int i = 0; i < howManyNamespaces; ++i) { |
| 99 | + sharedInformerFactories.add(new SharedInformerFactory(apiClient)); |
| 100 | + } |
| 101 | + return sharedInformerFactories; |
109 | 102 | } |
110 | 103 |
|
111 | 104 | @Bean |
112 | | - @ConditionalOnMissingBean(value = V1Endpoints.class, parameterizedContainer = SharedIndexInformer.class) |
113 | | - SharedIndexInformer<V1Endpoints> endpointsSharedIndexInformer(SharedInformerFactory sharedInformerFactory, |
114 | | - ApiClient apiClient, String kubernetesClientNamespace) { |
| 105 | + @ConditionalOnMissingBean(value = V1Service.class, |
| 106 | + parameterizedContainer = { List.class, SharedIndexInformer.class }) |
| 107 | + List<SharedIndexInformer<V1Service>> serviceSharedIndexInformers( |
| 108 | + List<SharedInformerFactory> sharedInformerFactories, List<String> selectiveNamespaces, |
| 109 | + ApiClient apiClient) { |
| 110 | + |
| 111 | + int howManyNamespaces = selectiveNamespaces.size(); |
| 112 | + List<SharedIndexInformer<V1Service>> serviceSharedIndexedInformers = new ArrayList<>(howManyNamespaces); |
| 113 | + for (int i = 0; i < howManyNamespaces; ++i) { |
| 114 | + GenericKubernetesApi<V1Service, V1ServiceList> servicesApi = new GenericKubernetesApi<>(V1Service.class, |
| 115 | + V1ServiceList.class, "", "v1", "services", apiClient); |
| 116 | + SharedIndexInformer<V1Service> sharedIndexInformer = sharedInformerFactories.get(i) |
| 117 | + .sharedIndexInformerFor(servicesApi, V1Service.class, 0L, selectiveNamespaces.get(i)); |
| 118 | + serviceSharedIndexedInformers.add(sharedIndexInformer); |
| 119 | + } |
| 120 | + return serviceSharedIndexedInformers; |
| 121 | + } |
115 | 122 |
|
116 | | - GenericKubernetesApi<V1Endpoints, V1EndpointsList> servicesApi = new GenericKubernetesApi<>(V1Endpoints.class, |
117 | | - V1EndpointsList.class, "", "v1", "endpoints", apiClient); |
| 123 | + @Bean |
| 124 | + @ConditionalOnMissingBean(value = V1Service.class, parameterizedContainer = { List.class, Lister.class }) |
| 125 | + List<Lister<V1Service>> serviceListers(List<String> selectiveNamespaces, |
| 126 | + List<SharedIndexInformer<V1Service>> serviceSharedIndexInformers) { |
| 127 | + |
| 128 | + int howManyNamespaces = selectiveNamespaces.size(); |
| 129 | + List<Lister<V1Service>> serviceListers = new ArrayList<>(howManyNamespaces); |
| 130 | + |
| 131 | + for (int i = 0; i < howManyNamespaces; ++i) { |
| 132 | + String namespace = selectiveNamespaces.get(i); |
| 133 | + Lister<V1Service> lister = new Lister<>(serviceSharedIndexInformers.get(i).getIndexer(), namespace); |
| 134 | + LOG.debug(() -> "registering lister (for services) in namespace : " + namespace); |
| 135 | + serviceListers.add(lister); |
| 136 | + } |
118 | 137 |
|
119 | | - return sharedInformerFactory.sharedIndexInformerFor(servicesApi, V1Endpoints.class, 0L, |
120 | | - kubernetesClientNamespace); |
| 138 | + return serviceListers; |
121 | 139 | } |
122 | 140 |
|
123 | 141 | @Bean |
124 | | - @ConditionalOnMissingBean(value = V1Service.class, parameterizedContainer = Lister.class) |
125 | | - Lister<V1Service> servicesLister(SharedIndexInformer<V1Service> servicesSharedIndexInformer, |
126 | | - String kubernetesClientNamespace) { |
127 | | - return new Lister<>(servicesSharedIndexInformer.getIndexer(), kubernetesClientNamespace); |
| 142 | + @ConditionalOnMissingBean(value = V1Endpoints.class, |
| 143 | + parameterizedContainer = { List.class, SharedIndexInformer.class }) |
| 144 | + List<SharedIndexInformer<V1Endpoints>> endpointsSharedIndexInformers( |
| 145 | + List<SharedInformerFactory> sharedInformerFactories, List<String> selectiveNamespaces, |
| 146 | + ApiClient apiClient) { |
| 147 | + |
| 148 | + int howManyNamespaces = selectiveNamespaces.size(); |
| 149 | + List<SharedIndexInformer<V1Endpoints>> endpointsSharedIndexedInformers = new ArrayList<>(howManyNamespaces); |
| 150 | + for (int i = 0; i < howManyNamespaces; ++i) { |
| 151 | + GenericKubernetesApi<V1Endpoints, V1EndpointsList> endpointsApi = new GenericKubernetesApi<>( |
| 152 | + V1Endpoints.class, V1EndpointsList.class, "", "v1", "endpoints", apiClient); |
| 153 | + SharedIndexInformer<V1Endpoints> sharedIndexInformer = sharedInformerFactories.get(i) |
| 154 | + .sharedIndexInformerFor(endpointsApi, V1Endpoints.class, 0L, selectiveNamespaces.get(i)); |
| 155 | + endpointsSharedIndexedInformers.add(sharedIndexInformer); |
| 156 | + } |
| 157 | + return endpointsSharedIndexedInformers; |
128 | 158 | } |
129 | 159 |
|
130 | 160 | @Bean |
131 | | - @ConditionalOnMissingBean(value = V1Endpoints.class, parameterizedContainer = Lister.class) |
132 | | - Lister<V1Endpoints> endpointsLister(SharedIndexInformer<V1Endpoints> endpointsSharedIndexInformer, |
133 | | - String kubernetesClientNamespace) { |
134 | | - return new Lister<>(endpointsSharedIndexInformer.getIndexer(), kubernetesClientNamespace); |
| 161 | + @ConditionalOnMissingBean(value = V1Endpoints.class, parameterizedContainer = { List.class, Lister.class }) |
| 162 | + List<Lister<V1Endpoints>> endpointsListers(List<String> selectiveNamespaces, |
| 163 | + List<SharedIndexInformer<V1Endpoints>> serviceSharedIndexInformers) { |
| 164 | + |
| 165 | + int howManyNamespaces = selectiveNamespaces.size(); |
| 166 | + List<Lister<V1Endpoints>> endpointsListers = new ArrayList<>(howManyNamespaces); |
| 167 | + |
| 168 | + for (int i = 0; i < howManyNamespaces; ++i) { |
| 169 | + String namespace = selectiveNamespaces.get(i); |
| 170 | + Lister<V1Endpoints> lister = new Lister<>(serviceSharedIndexInformers.get(i).getIndexer()); |
| 171 | + LOG.debug(() -> "registering lister (for endpoints) in namespace : " + namespace); |
| 172 | + endpointsListers.add(lister); |
| 173 | + } |
| 174 | + |
| 175 | + return endpointsListers; |
135 | 176 | } |
136 | 177 |
|
137 | 178 | } |
0 commit comments