Skip to content

Commit 318bdc1

Browse files
Merge remote-tracking branch 'upstream/master' into ownerref
2 parents d3f9bdb + ffb7dee commit 318bdc1

File tree

18 files changed

+383
-19
lines changed

18 files changed

+383
-19
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
.settings/
66
.project
77
.vscode/
8+
.attach_pid*
89

910
# Maven builds
1011
*/target/

extended/src/main/java/io/kubernetes/client/extended/event/legacy/EventUtils.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
package io.kubernetes.client.extended.event.legacy;
1414

1515
import io.kubernetes.client.openapi.models.CoreV1Event;
16-
import org.apache.commons.lang.RandomStringUtils;
16+
import org.apache.commons.lang3.RandomStringUtils;
1717
import org.apache.commons.lang3.tuple.MutablePair;
1818
import org.joda.time.DateTime;
1919

extended/src/main/java/io/kubernetes/client/extended/kubectl/KubectlAnnotate.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
import io.kubernetes.client.util.generic.KubernetesApiResponse;
2121
import java.util.HashMap;
2222
import java.util.Map;
23-
import org.apache.commons.lang.StringUtils;
23+
import org.apache.commons.lang3.StringUtils;
2424

2525
public class KubectlAnnotate<ApiType extends KubernetesObject>
2626
extends Kubectl.ResourceBuilder<ApiType, KubectlAnnotate<ApiType>>

extended/src/main/java/io/kubernetes/client/extended/kubectl/KubectlDelete.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
import io.kubernetes.client.extended.kubectl.exception.KubectlException;
1717
import io.kubernetes.client.openapi.ApiException;
1818
import io.kubernetes.client.util.ModelMapper;
19-
import org.apache.commons.lang.StringUtils;
19+
import org.apache.commons.lang3.StringUtils;
2020

2121
public class KubectlDelete<ApiType extends KubernetesObject>
2222
extends Kubectl.ResourceBuilder<ApiType, KubectlDelete<ApiType>>

extended/src/main/java/io/kubernetes/client/extended/kubectl/KubectlGet.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import io.kubernetes.client.util.generic.GenericKubernetesApi;
2020
import io.kubernetes.client.util.generic.options.ListOptions;
2121
import java.util.List;
22-
import org.apache.commons.lang.StringUtils;
22+
import org.apache.commons.lang3.StringUtils;
2323

2424
public class KubectlGet<ApiType extends KubernetesObject>
2525
extends Kubectl.ApiClientBuilder<KubectlGet<ApiType>>

extended/src/main/java/io/kubernetes/client/extended/kubectl/KubectlLabel.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
import io.kubernetes.client.util.labels.Labels;
2020
import java.util.HashMap;
2121
import java.util.Map;
22-
import org.apache.commons.lang.StringUtils;
22+
import org.apache.commons.lang3.StringUtils;
2323

2424
public class KubectlLabel<ApiType extends KubernetesObject>
2525
extends Kubectl.ResourceBuilder<ApiType, KubectlLabel<ApiType>>

extended/src/main/java/io/kubernetes/client/extended/kubectl/KubectlReplace.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
import io.kubernetes.client.openapi.ApiException;
1818
import io.kubernetes.client.util.ModelMapper;
1919
import io.kubernetes.client.util.generic.options.UpdateOptions;
20-
import org.apache.commons.lang.StringUtils;
20+
import org.apache.commons.lang3.StringUtils;
2121

2222
public class KubectlReplace<ApiType extends KubernetesObject>
2323
extends Kubectl.ResourceBuilder<ApiType, KubectlReplace<ApiType>>

