Skip to content

Commit 30aef63

Browse files
jshum2479russgoldrjeberhard
authored
Update unit tests and simplify logic for dynamic update (#2237)
* add unit test for dynamic update * Fix v1 bug when users are added in the update cycle, it should recreate the primordial domain. Co-authored-by: Russell Gold <russ@russgold.net> Co-authored-by: Ryan Eberhard <ryan.eberhard@oracle.com>
1 parent 86fa2da commit 30aef63

File tree

9 files changed

+227
-152
lines changed

9 files changed

+227
-152
lines changed

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

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,17 +46,25 @@
4646
import oracle.kubernetes.operator.work.Packet;
4747
import oracle.kubernetes.operator.work.Step;
4848
import oracle.kubernetes.weblogic.domain.model.ClusterStatus;
49+
import oracle.kubernetes.weblogic.domain.model.Configuration;
4950
import oracle.kubernetes.weblogic.domain.model.Domain;
5051
import oracle.kubernetes.weblogic.domain.model.DomainCondition;
52+
import oracle.kubernetes.weblogic.domain.model.DomainConditionType;
53+
import oracle.kubernetes.weblogic.domain.model.DomainSpec;
5154
import oracle.kubernetes.weblogic.domain.model.DomainStatus;
55+
import oracle.kubernetes.weblogic.domain.model.Model;
56+
import oracle.kubernetes.weblogic.domain.model.OnlineUpdate;
5257
import oracle.kubernetes.weblogic.domain.model.ServerHealth;
5358
import oracle.kubernetes.weblogic.domain.model.ServerStatus;
5459

5560
import static oracle.kubernetes.operator.LabelConstants.CLUSTERNAME_LABEL;
61+
import static oracle.kubernetes.operator.MIINonDynamicChangesMethod.CommitUpdateOnly;
5662
import static oracle.kubernetes.operator.ProcessingConstants.DOMAIN_TOPOLOGY;
5763
import static oracle.kubernetes.operator.ProcessingConstants.EXCEEDED_INTROSPECTOR_MAX_RETRY_COUNT_ERROR_MSG;
5864
import static oracle.kubernetes.operator.ProcessingConstants.FATAL_INTROSPECTOR_ERROR;
5965
import static oracle.kubernetes.operator.ProcessingConstants.FATAL_INTROSPECTOR_ERROR_MSG;
66+
import static oracle.kubernetes.operator.ProcessingConstants.MII_DYNAMIC_UPDATE;
67+
import static oracle.kubernetes.operator.ProcessingConstants.MII_DYNAMIC_UPDATE_RESTART_REQUIRED;
6068
import static oracle.kubernetes.operator.ProcessingConstants.SERVER_HEALTH_MAP;
6169
import static oracle.kubernetes.operator.ProcessingConstants.SERVER_STATE_MAP;
6270
import static oracle.kubernetes.operator.WebLogicConstants.RUNNING_STATE;
@@ -490,9 +498,13 @@ static class StatusUpdateContext extends DomainStatusUpdaterContext {
490498
private final WlsDomainConfig config;
491499
private final Map<String, String> serverState;
492500
private final Map<String, ServerHealth> serverHealth;
501+
private final Optional<DomainPresenceInfo> info;
502+
private final Packet packet;
493503

494504
StatusUpdateContext(Packet packet, StatusUpdateStep statusUpdateStep) {
495505
super(packet, statusUpdateStep);
506+
this.packet = packet;
507+
info = DomainPresenceInfo.fromPacket(packet);
496508
config = packet.getValue(DOMAIN_TOPOLOGY);
497509
serverState = packet.getValue(SERVER_STATE_MAP);
498510
serverHealth = packet.getValue(SERVER_HEALTH_MAP);
@@ -523,6 +535,54 @@ void modifyStatus(DomainStatus status) {
523535
.withReason(MANAGED_SERVERS_STARTING_PROGRESS_REASON));
524536
}
525537

538+
if (miiNondynamicRestartRequired() && isCommitUpdateOnly()) {
539+
setOnlineUpdateNeedRestartCondition(status);
540+
}
541+
542+
}
543+
544+
private boolean miiNondynamicRestartRequired() {
545+
return MII_DYNAMIC_UPDATE_RESTART_REQUIRED.equals(packet.get(MII_DYNAMIC_UPDATE));
546+
}
547+
548+
private boolean isCommitUpdateOnly() {
549+
return getMiiNonDynamicChangesMethod() == CommitUpdateOnly;
550+
}
551+
552+
private MIINonDynamicChangesMethod getMiiNonDynamicChangesMethod() {
553+
return info
554+
.map(DomainPresenceInfo::getDomain)
555+
.map(Domain::getSpec)
556+
.map(DomainSpec::getConfiguration)
557+
.map(Configuration::getModel)
558+
.map(Model::getOnlineUpdate)
559+
.map(OnlineUpdate::getOnNonDynamicChanges)
560+
.orElse(MIINonDynamicChangesMethod.CommitUpdateOnly);
561+
}
562+
563+
private void setOnlineUpdateNeedRestartCondition(DomainStatus status) {
564+
String dynamicUpdateRollBackFile = Optional.ofNullable((String)packet.get(
565+
ProcessingConstants.MII_DYNAMIC_UPDATE_WDTROLLBACKFILE))
566+
.orElse("");
567+
String message = String.format("%s\n%s",
568+
LOGGER.formatMessage(MessageKeys.MII_DOMAIN_UPDATED_POD_RESTART_REQUIRED), dynamicUpdateRollBackFile);
569+
updateDomainConditions(status, message, DomainConditionType.ConfigChangesPendingRestart);
570+
}
571+
572+
private void updateDomainConditions(DomainStatus status, String message, DomainConditionType domainSourceType) {
573+
String introspectVersion = info
574+
.map(DomainPresenceInfo::getDomain)
575+
.map(Domain::getSpec)
576+
.map(DomainSpec::getIntrospectVersion)
577+
.orElse("");
578+
579+
DomainCondition onlineUpdateCondition = new DomainCondition(domainSourceType)
580+
.withMessage(message)
581+
.withReason("Online update applied, introspectVersion updated to " + introspectVersion)
582+
.withStatus("True");
583+
584+
status.removeConditionIf(c -> c.getType() == DomainConditionType.ConfigChangesPendingRestart);
585+
status.addCondition(onlineUpdateCondition);
526586
}
527587

528588
private boolean stillHasPodPendingRestart(DomainStatus status) {
@@ -651,9 +711,11 @@ Map<String, ClusterStatus> getClusterStatuses() {
651711
private ClusterStatus createClusterStatus(String clusterName) {
652712
return new ClusterStatus()
653713
.withClusterName(clusterName)
654-
.withReplicas(Optional.ofNullable(getClusterCounts().get(clusterName)).map(Long::intValue).orElse(null))
714+
.withReplicas(Optional.ofNullable(getClusterCounts().get(clusterName))
715+
.map(Long::intValue).orElse(null))
655716
.withReadyReplicas(
656-
Optional.ofNullable(getClusterCounts(true).get(clusterName)).map(Long::intValue).orElse(null))
717+
Optional.ofNullable(getClusterCounts(true)
718+
.get(clusterName)).map(Long::intValue).orElse(null))
657719
.withMaximumReplicas(getClusterMaximumSize(clusterName))
658720
.withMinimumReplicas(getClusterMinimumSize(clusterName))
659721
.withReplicasGoal(getClusterSizeGoal(clusterName));

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

Lines changed: 35 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -57,14 +57,8 @@
5757
import oracle.kubernetes.operator.work.NextAction;
5858
import oracle.kubernetes.operator.work.Packet;
5959
import oracle.kubernetes.operator.work.Step;
60-
import oracle.kubernetes.weblogic.domain.model.Configuration;
6160
import oracle.kubernetes.weblogic.domain.model.Domain;
62-
import oracle.kubernetes.weblogic.domain.model.DomainCondition;
63-
import oracle.kubernetes.weblogic.domain.model.DomainConditionType;
64-
import oracle.kubernetes.weblogic.domain.model.DomainSpec;
6561
import oracle.kubernetes.weblogic.domain.model.DomainStatus;
66-
import oracle.kubernetes.weblogic.domain.model.Model;
67-
import oracle.kubernetes.weblogic.domain.model.OnlineUpdate;
6862
import oracle.kubernetes.weblogic.domain.model.ServerEnvVars;
6963
import oracle.kubernetes.weblogic.domain.model.ServerSpec;
7064
import oracle.kubernetes.weblogic.domain.model.Shutdown;
@@ -73,7 +67,8 @@
7367
import static oracle.kubernetes.operator.IntrospectorConfigMapConstants.NUM_CONFIG_MAPS;
7468
import static oracle.kubernetes.operator.LabelConstants.INTROSPECTION_STATE_LABEL;
7569
import static oracle.kubernetes.operator.LabelConstants.MII_UPDATED_RESTART_REQUIRED_LABEL;
76-
import static oracle.kubernetes.operator.logging.MessageKeys.MII_DOMAIN_DYNAMICALLY_UPDATED;
70+
import static oracle.kubernetes.operator.LabelConstants.MODEL_IN_IMAGE_DOMAINZIP_HASH;
71+
import static oracle.kubernetes.operator.ProcessingConstants.MII_DYNAMIC_UPDATE_SUCCESS;
7772

7873
public abstract class PodStepContext extends BasePodStepContext {
7974

@@ -94,6 +89,7 @@ public abstract class PodStepContext extends BasePodStepContext {
9489
private final String miiModelSecretsHash;
9590
private final String miiDomainZipHash;
9691
private final String domainRestartVersion;
92+
private boolean addRestartRequiredLabel;
9793

9894
PodStepContext(Step conflictStep, Packet packet) {
9995
super(packet.getSpi(DomainPresenceInfo.class));
@@ -379,10 +375,6 @@ private Step patchCurrentPod(V1Pod currentPod, Step next) {
379375
return createProgressingStep(patchPod(currentPod, next));
380376
}
381377

382-
private Step patchRunningPod(V1Pod currentPod, V1Pod updatedPod, Step next, boolean addRestartRequiredLabel) {
383-
return createProgressingStep(patchPod(currentPod, updatedPod, next, addRestartRequiredLabel));
384-
}
385-
386378
protected Step patchPod(V1Pod currentPod, Step next) {
387379
JsonPatchBuilder patchBuilder = Json.createPatchBuilder();
388380
KubernetesUtils.addPatches(
@@ -394,50 +386,18 @@ protected Step patchPod(V1Pod currentPod, Step next) {
394386
new V1Patch(patchBuilder.build().toString()), patchResponse(next));
395387
}
396388

397-
// Method for online update
398-
protected Step patchPod(V1Pod currentPod, V1Pod updatedPod, Step next, boolean addRestartRequiredLabel) {
399-
JsonPatchBuilder patchBuilder = Json.createPatchBuilder();
400-
Map<String, String> updatedLabels = Optional.ofNullable(updatedPod)
401-
.map(V1Pod::getMetadata)
402-
.map(V1ObjectMeta::getLabels)
403-
.orElse(null);
404-
405-
Map<String, String> updatedAnnotations = Optional.ofNullable(updatedPod)
406-
.map(V1Pod::getMetadata)
407-
.map(V1ObjectMeta::getAnnotations)
408-
.orElse(null);
409-
if (updatedLabels != null) {
410-
String introspectVersion = Optional.ofNullable(info)
411-
.map(DomainPresenceInfo::getDomain)
412-
.map(Domain::getSpec)
413-
.map(DomainSpec::getIntrospectVersion)
414-
.orElse(null);
415-
if (introspectVersion != null) {
416-
updatedLabels.put(INTROSPECTION_STATE_LABEL, introspectVersion);
417-
if (addRestartRequiredLabel) {
418-
updatedLabels.put(MII_UPDATED_RESTART_REQUIRED_LABEL, "true");
419-
}
420-
}
421-
422-
KubernetesUtils.addPatches(
423-
patchBuilder, "/metadata/labels/", getLabels(currentPod), updatedLabels);
424-
}
425-
if (updatedAnnotations != null) {
426-
KubernetesUtils.addPatches(
427-
patchBuilder, "/metadata/annotations/", getAnnotations(currentPod),
428-
updatedAnnotations);
429-
}
430-
return new CallBuilder()
431-
.patchPodAsync(getPodName(), getNamespace(), getDomainUid(),
432-
new V1Patch(patchBuilder.build().toString()), patchResponse(next));
433-
}
434-
435389
private Map<String, String> getNonHashedPodLabels() {
436390
Map<String,String> result = new HashMap<>(getPodLabels());
391+
Optional.ofNullable(miiDomainZipHash)
392+
.ifPresent(h -> result.put(MODEL_IN_IMAGE_DOMAINZIP_HASH, formatHashLabel(h)));
437393

438394
Optional.ofNullable(getDomain().getSpec().getIntrospectVersion())
439395
.ifPresent(version -> result.put(INTROSPECTION_STATE_LABEL, version));
440396

397+
if (addRestartRequiredLabel) {
398+
result.put(MII_UPDATED_RESTART_REQUIRED_LABEL, "true");
399+
}
400+
441401
return result;
442402
}
443403

@@ -485,7 +445,8 @@ private boolean mustPatchPod(V1Pod currentPod) {
485445
private boolean canUseCurrentPod(V1Pod currentPod) {
486446

487447
boolean useCurrent =
488-
AnnotationHelper.getHash(getPodModel()).equals(AnnotationHelper.getHash(currentPod));
448+
AnnotationHelper.getHash(getPodModel()).equals(AnnotationHelper.getHash(currentPod))
449+
&& canUseNewDomainZip(currentPod);
489450

490451
if (!useCurrent && AnnotationHelper.getDebugString(currentPod).length() > 0) {
491452
LOGGER.fine(
@@ -497,6 +458,28 @@ private boolean canUseCurrentPod(V1Pod currentPod) {
497458
return useCurrent;
498459
}
499460

461+
private boolean canUseNewDomainZip(V1Pod currentPod) {
462+
String dynamicUpdateResult = packet.getValue(ProcessingConstants.MII_DYNAMIC_UPDATE);
463+
464+
if (miiDomainZipHash == null || isDomainZipUnchanged(currentPod)) {
465+
return true;
466+
} else if (dynamicUpdateResult == null) {
467+
return false;
468+
} else if (dynamicUpdateResult.equals(MII_DYNAMIC_UPDATE_SUCCESS)) {
469+
return true;
470+
} else if (getDomain().getMiiNonDynamicChangesMethod() == MIINonDynamicChangesMethod.CommitUpdateOnly) {
471+
addRestartRequiredLabel = true;
472+
return true;
473+
} else {
474+
return false;
475+
}
476+
}
477+
478+
private boolean isDomainZipUnchanged(V1Pod currentPod) {
479+
return formatHashLabel(miiDomainZipHash)
480+
.equals(currentPod.getMetadata().getLabels().get(MODEL_IN_IMAGE_DOMAINZIP_HASH));
481+
}
482+
500483
private String getReasonToRecycle(V1Pod currentPod) {
501484
PodCompatibility compatibility = new PodCompatibility(getPodModel(), currentPod);
502485
return compatibility.getIncompatibility();
@@ -540,6 +523,8 @@ V1Pod withNonHashedElements(V1Pod pod) {
540523
getPodAnnotations().entrySet().stream()
541524
.filter(PodStepContext::isPatchableItem)
542525
.forEach(e -> metadata.putAnnotationsItem(e.getKey(), e.getValue()));
526+
Optional.ofNullable(miiDomainZipHash)
527+
.ifPresent(hash -> addHashLabel(metadata, LabelConstants.MODEL_IN_IMAGE_DOMAINZIP_HASH, hash));
543528

544529
setTerminationGracePeriod(pod);
545530
getContainer(pod).map(V1Container::getEnv).ifPresent(this::updateEnv);
@@ -625,8 +610,6 @@ LabelConstants.CLUSTERRESTARTVERSION_LABEL, getServerSpec().getClusterRestartVer
625610
.putLabelsItem(
626611
LabelConstants.SERVERRESTARTVERSION_LABEL, getServerSpec().getServerRestartVersion());
627612

628-
Optional.ofNullable(miiDomainZipHash)
629-
.ifPresent(hash -> addHashLabel(metadata, LabelConstants.MODEL_IN_IMAGE_DOMAINZIP_HASH, hash));
630613
Optional.ofNullable(miiModelSecretsHash)
631614
.ifPresent(hash -> addHashLabel(metadata, LabelConstants.MODEL_IN_IMAGE_MODEL_SECRETS_HASH, hash));
632615
return metadata;
@@ -915,50 +898,14 @@ private class VerifyPodStep extends BaseStep {
915898
public NextAction apply(Packet packet) {
916899
V1Pod currentPod = info.getServerPod(getServerName());
917900
// reset introspect failure job count - if any
918-
919901
Optional.ofNullable(packet.getSpi(DomainPresenceInfo.class))
920902
.map(DomainPresenceInfo::getDomain)
921903
.map(Domain::getStatus)
922904
.ifPresent(DomainStatus::resetIntrospectJobFailureCount);
923905

924-
String dynamicUpdateResult = Optional.ofNullable((String)packet.get(ProcessingConstants.MII_DYNAMIC_UPDATE))
925-
.orElse(null);
926-
927906
if (currentPod == null) {
928907
return doNext(createNewPod(getNext()), packet);
929908
} else if (!canUseCurrentPod(currentPod)) {
930-
if (shouldNotRestartAfterOnlineUpdate(dynamicUpdateResult)) {
931-
Map<String, String> labels = Optional.of(currentPod)
932-
.map(V1Pod::getMetadata)
933-
.map(V1ObjectMeta::getLabels)
934-
.orElse(new HashMap<>());
935-
String serverName = "";
936-
if (labels.containsKey(LabelConstants.SERVERNAME_LABEL)) {
937-
serverName = labels.get(LabelConstants.SERVERNAME_LABEL);
938-
}
939-
LOGGER.fine(MII_DOMAIN_DYNAMICALLY_UPDATED, info.getDomain().getDomainUid(), serverName);
940-
logPodExists();
941-
//Create dummy meta data for patching
942-
V1Pod updatedPod = AnnotationHelper.withSha256Hash(createPodRecipe());
943-
V1ObjectMeta updatedMetaData = new V1ObjectMeta();
944-
945-
updatedMetaData.putAnnotationsItem("weblogic.sha256",
946-
updatedPod.getMetadata().getAnnotations().get("weblogic.sha256"));
947-
if (miiDomainZipHash != null) {
948-
updatedMetaData.putLabelsItem(LabelConstants.MODEL_IN_IMAGE_DOMAINZIP_HASH,
949-
formatHashLabel(miiDomainZipHash));
950-
}
951-
updatedPod.setMetadata(updatedMetaData);
952-
boolean addRestartRequiredLabel = false;
953-
// if the introspector job tells it needs restart, update the condition with the needed attributes
954-
if (ProcessingConstants.MII_DYNAMIC_UPDATE_RESTART_REQUIRED.equals(dynamicUpdateResult)) {
955-
setOnlineUpdateNeedRestartCondition(packet);
956-
addRestartRequiredLabel = true;
957-
} else {
958-
setOnlineUpdateSuccessCondition();
959-
}
960-
return doNext(patchRunningPod(currentPod, updatedPod, getNext(), addRestartRequiredLabel), packet);
961-
}
962909
LOGGER.info(
963910
MessageKeys.CYCLING_POD,
964911
Objects.requireNonNull(currentPod.getMetadata()).getName(),
@@ -971,64 +918,6 @@ public NextAction apply(Packet packet) {
971918
return doNext(packet);
972919
}
973920
}
974-
975-
private boolean shouldNotRestartAfterOnlineUpdate(String dynamicUpdateResult) {
976-
boolean result = false;
977-
if (ProcessingConstants.MII_DYNAMIC_UPDATE_SUCCESS.equals(dynamicUpdateResult)) {
978-
result = true;
979-
} else if (ProcessingConstants.MII_DYNAMIC_UPDATE_RESTART_REQUIRED.equals(dynamicUpdateResult)) {
980-
result = MIINonDynamicChangesMethod.CommitUpdateOnly.equals(
981-
Optional.ofNullable(info)
982-
.map(DomainPresenceInfo::getDomain)
983-
.map(Domain::getSpec)
984-
.map(DomainSpec::getConfiguration)
985-
.map(Configuration::getModel)
986-
.map(Model::getOnlineUpdate)
987-
.map(OnlineUpdate::getOnNonDynamicChanges)
988-
.orElse(MIINonDynamicChangesMethod.CommitUpdateOnly));
989-
}
990-
return result;
991-
}
992-
993-
private void setOnlineUpdateNeedRestartCondition(Packet packet) {
994-
String dynamicUpdateRollBackFile = Optional.ofNullable((String)packet.get(
995-
ProcessingConstants.MII_DYNAMIC_UPDATE_WDTROLLBACKFILE))
996-
.orElse("");
997-
String message = String.format("%s\n%s",
998-
LOGGER.formatMessage(MessageKeys.MII_DOMAIN_UPDATED_POD_RESTART_REQUIRED), dynamicUpdateRollBackFile);
999-
updateDomainConditions(message, DomainConditionType.ConfigChangesPendingRestart);
1000-
}
1001-
1002-
private void setOnlineUpdateSuccessCondition() {
1003-
// updateDomainConditions("Online update successful. No restart necessary",
1004-
// DomainConditionType.OnlineUpdateComplete);
1005-
}
1006-
1007-
@SuppressWarnings("SameParameterValue")
1008-
private void updateDomainConditions(String message, DomainConditionType domainSourceType) {
1009-
DomainCondition onlineUpdateCondition = new DomainCondition(domainSourceType);
1010-
String introspectVersion = Optional.ofNullable(info)
1011-
.map(DomainPresenceInfo::getDomain)
1012-
.map(Domain::getSpec)
1013-
.map(DomainSpec::getIntrospectVersion)
1014-
.orElse("");
1015-
1016-
onlineUpdateCondition
1017-
.withMessage(message)
1018-
.withReason("Online update applied, introspectVersion updated to " + introspectVersion)
1019-
.withStatus("True");
1020-
1021-
Optional.ofNullable(info)
1022-
.map(DomainPresenceInfo::getDomain)
1023-
.map(Domain::getStatus)
1024-
.ifPresent(o -> o.removeConditionIf(c -> c.getType() == DomainConditionType.ConfigChangesPendingRestart));
1025-
1026-
Optional.ofNullable(info)
1027-
.map(DomainPresenceInfo::getDomain)
1028-
.map(Domain::getStatus)
1029-
.ifPresent(o -> o.addCondition(onlineUpdateCondition));
1030-
}
1031-
1032921
}
1033922

1034923
private abstract class BaseResponseStep extends ResponseStep<V1Pod> {

operator/src/main/java/oracle/kubernetes/weblogic/domain/DomainConfigurator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ public abstract DomainConfigurator withPodSecurityContext(
488488
*
489489
* @return this object
490490
*/
491-
public abstract DomainConfigurator withMIIOnlineUpate();
491+
public abstract DomainConfigurator withMIIOnlineUpdate();
492492

493493
/**
494494
* Set onNonDynamicChanges to CommitUpdateAndRoll for MII Online Update.

0 commit comments

Comments
 (0)