Skip to content

Commit c4b4c20

Browse files
committed
Add support for pod changes due to security contexts and probes
1 parent 84614f7 commit c4b4c20

File tree

4 files changed

+154
-153
lines changed

4 files changed

+154
-153
lines changed

operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java

Lines changed: 64 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
package oracle.kubernetes.operator.helpers;
66

77
import static oracle.kubernetes.operator.LabelConstants.forDomainUid;
8+
import static oracle.kubernetes.operator.VersionConstants.DEFAULT_DOMAIN_VERSION;
89

910
import io.kubernetes.client.custom.IntOrString;
1011
import io.kubernetes.client.models.*;
@@ -270,55 +271,35 @@ private boolean canUseCurrentPod(V1Pod currentPod) {
270271
// Therefore, we'll just compare specific fields
271272
private static boolean isCurrentPodValid(V1Pod build, V1Pod current) {
272273
List<String> ignoring = getVolumesToIgnore(current);
273-
if (!VersionHelper.matchesResourceVersion(
274-
current.getMetadata(), VersionConstants.DEFAULT_DOMAIN_VERSION)) {
275-
return false;
276-
}
277-
278-
if (!isRestartVersionValid(build, current)) {
279-
return false;
280-
}
281-
282-
if (areUnequal(
283-
volumesWithout(current.getSpec().getVolumes(), ignoring), build.getSpec().getVolumes()))
284-
return false;
285-
286-
if (areUnequal(current.getSpec().getImagePullSecrets(), build.getSpec().getImagePullSecrets()))
287-
return false;
288274

289-
if (areUnequal(getCustomerLabels(current), getCustomerLabels(build))) return false;
290-
291-
if (areUnequal(current.getMetadata().getAnnotations(), build.getMetadata().getAnnotations()))
292-
return false;
293-
294-
List<V1Container> buildContainers = build.getSpec().getContainers();
295-
List<V1Container> currentContainers = current.getSpec().getContainers();
275+
return isCurrentPodMetadataValid(build.getMetadata(), current.getMetadata())
276+
&& isCurrentPodSpecValid(build.getSpec(), current.getSpec(), ignoring);
277+
}
296278

297-
if (buildContainers != null) {
298-
if (currentContainers == null) {
299-
return false;
300-
}
279+
private static boolean isCurrentPodMetadataValid(V1ObjectMeta build, V1ObjectMeta current) {
280+
return VersionHelper.matchesResourceVersion(current, DEFAULT_DOMAIN_VERSION)
281+
&& isRestartVersionValid(build, current)
282+
&& Objects.equals(getCustomerLabels(current), getCustomerLabels(build))
283+
&& Objects.equals(current.getAnnotations(), build.getAnnotations());
284+
}
301285

302-
for (V1Container bc : buildContainers) {
303-
V1Container fcc = getContainerWithName(currentContainers, bc.getName());
304-
if (fcc == null) {
305-
return false;
306-
}
307-
if (!fcc.getImage().equals(bc.getImage())
308-
|| !fcc.getImagePullPolicy().equals(bc.getImagePullPolicy())) {
309-
return false;
310-
}
286+
private static boolean isCurrentPodSpecValid(
287+
V1PodSpec build, V1PodSpec current, List<String> ignoring) {
288+
return Objects.equals(current.getSecurityContext(), build.getSecurityContext())
289+
// && Objects.equals(current.getNodeSelector(), build.getNodeSelector())
290+
&& equalSets(volumesWithout(current.getVolumes(), ignoring), build.getVolumes())
291+
&& equalSets(current.getImagePullSecrets(), build.getImagePullSecrets())
292+
&& areCompatible(build.getContainers(), current.getContainers(), ignoring);
293+
}
311294

312-
if (areUnequal(mountsWithout(fcc.getVolumeMounts(), ignoring), bc.getVolumeMounts()))
313-
return false;
295+
private static boolean areCompatible(
296+
List<V1Container> build, List<V1Container> current, List<String> ignoring) {
297+
if (build != null) {
298+
if (current == null) return false;
314299

315-
if (areUnequal(fcc.getPorts(), bc.getPorts())) {
316-
return false;
317-
}
318-
if (areUnequal(fcc.getEnv(), bc.getEnv())) {
319-
return false;
320-
}
321-
if (areUnequal(fcc.getEnvFrom(), bc.getEnvFrom())) {
300+
for (V1Container bc : build) {
301+
V1Container fcc = getContainerWithName(current, bc.getName());
302+
if (fcc == null || !isCompatible(bc, fcc, ignoring)) {
322303
return false;
323304
}
324305
}
@@ -327,6 +308,33 @@ private static boolean isCurrentPodValid(V1Pod build, V1Pod current) {
327308
return true;
328309
}
329310

311+
/**
312+
* Compares two pod spec containers for equality
313+
*
314+
* @param build the desired container model
315+
* @param current the current container, obtained from Kubernetes
316+
* @param ignoring a list of volume names to ignore
317+
* @return true if the containers are considered equal
318+
*/
319+
private static boolean isCompatible(
320+
V1Container build, V1Container current, List<String> ignoring) {
321+
return current.getImage().equals(build.getImage())
322+
&& current.getImagePullPolicy().equals(build.getImagePullPolicy())
323+
&& Objects.equals(current.getSecurityContext(), build.getSecurityContext())
324+
&& equalSettings(current.getLivenessProbe(), build.getLivenessProbe())
325+
&& equalSettings(current.getReadinessProbe(), build.getReadinessProbe())
326+
&& equalSets(mountsWithout(current.getVolumeMounts(), ignoring), build.getVolumeMounts())
327+
&& equalSets(current.getPorts(), build.getPorts())
328+
&& equalSets(current.getEnv(), build.getEnv())
329+
&& equalSets(current.getEnvFrom(), build.getEnvFrom());
330+
}
331+
332+
private static boolean equalSettings(V1Probe probe1, V1Probe probe2) {
333+
return Objects.equals(probe1.getInitialDelaySeconds(), probe2.getInitialDelaySeconds())
334+
&& Objects.equals(probe1.getTimeoutSeconds(), probe2.getTimeoutSeconds())
335+
&& Objects.equals(probe1.getPeriodSeconds(), probe2.getPeriodSeconds());
336+
}
337+
330338
private static List<V1Volume> volumesWithout(
331339
List<V1Volume> volumeMounts, List<String> volumesToIgnore) {
332340
List<V1Volume> result = new ArrayList<>(volumeMounts);
@@ -363,9 +371,9 @@ private static List<V1VolumeMount> getVolumeMounts(V1Container container) {
363371
return Optional.ofNullable(container.getVolumeMounts()).orElse(Collections.emptyList());
364372
}
365373

366-
private static Map<String, String> getCustomerLabels(V1Pod pod) {
374+
private static Map<String, String> getCustomerLabels(V1ObjectMeta metadata) {
367375
Map<String, String> result = new HashMap<>();
368-
for (Map.Entry<String, String> entry : pod.getMetadata().getLabels().entrySet())
376+
for (Map.Entry<String, String> entry : metadata.getLabels().entrySet())
369377
if (!isOperatorLabel(entry)) result.put(entry.getKey(), entry.getValue());
370378
return result;
371379
}
@@ -374,12 +382,10 @@ private static boolean isOperatorLabel(Map.Entry<String, String> label) {
374382
return label.getKey().startsWith("weblogic.");
375383
}
376384

377-
private static boolean isRestartVersionValid(V1Pod build, V1Pod current) {
378-
V1ObjectMeta m1 = build.getMetadata();
379-
V1ObjectMeta m2 = current.getMetadata();
380-
return isLabelSame(m1, m2, LabelConstants.DOMAINRESTARTVERSION_LABEL)
381-
&& isLabelSame(m1, m2, LabelConstants.CLUSTERRESTARTVERSION_LABEL)
382-
&& isLabelSame(m1, m2, LabelConstants.SERVERRESTARTVERSION_LABEL);
385+
private static boolean isRestartVersionValid(V1ObjectMeta build, V1ObjectMeta current) {
386+
return isLabelSame(build, current, LabelConstants.DOMAINRESTARTVERSION_LABEL)
387+
&& isLabelSame(build, current, LabelConstants.CLUSTERRESTARTVERSION_LABEL)
388+
&& isLabelSame(build, current, LabelConstants.SERVERRESTARTVERSION_LABEL);
383389
}
384390

385391
private static boolean isLabelSame(V1ObjectMeta build, V1ObjectMeta current, String labelName) {
@@ -395,33 +401,13 @@ private static V1Container getContainerWithName(List<V1Container> containers, St
395401
return null;
396402
}
397403

398-
private static <T> boolean areUnequal(List<T> a, List<T> b) {
399-
if (a == b) {
400-
return false;
401-
}
402-
403-
if (a == null) a = Collections.emptyList();
404-
if (b == null) b = Collections.emptyList();
405-
406-
if (a.size() != b.size()) {
407-
return true;
408-
}
409-
410-
List<T> bprime = new ArrayList<>(b);
411-
for (T at : a) {
412-
if (!bprime.remove(at)) {
413-
return true;
414-
}
415-
}
416-
return false;
417-
}
418-
419-
private static <K, V> boolean areUnequal(Map<K, V> a, Map<K, V> b) {
420-
return !emptyIfNull(a).equals(emptyIfNull(b));
404+
private static <T> boolean equalSets(List<T> first, List<T> second) {
405+
if (first == second) return true;
406+
return asSet(first).equals(asSet(second));
421407
}
422408

423-
private static <K, V> Map<K, V> emptyIfNull(Map<K, V> map) {
424-
return map != null ? map : Collections.emptyMap();
409+
private static <T> Set<T> asSet(List<T> first) {
410+
return (first == null) ? Collections.emptySet() : new HashSet<>(first);
425411
}
426412

427413
private class VerifyPodStep extends Step {
@@ -595,8 +581,7 @@ protected V1ObjectMeta createMetadata() {
595581
// Add internal labels. This will overwrite any custom labels that conflict with internal
596582
// labels.
597583
metadata
598-
.putLabelsItem(
599-
LabelConstants.RESOURCE_VERSION_LABEL, VersionConstants.DEFAULT_DOMAIN_VERSION)
584+
.putLabelsItem(LabelConstants.RESOURCE_VERSION_LABEL, DEFAULT_DOMAIN_VERSION)
600585
.putLabelsItem(LabelConstants.DOMAINUID_LABEL, getDomainUID())
601586
.putLabelsItem(LabelConstants.DOMAINNAME_LABEL, getDomainName())
602587
.putLabelsItem(LabelConstants.SERVERNAME_LABEL, getServerName())

operator/src/test/java/oracle/kubernetes/operator/helpers/AdminPodHelperTest.java

Lines changed: 18 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,8 @@
66

77
import static oracle.kubernetes.LogMatcher.containsFine;
88
import static oracle.kubernetes.LogMatcher.containsInfo;
9-
import static oracle.kubernetes.operator.LabelConstants.RESOURCE_VERSION_LABEL;
10-
import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_POD_CREATED;
11-
import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_POD_EXISTS;
12-
import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_POD_REPLACED;
13-
import static org.hamcrest.Matchers.allOf;
14-
import static org.hamcrest.Matchers.contains;
15-
import static org.hamcrest.Matchers.empty;
16-
import static org.hamcrest.Matchers.equalTo;
17-
import static org.hamcrest.Matchers.hasEntry;
18-
import static org.hamcrest.Matchers.hasKey;
19-
import static org.hamcrest.Matchers.not;
9+
import static oracle.kubernetes.operator.logging.MessageKeys.*;
10+
import static org.hamcrest.Matchers.*;
2011
import static org.hamcrest.junit.MatcherAssert.assertThat;
2112

2213
import io.kubernetes.client.ApiException;
@@ -67,7 +58,8 @@ String getPodReplacedMessageKey() {
6758
return ADMIN_POD_REPLACED;
6859
}
6960

70-
private void verifyAdminPodReplacedWhen(PodMutator mutator) {
61+
@Override
62+
protected void verifyReplacePodWhen(PodMutator mutator) {
7163
testSupport.addComponent(
7264
ProcessingConstants.PODWATCHER_COMPONENT_NAME,
7365
PodAwaiterStepFactory.class,
@@ -158,25 +150,14 @@ public void whenAdminPodReplacementFails_retryOnFailure() {
158150
testSupport.verifyCompletionThrowable(ApiException.class);
159151
}
160152

161-
@Test
162-
public void whenExistingAdminPodHasBadVersion_replaceIt() {
163-
verifyAdminPodReplacedWhen(
164-
pod -> pod.getMetadata().putLabelsItem(RESOURCE_VERSION_LABEL, "??"));
165-
}
166-
167-
@Test
168-
public void whenExistingManagedPodHasUnknownCustomerLabel_designateForRoll() {
169-
verifyAdminPodReplacedWhen(pod -> pod.getMetadata().putLabelsItem("customer.label", "value"));
170-
}
171-
172153
@Test
173154
public void whenExistingAdminPodSpecHasUnknownCustomerAnnotation_replaceIt() {
174-
verifyAdminPodReplacedWhen(pod -> pod.getMetadata().putAnnotationsItem("annotation1", "value"));
155+
verifyReplacePodWhen(pod -> pod.getMetadata().putAnnotationsItem("annotation1", "value"));
175156
}
176157

177158
@Test
178159
public void whenExistingAdminPodSpecHasUnknownAddedVolumes_replaceIt() {
179-
verifyAdminPodReplacedWhen((pod) -> pod.getSpec().addVolumesItem(new V1Volume().name("dummy")));
160+
verifyReplacePodWhen((pod) -> pod.getSpec().addVolumesItem(new V1Volume().name("dummy")));
180161
}
181162

182163
@Test
@@ -194,19 +175,19 @@ public void whenExistingAdminPodSpecHasK8sVolume_ignoreIt() {
194175

195176
@Test
196177
public void whenExistingAdminPodSpecHasUnusedImagePullSecret_replaceIt() {
197-
verifyAdminPodReplacedWhen(
178+
verifyReplacePodWhen(
198179
(pod) ->
199180
pod.getSpec().addImagePullSecretsItem(new V1LocalObjectReference().name("secret")));
200181
}
201182

202183
@Test
203184
public void whenExistingAdminPodSpecHasNoContainers_replaceIt() {
204-
verifyAdminPodReplacedWhen((pod) -> pod.getSpec().setContainers(null));
185+
verifyReplacePodWhen((pod) -> pod.getSpec().setContainers(null));
205186
}
206187

207188
@Test
208189
public void whenExistingAdminPodSpecHasNoContainersWithExpectedName_replaceIt() {
209-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).setName("???"));
190+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).setName("???"));
210191
}
211192

212193
private V1Container getSpecContainer(V1Pod pod) {
@@ -215,7 +196,7 @@ private V1Container getSpecContainer(V1Pod pod) {
215196

216197
@Test
217198
public void whenExistingAdminPodSpecHasUnneededVolumeMount_replaceIt() {
218-
verifyAdminPodReplacedWhen(
199+
verifyReplacePodWhen(
219200
(pod) -> getSpecContainer(pod).addVolumeMountsItem(new V1VolumeMount().name("dummy")));
220201
}
221202

@@ -232,22 +213,22 @@ public void whenExistingAdminPodSpecHasK8sVolumeMount_ignoreIt() {
232213

233214
@Test
234215
public void whenExistingAdminPodSpecContainerHasWrongImage_replaceIt() {
235-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).setImage(VERSIONED_IMAGE));
216+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).setImage(VERSIONED_IMAGE));
236217
}
237218

238219
@Test
239220
public void whenExistingAdminPodSpecContainerHasWrongImagePullPolicy_replaceIt() {
240-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).setImagePullPolicy("NONE"));
221+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).setImagePullPolicy("NONE"));
241222
}
242223

243224
@Test
244225
public void whenExistingAdminPodSpecContainerHasNoPorts_replaceIt() {
245-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).setPorts(Collections.emptyList()));
226+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).setPorts(Collections.emptyList()));
246227
}
247228

248229
@Test
249230
public void whenExistingAdminPodSpecContainerHasExtraPort_replaceIt() {
250-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).addPortsItem(definePort(1234)));
231+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).addPortsItem(definePort(1234)));
251232
}
252233

253234
private V1ContainerPort definePort(int port) {
@@ -256,24 +237,23 @@ private V1ContainerPort definePort(int port) {
256237

257238
@Test
258239
public void whenExistingAdminPodSpecContainerHasIncorrectPort_replaceIt() {
259-
verifyAdminPodReplacedWhen(
260-
(pod) -> getSpecContainer(pod).getPorts().get(0).setContainerPort(1234));
240+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).getPorts().get(0).setContainerPort(1234));
261241
}
262242

263243
@Test
264244
public void whenExistingAdminPodSpecContainerHasWrongEnvVariable_replaceIt() {
265-
verifyAdminPodReplacedWhen((pod) -> getSpecContainer(pod).getEnv().get(0).setValue("???"));
245+
verifyReplacePodWhen((pod) -> getSpecContainer(pod).getEnv().get(0).setValue("???"));
266246
}
267247

268248
@Test
269249
public void whenExistingAdminPodSpecContainerHasWrongEnvFrom_replaceIt() {
270-
verifyAdminPodReplacedWhen(
250+
verifyReplacePodWhen(
271251
(pod) -> getSpecContainer(pod).envFrom(Collections.singletonList(new V1EnvFromSource())));
272252
}
273253

274254
@Test
275255
public void whenExistingAdminPodSpecContainerHasRestartVersion_replaceIt() {
276-
verifyAdminPodReplacedWhen(
256+
verifyReplacePodWhen(
277257
(pod) ->
278258
pod.getMetadata()
279259
.putLabelsItem(LabelConstants.SERVERRESTARTVERSION_LABEL, "adminRestartV1"));

0 commit comments

Comments
 (0)