kubernetes/pom.xml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@
141141
<dependency>
142142
<groupId>io.sundr</groupId>
143143
<artifactId>builder-annotations</artifactId>
144+
<optional>true</optional>
144145
</dependency>
145146
<dependency>
146147
<groupId>javax.annotation</groupId>
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
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.manifests;
14+
15+
import com.google.common.io.Resources;
16+
import io.kubernetes.client.spring.extended.manifests.annotation.FromYaml;
17+
import io.kubernetes.client.util.Yaml;
18+
import java.io.IOException;
19+
import java.lang.reflect.Field;
20+
import java.nio.file.Files;
21+
import java.nio.file.Path;
22+
import java.nio.file.Paths;
23+
import org.slf4j.Logger;
24+
import org.slf4j.LoggerFactory;
25+
import org.springframework.beans.BeansException;
26+
import org.springframework.beans.factory.BeanCreationException;
27+
import org.springframework.beans.factory.BeanFactory;
28+
import org.springframework.beans.factory.BeanFactoryAware;
29+
import org.springframework.beans.factory.ListableBeanFactory;
30+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
31+
import org.springframework.beans.factory.config.BeanPostProcessor;
32+
import org.springframework.beans.factory.config.InstantiationAwareBeanPostProcessor;
33+
import org.springframework.util.ReflectionUtils;
34+
import org.yaml.snakeyaml.error.YAMLException;
35+
36+
public class KubernetesFromYamlProcessor
37+
implements InstantiationAwareBeanPostProcessor, BeanPostProcessor, BeanFactoryAware {
38+
39+
private static final Logger log = LoggerFactory.getLogger(KubernetesFromYamlProcessor.class);
40+
41+
private ListableBeanFactory beanFactory;
42+
43+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
44+
45+
FromYaml fromYamlAnnotation;
46+
try {
47+
fromYamlAnnotation = beanFactory.findAnnotationOnBean(beanName, FromYaml.class);
48+
if (fromYamlAnnotation != null) {
49+
Object loadedObj = loadFromYaml(fromYamlAnnotation.filePath());
50+
if (!bean.getClass().isAssignableFrom(loadedObj.getClass())) {
51+
log.warn(
52+
"Incompatible types for @FromYaml, {} cannot apply to {}",
53+
fromYamlAnnotation.filePath(),
54+
bean.getClass());
55+
return bean;
56+
}
57+
return loadedObj;
58+
}
59+
} catch (NoSuchBeanDefinitionException e) {
60+
return bean;
61+
}
62+
63+
for (Field field : bean.getClass().getDeclaredFields()) {
64+
ReflectionUtils.makeAccessible(field);
65+
try {
66+
if (field.get(bean) != null) {
67+
continue; // field already set, skip processing
68+
}
69+
} catch (IllegalAccessException e) {
70+
log.warn("Failed inject resource for @FromYaml annotated field {}", field, e);
71+
continue;
72+
}
73+
74+
fromYamlAnnotation = field.getAnnotation(FromYaml.class);
75+
if (fromYamlAnnotation == null) {
76+
continue; // skip if the field doesn't have the annotation
77+
}
78+
79+
Object loadedObj = loadFromYaml(fromYamlAnnotation.filePath());
80+
ReflectionUtils.setField(field, bean, loadedObj);
81+
}
82+
return bean;
83+
}
84+
85+
@Override
86+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
87+
this.beanFactory = (ListableBeanFactory) beanFactory;
88+
}
89+
90+
private Object loadFromYaml(String targetFilePath) {
91+
Path targetPath = Paths.get(targetFilePath);
92+
if (!Files.exists(Paths.get(targetFilePath))) { // checks if it exists on the machine
93+
// otherwise use load from classpath resources
94+
Path classPath = Paths.get(Resources.getResource(targetFilePath).getPath());
95+
if (Files.exists(classPath)) { // use classpath it works
96+
targetPath = classPath;
97+
} else {
98+
throw new BeanCreationException(
99+
"No such file " + targetFilePath + " either on the machine or classpaths");
100+
}
101+
}
102+
103+
try {
104+
String yamlContent = new String(Files.readAllBytes(targetPath));
105+
Object loadedObj = Yaml.load(yamlContent);
106+
return loadedObj;
107+
} catch (IOException e) {
108+
log.error("Failed reading resource for @FromYaml annotated from {}", targetFilePath, e);
109+
throw new BeanCreationException("Failed reading Yaml resource from file", e);
110+
} catch (YAMLException e) {
111+
log.error("Failed parsing yaml file {}", targetFilePath, e);
112+
throw new BeanCreationException("Failed parsing Yaml", e);
113+
}
114+
}
115+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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.manifests;
14+
15+
import io.kubernetes.client.common.KubernetesObject;
16+
import io.kubernetes.client.extended.kubectl.Kubectl;
17+
import io.kubernetes.client.extended.kubectl.exception.KubectlException;
18+
import io.kubernetes.client.openapi.ApiClient;
19+
import io.kubernetes.client.spring.extended.manifests.annotation.KubectlApply;
20+
import org.slf4j.Logger;
21+
import org.slf4j.LoggerFactory;
22+
import org.springframework.beans.BeansException;
23+
import org.springframework.beans.factory.BeanCreationException;
24+
import org.springframework.beans.factory.BeanFactory;
25+
import org.springframework.beans.factory.BeanFactoryAware;
26+
import org.springframework.beans.factory.ListableBeanFactory;
27+
import org.springframework.beans.factory.annotation.Autowired;
28+
import org.springframework.beans.factory.config.BeanPostProcessor;
29+
30+
public class KubernetesKubectlApplyProcessor implements BeanPostProcessor, BeanFactoryAware {
31+
32+
private static final Logger log = LoggerFactory.getLogger(KubernetesKubectlApplyProcessor.class);
33+
34+
private ListableBeanFactory beanFactory;
35+
36+
@Autowired private ApiClient apiClient;
37+
38+
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
39+
if (!(bean instanceof KubernetesObject)) {
40+
return bean; // no-op
41+
}
42+
43+
KubectlApply apply = beanFactory.findAnnotationOnBean(beanName, KubectlApply.class);
44+
if (apply == null) {
45+
return bean;
46+
}
47+
48+
Class<? extends KubernetesObject> apiTypeClass =
49+
(Class<? extends KubernetesObject>) bean.getClass();
50+
51+
try {
52+
log.info("@KubectlApply ensuring resource upon bean {}", beanName);
53+
return apply(apiTypeClass, bean);
54+
} catch (KubectlException e) {
55+
log.error("Failed ensuring resource from @KubectlApply", e);
56+
throw new BeanCreationException("Failed ensuring resource from @KubectlApply", e);
57+
}
58+
}
59+
60+
public <ApiType extends KubernetesObject> ApiType apply(Class<ApiType> apiTypeClass, Object obj)
61+
throws KubectlException {
62+
return Kubectl.apply(apiTypeClass)
63+
.apiClient(this.apiClient)
64+
.resource((ApiType) obj)
65+
.execute(); // replaced the bean of the created status
66+
}
67+
68+
@Override
69+
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
70+
this.beanFactory = (ListableBeanFactory) beanFactory;
71+
}
72+
}

0 commit comments

Comments
 (0)