Skip to content

Commit 3d613df

Browse files
ankedialennyphan
andauthored
Owls 103828 - Fix for the Cluster and Domain 'Available' conditions for admin only domains and intentionally shutdown clusters (#3602)
* Fix for the Cluster and Domain 'Available' conditions for admin only domains and intentionally shutdown clusters Co-authored-by: Lenny Phan <lenny.phan@oracle.com>
1 parent f4a6fb9 commit 3d613df

File tree

3 files changed

+99
-20
lines changed

3 files changed

+99
-20
lines changed

documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -195,15 +195,22 @@ The following is a list of condition types for a Cluster resource.
195195
* There are no pending server shutdown requests.
196196

197197
#### `Available` {id="cluster-available"}
198-
- The `status` attribute is set to `True` when a sufficient number of WebLogic Server pods are
199-
ready in the cluster. This includes either:
200-
* All WebLogic Server pods in the cluster are ready, as configured in the `cluster.spec.replicas` field,
201-
or if it is not configured, then in the `domain.spec.replicas` field.
202-
* Some of the expected server pods for the cluster are temporarily not ready, and the number of
203-
`not ready` server pods is less than or equal to `cluster.spec.maxUnavailable` which defaults to `1`.
204-
- The `status` attribute is also set to `True` when no WebLogic Server pods are running and this
205-
is the expected state, such as when `cluster.spec.replicas` is set to `0`, or when
206-
`cluster.spec.serverStartPolicy` is set to `Never`.
198+
- The `status` attribute is set to `True` when a sufficient number of WebLogic Server pods are
199+
ready in the cluster. Both of the following must be true:
200+
- At least one pod in the cluster is expected to run and is `ready`.
201+
- The number of `not ready` server pods which are expected to run
202+
is less than or equal to `cluster.spec.maxUnavailable` which defaults to `1`.
203+
- Examples:
204+
- If a cluster has `serverStartPolicy` `Never` or `replicas` `0`,
205+
or a cluster is in a domain with `serverStartPolicy` `AdminOnly` or `Never`,
206+
then the cluster will have `Available` `False`.
207+
- If a cluster and domain both have a `serverStartPolicy` of `IfNeeded`,
208+
and `cluster.spec.replicas` is `1`,
209+
then the cluster `Available` will be `True` only when its single pod is `ready`.
210+
- If a cluster and domain both have a `serverStartPolicy` of `IfNeeded`,
211+
`cluster.spec.replicas` is `4`,
212+
and `cluster.spec.maxUnavailable` is `1` (the default),
213+
then the cluster `Available` will be `True` only when three or four of its pods are `ready`.
207214
- **Note**: The `Available` `status` can be `True` even when the `status` for the `Completed`
208215
condition is `False`, a `Failed` condition is reported on the Domain resource, or the cluster
209216
has up to `cluster.spec.maxUnavailable` pods that are not ready.

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

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,11 @@ private ClusterCheck createFrom(ClusterStatus clusterStatus) {
749749
}
750750

751751
private boolean isProcessingCompleted() {
752-
return !haveTooManyReplicas() && allIntendedServersReady();
752+
return isDomainWithNeverStartPolicy() || (!haveTooManyReplicas() && allIntendedServersReady());
753+
}
754+
755+
private boolean isDomainWithNeverStartPolicy() {
756+
return getDomain().getSpec().getServerStartPolicy() == ServerStartPolicy.NEVER;
753757
}
754758

755759
private boolean haveTooManyReplicas() {
@@ -835,7 +839,7 @@ private boolean isServerNotReady(@Nonnull String serverName) {
835839
}
836840

837841
private boolean isUnavailable(@Nonnull ClusterCheck clusterCheck) {
838-
return !clusterCheck.isAvailable();
842+
return !clusterCheck.isAvailableOrIntentionallyShutdown();
839843
}
840844

841845
private boolean noApplicationServersReady() {
@@ -857,13 +861,23 @@ private Collection<DomainPresenceInfo.ServerStartupInfo> getServerStartupInfos()
857861

858862
// when the domain start policy is ADMIN_ONLY, the admin server is considered to be an application server.
859863
private boolean isApplicationServer(String serverName) {
860-
return isAdminOnlyDomain() || !isAdminServer(serverName);
864+
return !isAdminServer(serverName);
861865
}
862866

863867
private boolean isAdminOnlyDomain() {
868+
return isAdminOnlyServerStartPolicy()
869+
|| isOnlyAdminServerRunningInDomain();
870+
}
871+
872+
private boolean isAdminOnlyServerStartPolicy() {
864873
return getDomain().getSpec().getServerStartPolicy() == ServerStartPolicy.ADMIN_ONLY;
865874
}
866875

876+
private boolean isOnlyAdminServerRunningInDomain() {
877+
return expectedRunningServers.size() == 1
878+
&& expectedRunningServers.contains(getInfo().getAdminServerName());
879+
}
880+
867881
private boolean isAdminServer(String serverName) {
868882
return status.getServers().stream()
869883
.filter(s -> s.getServerName().equals(serverName))
@@ -906,6 +920,10 @@ private List<String> getNonStartedClusteredServers(DomainStatus domainStatus, St
906920
}
907921

908922
boolean isAvailable() {
923+
return sufficientServersReady();
924+
}
925+
926+
boolean isAvailableOrIntentionallyShutdown() {
909927
return isClusterIntentionallyShutDown() || sufficientServersReady();
910928
}
911929

operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -332,8 +332,7 @@ void whenStatusUnchanged_statusStepDoesNotUpdateDomain() {
332332
.withStateGoal(SHUTDOWN_STATE)
333333
.withServerName("server1")
334334
.withHealth(overallHealth("health1"))))
335-
.addCondition(new DomainCondition(AVAILABLE).withStatus(false)
336-
.withMessage(LOGGER.formatMessage(NO_APPLICATION_SERVERS_READY)))
335+
.addCondition(new DomainCondition(AVAILABLE).withStatus(true))
337336
.addCondition(new DomainCondition(COMPLETED).withStatus(true)));
338337

339338
testSupport.clearNumCalls();
@@ -1041,15 +1040,15 @@ void whenNumServersStartedBelowMinReplicasForDynamicClusterAndAllowed_domainIsAv
10411040
}
10421041

10431042
@Test
1044-
void whenReplicaCountIsZero_domainIsNotAvailable() {
1043+
void whenReplicaCountIsZeroAndAdminServerRunning_domainIsAvailable() {
10451044
defineScenario()
10461045
.withDynamicCluster("cluster1", 3, 4)
10471046
.notStarting("ms1", "ms2", "ms3", "ms4")
10481047
.build();
10491048

10501049
updateDomainStatus();
10511050

1052-
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE));
1051+
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE));
10531052
}
10541053

