22
33import java .util .List ;
44import java .util .Map ;
5+ import java .util .Objects ;
56import java .util .Optional ;
67
78import io .fabric8 .kubernetes .api .model .Container ;
9+ import io .fabric8 .kubernetes .api .model .EnvVar ;
810import io .fabric8 .kubernetes .api .model .GenericKubernetesResource ;
911import io .fabric8 .kubernetes .api .model .PodTemplateSpec ;
1012import io .fabric8 .kubernetes .api .model .Quantity ;
1113import io .fabric8 .kubernetes .api .model .ResourceRequirements ;
1214
1315/**
14- * Sanitizes the {@link ResourceRequirements} in the containers of a pair of {@link PodTemplateSpec}
15- * instances.
16+ * Sanitizes the {@link ResourceRequirements} and the {@link EnvVar} in the containers of a pair of
17+ * {@link PodTemplateSpec} instances.
1618 *
1719 * <p>When the sanitizer finds a mismatch in the structure of the given templates, before it gets to
18- * the nested resource limits and requests , it returns early without fixing the actual map. This is
19- * an optimization because the given templates will anyway differ at this point. This means we do
20- * not have to attempt to sanitize the resources for these use cases, since there will anyway be an
21- * update of the K8s resource.
20+ * the nested fields , it returns early without fixing the actual map. This is an optimization
21+ * because the given templates will anyway differ at this point. This means we do not have to
22+ * attempt to sanitize the fields for these use cases, since there will anyway be an update of the
23+ * K8s resource.
2224 *
2325 * <p>The algorithm traverses the whole template structure because we need the actual and desired
24- * {@link Quantity} instances to compare their numerical amount . Using the {@link
26+ * {@link Quantity} and {@link EnvVar} instances . Using the {@link
2527 * GenericKubernetesResource#get(Map, Object...)} shortcut would need to create new instances just
2628 * for the sanitization check.
2729 */
28- class ResourceRequirementsSanitizer {
30+ class PodTemplateSpecSanitizer {
2931
30- static void sanitizeResourceRequirements (
32+ static void sanitizePodTemplateSpec (
3133 final Map <String , Object > actualMap ,
3234 final PodTemplateSpec actualTemplate ,
3335 final PodTemplateSpec desiredTemplate ) {
@@ -37,31 +39,37 @@ static void sanitizeResourceRequirements(
3739 if (actualTemplate .getSpec () == null || desiredTemplate .getSpec () == null ) {
3840 return ;
3941 }
40- sanitizeResourceRequirements (
42+ sanitizePodTemplateSpec (
4143 actualMap ,
4244 actualTemplate .getSpec ().getInitContainers (),
4345 desiredTemplate .getSpec ().getInitContainers (),
4446 "initContainers" );
45- sanitizeResourceRequirements (
47+ sanitizePodTemplateSpec (
4648 actualMap ,
4749 actualTemplate .getSpec ().getContainers (),
4850 desiredTemplate .getSpec ().getContainers (),
4951 "containers" );
5052 }
5153
52- private static void sanitizeResourceRequirements (
54+ private static void sanitizePodTemplateSpec (
5355 final Map <String , Object > actualMap ,
5456 final List <Container > actualContainers ,
5557 final List <Container > desiredContainers ,
5658 final String containerPath ) {
5759 int containers = desiredContainers .size ();
5860 if (containers == actualContainers .size ()) {
5961 for (int containerIndex = 0 ; containerIndex < containers ; containerIndex ++) {
60- var desiredContainer = desiredContainers .get (containerIndex );
61- var actualContainer = actualContainers .get (containerIndex );
62+ final var desiredContainer = desiredContainers .get (containerIndex );
63+ final var actualContainer = actualContainers .get (containerIndex );
6264 if (!desiredContainer .getName ().equals (actualContainer .getName ())) {
6365 return ;
6466 }
67+ sanitizeEnvVars (
68+ actualMap ,
69+ actualContainer .getEnv (),
70+ desiredContainer .getEnv (),
71+ containerPath ,
72+ containerIndex );
6573 sanitizeResourceRequirements (
6674 actualMap ,
6775 actualContainer .getResources (),
@@ -121,7 +129,7 @@ private static void sanitizeQuantities(
121129 m ->
122130 actualResource .forEach (
123131 (key , actualQuantity ) -> {
124- var desiredQuantity = desiredResource .get (key );
132+ final var desiredQuantity = desiredResource .get (key );
125133 if (desiredQuantity == null ) {
126134 return ;
127135 }
@@ -138,4 +146,53 @@ private static void sanitizeQuantities(
138146 }
139147 }));
140148 }
149+
150+ @ SuppressWarnings ("unchecked" )
151+ private static void sanitizeEnvVars (
152+ final Map <String , Object > actualMap ,
153+ final List <EnvVar > actualEnvVars ,
154+ final List <EnvVar > desiredEnvVars ,
155+ final String containerPath ,
156+ final int containerIndex ) {
157+ if (desiredEnvVars .isEmpty () || actualEnvVars .isEmpty ()) {
158+ return ;
159+ }
160+ Optional .ofNullable (
161+ GenericKubernetesResource .get (
162+ actualMap , "spec" , "template" , "spec" , containerPath , containerIndex , "env" ))
163+ .map (List .class ::cast )
164+ .ifPresent (
165+ envVars ->
166+ actualEnvVars .forEach (
167+ actualEnvVar -> {
168+ final var actualEnvVarName = actualEnvVar .getName ();
169+ final var actualEnvVarValue = actualEnvVar .getValue ();
170+ // check if the actual EnvVar value string is not null or the desired EnvVar
171+ // already contains the same EnvVar name with a non empty EnvVar value
172+ final var isDesiredEnvVarEmpty =
173+ hasEnvVarNoEmptyValue (actualEnvVarName , desiredEnvVars );
174+ if (actualEnvVarValue != null || isDesiredEnvVarEmpty ) {
175+ return ;
176+ }
177+ envVars .stream ()
178+ .filter (
179+ envVar ->
180+ ((Map <String , String >) envVar )
181+ .get ("name" )
182+ .equals (actualEnvVarName ))
183+ // add the actual EnvVar value with an empty string to prevent a
184+ // resource update
185+ .forEach (envVar -> ((Map <String , String >) envVar ).put ("value" , "" ));
186+ }));
187+ }
188+
189+ private static boolean hasEnvVarNoEmptyValue (
190+ final String envVarName , final List <EnvVar > envVars ) {
191+ return envVars .stream ()
192+ .anyMatch (
193+ envVar ->
194+ Objects .equals (envVarName , envVar .getName ())
195+ && envVar .getValue () != null
196+ && !envVar .getValue ().isEmpty ());
197+ }
141198}
0 commit comments