Skip to content

Commit c803660

Browse files
committed
Make managed server shutdown more resilient
1 parent 2c6a2d5 commit c803660

20 files changed

+165
-61
lines changed

common/src/main/resources/Operator.properties

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,8 @@ WLSKO-0195=The operator failed after retrying for {0,number,#} minutes. \
132132
WLSKO-0198={0} Fiber {1}
133133
WLSKO-0199=WL pod shutdown: Initiating shutdown of WebLogic server {0} via REST interface.
134134
WLSKO-0200=WL pod shutdown: Successfully shutdown WebLogic server {0} via REST interface.
135-
WLSKO-0201=WL pod shutdown: Failed to shutdown WebLogic server {0} via REST interface with response: {1}.
136-
WLSKO-0203=WL pod shutdown: Failed to shutdown WebLogic server {0} via REST interface due to exception: {1}.
135+
WLSKO-0201=WL pod shutdown: Failed to shut down WebLogic server {0} via REST interface with response: {1}.
136+
WLSKO-0203=WL pod shutdown: Failed to shut down WebLogic server {0} via REST interface due to exception: {1}.
137137
WLSKO-0204=WL pod shutdown: Retry shutdown of WebLogic server {0} via REST interface.
138138
WLSKO-0213=InputFile: {0} does not exist or could not be read.
139139
WLSKO-0214=The output dir {0} specified by ''-d'' does not exist or could not be read.

operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,8 +621,8 @@ private void processServerPodWatch(V1Pod pod, String watchType) {
621621
}
622622
}
623623
boolean isReady = PodHelper.isReady(pod);
624-
boolean isLabedlForShutdown = PodHelper.isPodAlreadyLabeledForShutdown(pod);
625-
if ((isEvicted || isReady != isLabedlForShutdown || PodHelper.isFailed(pod)) && !PodHelper.isDeleting(pod)) {
624+
boolean isLabeledForShutdown = PodHelper.isPodAlreadyAnnotatedForShutdown(pod);
625+
if ((isEvicted || isReady != isLabeledForShutdown || PodHelper.isFailed(pod)) && !PodHelper.isDeleting(pod)) {
626626
createMakeRightOperation(info).interrupt().withExplicitRecheck().execute();
627627
}
628628
boolean isUnschedulable = PodHelper.hasUnSchedulableCondition(pod);

operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1297,11 +1297,11 @@ private boolean isServerComplete(@Nonnull String serverName) {
12971297
&& isNotMarkedForRoll(serverName);
12981298
}
12991299

1300-
// returns true if the server pod does not have a label indicating that it needs to be rolled
1300+
// returns true if the server pod does not have an annotation indicating that it needs to be rolled
13011301
private boolean isNotMarkedForRoll(String serverName) {
13021302
return Optional.ofNullable(getInfo().getServerPod(serverName))
13031303
.map(V1Pod::getMetadata)
1304-
.map(V1ObjectMeta::getLabels)
1304+
.map(V1ObjectMeta::getAnnotations)
13051305
.map(Map::keySet).orElse(Collections.emptySet()).stream()
13061306
.noneMatch(k -> k.equals(TO_BE_ROLLED_LABEL));
13071307
}

operator/src/main/java/oracle/kubernetes/operator/MakeRightDomainOperation.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ private static boolean wasInspectionRun(Packet packet) {
8181
if (lastTransitionTime != null) {
8282
String time = packet.getValue(INTROSPECTION_TIME);
8383
if (time != null) {
84-
OffsetDateTime lastIntrospectionTime = OffsetDateTime.parse(time.replace('_', ':'));
84+
OffsetDateTime lastIntrospectionTime = OffsetDateTime.parse(time);
8585
if (lastIntrospectionTime.isAfter(lastTransitionTime)) {
8686
return true;
8787
}

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

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,8 @@ abstract static class ConfigMapContext extends StepContextBase {
220220
private final String name;
221221
private final String namespace;
222222
private V1ConfigMap model;
223-
private final Map<String, String> labels = new HashMap<>();
223+
private Map<String, String> annotations;
224+
private Map<String, String> labels;
224225
protected final SemanticVersion productVersion;
225226

226227
ConfigMapContext(Step conflictStep, String name, String namespace, Map<String, String> contents,
@@ -275,6 +276,7 @@ private V1ObjectMeta createMetadata() {
275276
new V1ObjectMeta()
276277
.name(name)
277278
.namespace(namespace)
279+
.annotations(annotations)
278280
.labels(labels));
279281

280282
if (productVersion != null) {
@@ -284,8 +286,20 @@ private V1ObjectMeta createMetadata() {
284286
return metadata;
285287
}
286288

289+
@SuppressWarnings("SameParameterValue")
290+
void addAnnotation(String name, String value) {
291+
if (annotations == null) {
292+
annotations = new HashMap<>();
293+
}
294+
annotations.put(name, value);
295+
model = null;
296+
}
297+
287298
@SuppressWarnings("SameParameterValue")
288299
void addLabel(String name, String value) {
300+
if (labels == null) {
301+
labels = new HashMap<>();
302+
}
289303
labels.put(name, value);
290304
model = null;
291305
}
@@ -332,7 +346,7 @@ public Result onSuccess(Packet packet, KubernetesApiResponse<V1ConfigMap> callRe
332346
Optional.ofNullable(domain).map(DomainResource::getMetadata).map(V1ObjectMeta::getGeneration)
333347
.ifPresent(value -> addLabel(INTROSPECTION_DOMAIN_SPEC_GENERATION, value.toString()));
334348
Optional.ofNullable((String) packet.get(INTROSPECTION_TIME))
335-
.ifPresent(value -> addLabel(INTROSPECTION_TIME, value));
349+
.ifPresent(value -> addAnnotation(INTROSPECTION_TIME, value));
336350
V1ConfigMap existingMap = withoutTransientData(callResponse.getObject());
337351
if (existingMap == null) {
338352
return doNext(createConfigMap(getNext()), packet);
@@ -369,8 +383,12 @@ private Step replaceConfigMap(Step next) {
369383
return RequestBuilder.CM.update(model, createReplaceResponseStep(next));
370384
}
371385

386+
private Map<String,String> getAnnotations() {
387+
return Optional.ofNullable(annotations).map(Collections::unmodifiableMap).orElse(Collections.emptyMap());
388+
}
389+
372390
private Map<String,String> getLabels() {
373-
return Collections.unmodifiableMap(labels);
391+
return Optional.ofNullable(labels).map(Collections::unmodifiableMap).orElse(Collections.emptyMap());
374392
}
375393

376394
private boolean mustPatchCurrentMap(V1ConfigMap currentMap) {
@@ -921,7 +939,12 @@ private void recordIntrospectVersionAndGeneration(V1ConfigMap result, Packet pac
921939
() -> packet.remove(INTROSPECTION_STATE_LABEL));
922940
Optional.ofNullable(labels).map(l -> l.get(INTROSPECTION_DOMAIN_SPEC_GENERATION))
923941
.ifPresent(generation -> packet.put(INTROSPECTION_DOMAIN_SPEC_GENERATION, generation));
924-
Optional.ofNullable(labels).map(l -> l.get(INTROSPECTION_TIME))
942+
943+
Map<String, String> annotations = Optional.ofNullable(result)
944+
.map(V1ConfigMap::getMetadata)
945+
.map(V1ObjectMeta::getAnnotations).orElse(null);
946+
947+
Optional.ofNullable(annotations).map(l -> l.get(INTROSPECTION_TIME))
925948
.ifPresent(value -> packet.put(INTROSPECTION_TIME, value));
926949
}
927950

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ public Stream<V1Pod> getServerPods() {
373373
*/
374374
public Stream<V1Pod> getServerPodsNotBeingDeleted() {
375375
return getActiveServers().values().stream().filter(
376-
sko -> !PodHelper.isPodAlreadyLabeledForShutdown(sko.getPod().get())).map(this::getPod)
376+
sko -> !PodHelper.isPodAlreadyAnnotatedForShutdown(sko.getPod().get())).map(this::getPod)
377377
.filter(Objects::nonNull);
378378
}
379379

@@ -383,7 +383,7 @@ private V1Pod getPod(ServerKubernetesObjects sko) {
383383

384384
public boolean isServerPodBeingDeleted(String serverName) {
385385
return Optional.ofNullable(getSko(serverName)).map(ServerKubernetesObjects::getPod).map(AtomicReference::get)
386-
.map(PodHelper::isPodAlreadyLabeledForShutdown).orElse(false);
386+
.map(PodHelper::isPodAlreadyAnnotatedForShutdown).orElse(false);
387387
}
388388

389389
public boolean isServerPodDeleted(String serverName) {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ private class ReadPodLogStep extends Step {
505505

506506
Optional.ofNullable(jobPod).map(V1Pod::getMetadata)
507507
.map(V1ObjectMeta::getCreationTimestamp).map(OffsetDateTime::toString)
508-
.ifPresent(creationTime -> packet.put(INTROSPECTION_TIME, creationTime.replace(':', '_')));
508+
.ifPresent(creationTime -> packet.put(INTROSPECTION_TIME, creationTime));
509509
return doNext(readDomainIntrospectorPodLog(jobPodName, containerName, getNext()), packet);
510510
}
511511

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

Lines changed: 52 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import java.util.Collections;
88
import java.util.List;
99
import java.util.Map;
10+
import java.util.Objects;
1011
import java.util.Optional;
1112
import javax.annotation.Nonnull;
1213
import javax.annotation.Nullable;
@@ -374,7 +375,7 @@ private static boolean hasLabel(V1Pod pod, String label) {
374375
.map(l -> l.containsKey(label)).orElse(false);
375376
}
376377

377-
private static Step patchPod(V1Pod pod, String label, Step next) {
378+
private static Step patchPodLabel(V1Pod pod, String label, Step next) {
378379
if (!hasLabel(pod, label)) {
379380
JsonPatchBuilder patchBuilder = Json.createPatchBuilder();
380381
patchBuilder.add("/metadata/labels/" + label, "true");
@@ -386,6 +387,41 @@ private static Step patchPod(V1Pod pod, String label, Step next) {
386387
return next;
387388
}
388389

390+
/**
391+
* get pod's annotation value for a annotation name.
392+
* @param pod pod
393+
* @param annotationName annotation name
394+
* @return annotation value
395+
*/
396+
public static String getPodAnnotation(V1Pod pod, String annotationName) {
397+
return Optional.ofNullable(pod)
398+
.map(V1Pod::getMetadata)
399+
.map(V1ObjectMeta::getAnnotations)
400+
.map(m -> m.get(annotationName))
401+
.orElse(null);
402+
}
403+
404+
private static boolean hasAnnotation(V1Pod pod, String annotation) {
405+
return Optional.ofNullable(pod).map(V1Pod::getMetadata).map(V1ObjectMeta::getAnnotations)
406+
.map(l -> l.containsKey(annotation)).orElse(false);
407+
}
408+
409+
private static Step patchPodAnnotation(V1Pod pod, String annotation, Step next) {
410+
return patchPodAnnotation(pod, annotation, "true", next);
411+
}
412+
413+
private static Step patchPodAnnotation(V1Pod pod, String annotation, String value, Step next) {
414+
if (!hasAnnotation(pod, annotation)) {
415+
JsonPatchBuilder patchBuilder = Json.createPatchBuilder();
416+
patchBuilder.add("/metadata/annotations/" + annotation, value);
417+
V1ObjectMeta meta = pod.getMetadata();
418+
return RequestBuilder.POD.patch(meta.getNamespace(), meta.getName(),
419+
V1Patch.PATCH_FORMAT_JSON_PATCH,
420+
new V1Patch(patchBuilder.build().toString()), patchResponse(next));
421+
}
422+
return next;
423+
}
424+
389425
private static ResponseStep<V1Pod> patchResponse(Step next) {
390426
return new PatchPodResponseStep(next);
391427
}
@@ -413,22 +449,26 @@ public Result onFailure(Packet packet, KubernetesApiResponse<V1Pod> callResponse
413449
}
414450

415451
/**
416-
* Label pod as needing to shut down.
452+
* Annotate pod as needing to shut down.
417453
* @param pod Pod
418454
* @param next Next step
419-
* @return Step that will check for existing label and add if it is missing
455+
* @return Step that will check for existing annotation and add if it is missing
420456
*/
421-
public static Step labelPodAsNeedingToShutdown(V1Pod pod, Step next) {
422-
return patchPod(pod, LabelConstants.TO_BE_SHUTDOWN_LABEL, next);
457+
public static Step annotatePodAsNeedingToShutdown(V1Pod pod, String value, Step next) {
458+
return patchPodAnnotation(pod, LabelConstants.TO_BE_SHUTDOWN_LABEL, value, next);
423459
}
424460

425461
/**
426-
* Check if the pod is already labeld for shut down.
462+
* Check if the pod is already annotated for shut down.
427463
* @param pod Pod
428-
* @return true, if the pod is already labeled.
464+
* @return true, if the pod is already annotated.
429465
*/
430-
public static boolean isPodAlreadyLabeledForShutdown(V1Pod pod) {
431-
return hasLabel(pod, LabelConstants.TO_BE_SHUTDOWN_LABEL);
466+
public static boolean isPodAlreadyAnnotatedForShutdown(V1Pod pod) {
467+
return !Objects.isNull(getPodShutdownAnnotation(pod));
468+
}
469+
470+
public static String getPodShutdownAnnotation(V1Pod pod) {
471+
return getPodAnnotation(pod, LabelConstants.TO_BE_SHUTDOWN_LABEL);
432472
}
433473

434474
/**
@@ -711,7 +751,7 @@ String getServerName() {
711751
@Override
712752
// let the pod rolling step update the pod
713753
Step replaceCurrentPod(V1Pod pod, Step next) {
714-
return labelPodAsNeedingToRoll(pod, new DeferProcessing(pod, next));
754+
return annotatePodAsNeedingToRoll(pod, new DeferProcessing(pod, next));
715755
}
716756

717757
private class DeferProcessing extends Step {
@@ -767,8 +807,8 @@ private void deferProcessing(Step deferredStep) {
767807
}
768808

769809
// Patch the pod to indicate a pending roll.
770-
private Step labelPodAsNeedingToRoll(V1Pod pod, Step next) {
771-
return patchPod(pod, LabelConstants.TO_BE_ROLLED_LABEL, next);
810+
private Step annotatePodAsNeedingToRoll(V1Pod pod, Step next) {
811+
return patchPodAnnotation(pod, LabelConstants.TO_BE_ROLLED_LABEL, next);
772812
}
773813

774814
private Fiber.StepAndPacket createRollRequest(Step deferredStep) {

operator/src/main/java/oracle/kubernetes/operator/steps/HttpRequestProcessing.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import java.net.URI;
77
import java.net.http.HttpRequest;
88
import java.net.http.HttpResponse;
9+
import java.time.Duration;
910
import java.time.OffsetDateTime;
1011
import java.util.Collections;
1112
import java.util.HashMap;
@@ -30,7 +31,8 @@
3031

3132
abstract class HttpRequestProcessing {
3233

33-
private static final Long HTTP_TIMEOUT_SECONDS = 60L;
34+
public static final Long HTTP_TIMEOUT_SECONDS = 60L;
35+
3436
private static final Map<String, CookieList> COOKIES = new ConcurrentHashMap<>();
3537

3638
private final Packet packet;
@@ -84,10 +86,11 @@ AuthorizationSource getAuthorizationSource() {
8486
return SecretHelper.getAuthorizationSource(getPacket());
8587
}
8688

87-
final HttpRequest.Builder createRequestBuilder(String url) {
89+
final HttpRequest.Builder createRequestBuilder(String url, long timeout) {
8890
final URI uri = URI.create(url);
8991
HttpRequest.Builder builder = HttpRequest.newBuilder()
9092
.uri(uri)
93+
.timeout(Duration.ofSeconds(timeout))
9194
.header("Accept", "application/json")
9295
.header("Content-Type", "application/json")
9396
.header("X-Requested-By", "WebLogic Operator");

operator/src/main/java/oracle/kubernetes/operator/steps/ManagedServerUpIteratorStep.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ protected boolean isPodReady(V1Pod result) {
162162
}
163163

164164
protected boolean isPodMarkedForShutdown(V1Pod result) {
165-
return PodHelper.isDeleting(result) || PodHelper.isPodAlreadyLabeledForShutdown(result);
165+
return PodHelper.isDeleting(result) || PodHelper.isPodAlreadyAnnotatedForShutdown(result);
166166
}
167167
}
168168

0 commit comments

Comments
 (0)