10551054
@Test
@@ -1108,7 +1107,7 @@ void whenReplicaCountNotWithinMaxUnavailableOfReplicas_establishClusterAvailable
11081107
}
11091108

11101109
@Test
1111-
void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionTrue() {
1110+
void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionFalse() {
11121111
configureDomain().configureCluster(info, "cluster1").withReplicas(0).withMaxUnavailable(1);
11131112
defineScenario().withDynamicCluster("cluster1", 0, 0).build();
11141113
info.getReferencedClusters().forEach(testSupport::defineResources);
@@ -1119,7 +1118,7 @@ void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionTrue()
11191118
assertThat(clusterStatus.getConditions().size(), equalTo(2));
11201119
ClusterCondition condition = clusterStatus.getConditions().get(0);
11211120
assertThat(condition.getType(), equalTo(ClusterConditionType.AVAILABLE));
1122-
assertThat(condition.getStatus(), equalTo(TRUE));
1121+
assertThat(condition.getStatus(), equalTo(FALSE));
11231122
}
11241123

11251124
@Test
@@ -1267,15 +1266,15 @@ void withAllServersShutdown_domainIsCompleted() { // !!!! can the admin server
12671266
}
12681267

12691268
@Test
1270-
void withClusterIntentionallyShutdown_domainIsCompleted() {
1269+
void withClusterIntentionallyShutdownAndAdminServerRunning_domainIsAvailableAndCompleted() {
12711270
defineScenario()
12721271
.withCluster("cluster1", "ms1", "ms2")
12731272
.notStarting("ms1", "ms2")
12741273
.build();
12751274

12761275
updateDomainStatus();
12771276

1278-
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE));
1277+
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE));
12791278
assertThat(getRecordedDomain(), hasCondition(COMPLETED).withStatus(TRUE));
12801279
}
12811280

