From a54d759f0529032ab53ff8bf1ae521f60701edd5 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Mon, 31 Oct 2022 17:42:13 -0700 Subject: [PATCH 1/8] check Domain Status servers to see if admin server only --- .../kubernetes/operator/DomainStatusUpdater.java | 11 ++++++++++- .../operator/DomainStatusUpdateTestBase.java | 10 ++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index b80b3e5fb3a..6a6fcdc5176 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -857,13 +857,22 @@ private Collection getServerStartupInfos() // when the domain start policy is ADMIN_ONLY, the admin server is considered to be an application server. private boolean isApplicationServer(String serverName) { - return isAdminOnlyDomain() || !isAdminServer(serverName); + return !isAdminServer(serverName); } private boolean isAdminOnlyDomain() { + return isAdminOnlyServerStartPolicy() + || isOnlyAdminServerExpectedRunningInDomain(); + } + + private boolean isAdminOnlyServerStartPolicy() { return getDomain().getSpec().getServerStartPolicy() == ServerStartPolicy.ADMIN_ONLY; } + private boolean isOnlyAdminServerExpectedRunningInDomain() { + return status.getServers().size() == 1 && isAdminServer(getInfo().getAdminServerName()); + } + private boolean isAdminServer(String serverName) { return status.getServers().stream() .filter(s -> s.getServerName().equals(serverName)) diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java index 98eb95ebbfa..88ae65a9754 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java @@ -1736,6 +1736,16 @@ void whenServerStartupInfoIsNull_availableIsFalse() { hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE))); } + @Test + void whenDomainOnlyHasAdminServer_availableIsTrue() { + configureDomain().configureAdminServer(); + defineScenario().build(); + + updateDomainStatus(); + + assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE)); + } + private Collection getClusterConditions() { return testSupport.getResourceWithName(KubernetesTestSupport.CLUSTER, "cluster1") .getStatus().getConditions(); From f8caa6775108a8b986f0c357591e04f24e16b423 Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Mon, 31 Oct 2022 19:39:49 -0700 Subject: [PATCH 2/8] Identify admin server status by comparing server name --- .../java/oracle/kubernetes/operator/DomainStatusUpdater.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index 6a6fcdc5176..b715f92774a 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -870,7 +870,8 @@ private boolean isAdminOnlyServerStartPolicy() { } private boolean isOnlyAdminServerExpectedRunningInDomain() { - return status.getServers().size() == 1 && isAdminServer(getInfo().getAdminServerName()); + return status.getServers().size() == 1 + && status.getServers().get(0).getServerName().equals(getInfo().getAdminServerName()); } private boolean isAdminServer(String serverName) { From d3eb72bd713a394e4761336a9e5cdca62f3608bc Mon Sep 17 00:00:00 2001 From: Lenny Phan Date: Mon, 31 Oct 2022 19:59:43 -0700 Subject: [PATCH 3/8] rename method --- .../java/oracle/kubernetes/operator/DomainStatusUpdater.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index b715f92774a..c9096c5700f 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -862,14 +862,14 @@ private boolean isApplicationServer(String serverName) { private boolean isAdminOnlyDomain() { return isAdminOnlyServerStartPolicy() - || isOnlyAdminServerExpectedRunningInDomain(); + || isOnlyAdminServerRunningInDomain(); } private boolean isAdminOnlyServerStartPolicy() { return getDomain().getSpec().getServerStartPolicy() == ServerStartPolicy.ADMIN_ONLY; } - private boolean isOnlyAdminServerExpectedRunningInDomain() { + private boolean isOnlyAdminServerRunningInDomain() { return status.getServers().size() == 1 && status.getServers().get(0).getServerName().equals(getInfo().getAdminServerName()); } From 1a4ff8d6a132596c0229454bdb3ff6584dc4b90a Mon Sep 17 00:00:00 2001 From: Anil Kedia Date: Tue, 1 Nov 2022 14:56:41 +0000 Subject: [PATCH 4/8] OWLS-103828 - WKO 4.0: Set Cluster 'Available' Condition to false if no servers expected to run. --- .../operator/DomainStatusUpdater.java | 6 ++++- .../operator/DomainStatusUpdateTestBase.java | 22 +++++++++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index b80b3e5fb3a..77f97b4cff1 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -835,7 +835,7 @@ private boolean isServerNotReady(@Nonnull String serverName) { } private boolean isUnavailable(@Nonnull ClusterCheck clusterCheck) { - return !clusterCheck.isAvailable(); + return !clusterCheck.isAvailableOrIntentionallyShutdown(); } private boolean noApplicationServersReady() { @@ -906,6 +906,10 @@ private List getNonStartedClusteredServers(DomainStatus domainStatus, St } boolean isAvailable() { + return sufficientServersReady(); + } + + boolean isAvailableOrIntentionallyShutdown() { return isClusterIntentionallyShutDown() || sufficientServersReady(); } diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java index 98eb95ebbfa..da9b261ba5b 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java @@ -1108,7 +1108,7 @@ void whenReplicaCountNotWithinMaxUnavailableOfReplicas_establishClusterAvailable } @Test - void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionTrue() { + void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionFalse() { configureDomain().configureCluster(info, "cluster1").withReplicas(0).withMaxUnavailable(1); defineScenario().withDynamicCluster("cluster1", 0, 0).build(); info.getReferencedClusters().forEach(testSupport::defineResources); @@ -1119,7 +1119,7 @@ void whenClusterIsIntentionallyShutdown_establishClusterAvailableConditionTrue() assertThat(clusterStatus.getConditions().size(), equalTo(2)); ClusterCondition condition = clusterStatus.getConditions().get(0); assertThat(condition.getType(), equalTo(ClusterConditionType.AVAILABLE)); - assertThat(condition.getStatus(), equalTo(TRUE)); + assertThat(condition.getStatus(), equalTo(FALSE)); } @Test @@ -1741,6 +1741,24 @@ private Collection getClusterConditions() { .getStatus().getConditions(); } + @Test + void whenClusterIntentionallyShutdownAndSSINotConstructed_clusterAndDomainAvailableIsFalse() { + configureDomain() + .configureCluster(info, "cluster1").withReplicas(0); + info.getReferencedClusters().forEach(testSupport::defineResources); + defineScenario() + .withCluster("cluster1", "server31", "server2") + .notStarting("server1", "server2") + .build(); + info.setServerStartupInfo(null); + + updateDomainStatus(); + + assertThat(getClusterConditions(), + hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE))); + assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE)); + } + @SuppressWarnings("SameParameterValue") private ScenarioBuilder defineScenario() { return new ScenarioBuilder(); From f5b93fae39d1e039978304868e74967b80f0358a Mon Sep 17 00:00:00 2001 From: Anil Kedia Date: Tue, 1 Nov 2022 16:58:53 +0000 Subject: [PATCH 5/8] Merge changes from OWLS-103825 branch and additional changes as discussed with Lenny. --- .../operator/DomainStatusUpdater.java | 4 +-- .../operator/DomainStatusUpdateTestBase.java | 28 +++++++++++++++---- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index e8af1e857b8..0e1b3d4e9a4 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -870,8 +870,8 @@ private boolean isAdminOnlyServerStartPolicy() { } private boolean isOnlyAdminServerRunningInDomain() { - return status.getServers().size() == 1 - && status.getServers().get(0).getServerName().equals(getInfo().getAdminServerName()); + return expectedRunningServers.size() == 1 + && expectedRunningServers.contains(getInfo().getAdminServerName()); } private boolean isAdminServer(String serverName) { diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java index 4ff2ca3f6a3..1580691fb90 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java @@ -332,8 +332,7 @@ void whenStatusUnchanged_statusStepDoesNotUpdateDomain() { .withStateGoal(SHUTDOWN_STATE) .withServerName("server1") .withHealth(overallHealth("health1")))) - .addCondition(new DomainCondition(AVAILABLE).withStatus(false) - .withMessage(LOGGER.formatMessage(NO_APPLICATION_SERVERS_READY))) + .addCondition(new DomainCondition(AVAILABLE).withStatus(true)) .addCondition(new DomainCondition(COMPLETED).withStatus(true))); testSupport.clearNumCalls(); @@ -1041,7 +1040,7 @@ void whenNumServersStartedBelowMinReplicasForDynamicClusterAndAllowed_domainIsAv } @Test - void whenReplicaCountIsZero_domainIsNotAvailable() { + void whenReplicaCountIsZero_domainIsAvailable() { defineScenario() .withDynamicCluster("cluster1", 3, 4) .notStarting("ms1", "ms2", "ms3", "ms4") @@ -1049,7 +1048,7 @@ void whenReplicaCountIsZero_domainIsNotAvailable() { updateDomainStatus(); - assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE)); + assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE)); } @Test @@ -1275,7 +1274,7 @@ void withClusterIntentionallyShutdown_domainIsCompleted() { updateDomainStatus(); - assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(FALSE)); + assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE)); assertThat(getRecordedDomain(), hasCondition(COMPLETED).withStatus(TRUE)); } @@ -1751,13 +1750,30 @@ private Collection getClusterConditions() { .getStatus().getConditions(); } + @Test + void whenClusterIntentionallyShutdown_clusterAvailableIsFalseAndDomainAvailableIsTrue() { + configureDomain() + .configureCluster(info, "cluster1").withReplicas(0); + info.getReferencedClusters().forEach(testSupport::defineResources); + defineScenario() + .withCluster("cluster1", "server1", "server2") + .notStarting("server1", "server2") + .build(); + + updateDomainStatus(); + + assertThat(getClusterConditions(), + hasItems(new ClusterCondition(ClusterConditionType.AVAILABLE).withStatus(FALSE))); + assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE)); + } + @Test void whenClusterIntentionallyShutdownAndSSINotConstructed_clusterAndDomainAvailableIsFalse() { configureDomain() .configureCluster(info, "cluster1").withReplicas(0); info.getReferencedClusters().forEach(testSupport::defineResources); defineScenario() - .withCluster("cluster1", "server31", "server2") + .withCluster("cluster1", "server1", "server2") .notStarting("server1", "server2") .build(); info.setServerStartupInfo(null); From 535380536da4b872bcadda2528626d5a3f0c85bf Mon Sep 17 00:00:00 2001 From: Anil Kedia Date: Tue, 1 Nov 2022 17:11:26 +0000 Subject: [PATCH 6/8] Fix unit test names. --- .../kubernetes/operator/DomainStatusUpdateTestBase.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java index 1580691fb90..776ca8d880d 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java @@ -1040,7 +1040,7 @@ void whenNumServersStartedBelowMinReplicasForDynamicClusterAndAllowed_domainIsAv } @Test - void whenReplicaCountIsZero_domainIsAvailable() { + void whenReplicaCountIsZeroAndAdminServerRunning_domainIsAvailable() { defineScenario() .withDynamicCluster("cluster1", 3, 4) .notStarting("ms1", "ms2", "ms3", "ms4") @@ -1266,7 +1266,7 @@ void withAllServersShutdown_domainIsCompleted() { // !!!! can the admin server } @Test - void withClusterIntentionallyShutdown_domainIsCompleted() { + void withClusterIntentionallyShutdownAndAdminServerRunning_domainIsAvailableAndCompleted() { defineScenario() .withCluster("cluster1", "ms1", "ms2") .notStarting("ms1", "ms2") From b395c9d87b50c571ddb7940b6328a5561b40ab4b Mon Sep 17 00:00:00 2001 From: Anil Kedia Date: Tue, 1 Nov 2022 21:11:47 +0000 Subject: [PATCH 7/8] Fix for completed condition for Domains with NEVER start policy and doc changes. --- .../accessing-the-domain/status-conditions.md | 25 ++++++++++++------- .../operator/DomainStatusUpdater.java | 6 ++++- .../operator/DomainStatusUpdateTestBase.java | 10 ++++++++ 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md b/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md index 2dc65758846..66a11a97244 100644 --- a/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md +++ b/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md @@ -195,15 +195,22 @@ The following is a list of condition types for a Cluster resource. * There are no pending server shutdown requests. #### `Available` {id="cluster-available"} -- The `status` attribute is set to `True` when a sufficient number of WebLogic Server pods are - ready in the cluster. This includes either: - * All WebLogic Server pods in the cluster are ready, as configured in the `cluster.spec.replicas` field, - or if it is not configured, then in the `domain.spec.replicas` field. - * Some of the expected server pods for the cluster are temporarily not ready, and the number of - `not ready` server pods is less than or equal to `cluster.spec.maxUnavailable` which defaults to `1`. -- The `status` attribute is also set to `True` when no WebLogic Server pods are running and this - is the expected state, such as when `cluster.spec.replicas` is set to `0`, or when - `cluster.spec.serverStartPolicy` is set to `Never`. +- The `status` attribute is set to `True` when a sufficient number of WebLogic Server pods are + ready in the cluster. Both of the following must be true: + - At least one pod in the cluster is expected to run and is `ready`. + - The number of `not ready` server pods which are expected to run + is less than or equal to `cluster.spec.maxUnavailable` which defaults to `1`. +- Examples: + - If a cluster has `serverStartPolicy` `Never` or `replicas` `0`, + or a cluster is in a domain with `serverStartPolicy` `AdminOnly` or `Never`, + then the cluster will have `Available` `False`. + - If a cluster and domain both have a `serverStartPolicy` of `IfNeeded`, + and `cluster.spec.replicas` is `1`, + then the cluster `Available` will be `True` only when its single pod is `ready`. + - If a cluster and domain both have a `serverStartPolicy` of `IfNeeded`, + `cluster.spec.replicas` is `4`, + and `cluster.spec.maxUnavailable` is `1` (the default), + then the cluster `Available` will be `True` only when three are four of its pods are `ready`. - **Note**: The `Available` `status` can be `True` even when the `status` for the `Completed` condition is `False`, a `Failed` condition is reported on the Domain resource, or the cluster has up to `cluster.spec.maxUnavailable` pods that are not ready. diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java index 0e1b3d4e9a4..394a4ce1347 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainStatusUpdater.java @@ -749,7 +749,11 @@ private ClusterCheck createFrom(ClusterStatus clusterStatus) { } private boolean isProcessingCompleted() { - return !haveTooManyReplicas() && allIntendedServersReady(); + return isDomainWithNeverStartPolicy() || (!haveTooManyReplicas() && allIntendedServersReady()); + } + + private boolean isDomainWithNeverStartPolicy() { + return getDomain().getSpec().getServerStartPolicy() == ServerStartPolicy.NEVER; } private boolean haveTooManyReplicas() { diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java index 776ca8d880d..34cef59ac76 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainStatusUpdateTestBase.java @@ -1620,6 +1620,16 @@ void whenAdminOnlyAndAdminServerIsReady_availableIsTrue() { assertThat(getRecordedDomain(), hasCondition(AVAILABLE).withStatus(TRUE)); } + @Test + void whenDomainHasNeverStartPolicy_completedIsTrue() { + configureDomain().withDefaultServerStartPolicy(ServerStartPolicy.NEVER); + defineScenario().build(); + + updateDomainStatus(); + + assertThat(getRecordedDomain(), hasCondition(COMPLETED).withStatus(TRUE)); + } + @Test void whenAdminOnlyAndAdminServerIsNotReady_availableIsFalse() { configureDomain().withDefaultServerStartPolicy(ServerStartPolicy.ADMIN_ONLY); From db92d4aa89a2bfd7c8666fe1ce49ed22357364b9 Mon Sep 17 00:00:00 2001 From: Anil Kedia Date: Tue, 1 Nov 2022 21:32:53 +0000 Subject: [PATCH 8/8] Fix the typo as per the review comment. --- .../managing-domains/accessing-the-domain/status-conditions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md b/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md index 66a11a97244..4e7d7636aa9 100644 --- a/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md +++ b/documentation/staging/content/managing-domains/accessing-the-domain/status-conditions.md @@ -210,7 +210,7 @@ The following is a list of condition types for a Cluster resource. - If a cluster and domain both have a `serverStartPolicy` of `IfNeeded`, `cluster.spec.replicas` is `4`, and `cluster.spec.maxUnavailable` is `1` (the default), - then the cluster `Available` will be `True` only when three are four of its pods are `ready`. + then the cluster `Available` will be `True` only when three or four of its pods are `ready`. - **Note**: The `Available` `status` can be `True` even when the `status` for the `Completed` condition is `False`, a `Failed` condition is reported on the Domain resource, or the cluster has up to `cluster.spec.maxUnavailable` pods that are not ready.