@@ -1621,6 +1620,16 @@ void whenAdminOnlyAndAdminServerIsReady_availableIsTrue() {
16211620
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE));
16221621
}
16231622

1623+
@Test
1624+
void whenDomainHasNeverStartPolicy_completedIsTrue() {
1625+
configureDomain().withDefaultServerStartPolicy(ServerStartPolicy.NEVER);
1626+
defineScenario().build();
1627+
1628+
updateDomainStatus();
1629+
1630+
assertThat(getRecordedDomain(), hasCondition(COMPLETED).withStatus(TRUE));
1631+
}
1632+
16241633
@Test
16251634
void whenAdminOnlyAndAdminServerIsNotReady_availableIsFalse() {
16261635
configureDomain().withDefaultServerStartPolicy(ServerStartPolicy.ADMIN_ONLY);
@@ -1736,11 +1745,56 @@ void whenServerStartupInfoIsNull_availableIsFalse() {
17361745
hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE)));
17371746
}
17381747

1748+
@Test
1749+
void whenDomainOnlyHasAdminServer_availableIsTrue() {
1750+
configureDomain().configureAdminServer();
1751+
defineScenario().build();
1752+
1753+
updateDomainStatus();
1754+
1755+
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE));
1756+
}
1757+
17391758
private Collection<ClusterCondition> getClusterConditions() {
17401759
return testSupport.<ClusterResource>getResourceWithName(KubernetesTestSupport.CLUSTER, "cluster1")
17411760
.getStatus().getConditions();
17421761
}
17431762

1763+
@Test
1764+
void whenClusterIntentionallyShutdown_clusterAvailableIsFalseAndDomainAvailableIsTrue() {
1765+
configureDomain()
1766+
.configureCluster(info, "cluster1").withReplicas(0);
1767+
info.getReferencedClusters().forEach(testSupport::defineResources);
1768+
defineScenario()
1769+
.withCluster("cluster1", "server1", "server2")
1770+
.notStarting("server1", "server2")
1771+
.build();
1772+
1773+
updateDomainStatus();
1774+
1775+
assertThat(getClusterConditions(),
1776+
hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE)));
1777+
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE));
1778+
}
1779+
1780+
@Test
1781+
void whenClusterIntentionallyShutdownAndSSINotConstructed_clusterAndDomainAvailableIsFalse() {
1782+
configureDomain()
1783+
.configureCluster(info, "cluster1").withReplicas(0);
1784+
info.getReferencedClusters().forEach(testSupport::defineResources);
1785+
defineScenario()
1786+
.withCluster("cluster1", "server1", "server2")
1787+
.notStarting("server1", "server2")
1788+
.build();
1789+
info.setServerStartupInfo(null);
1790+
1791+
updateDomainStatus();
1792+
1793+
assertThat(getClusterConditions(),
1794+
hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE)));
1795+
assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE));
1796+
}
1797+
17441798
@SuppressWarnings("SameParameterValue")
17451799
private ScenarioBuilder defineScenario() {
17461800
return new ScenarioBuilder();

0 commit comments

Comments
 (0)