diff --git a/README.md b/README.md index 43ca077fc34..4cfae35e921 100644 --- a/README.md +++ b/README.md @@ -17,8 +17,8 @@ Oracle is finding ways for organizations using WebLogic Server to run important The fastest way to experience the operator is to follow the [Quick Start guide](https://oracle.github.io/weblogic-kubernetes-operator/quickstart/), or you can peruse our [documentation](https://oracle.github.io/weblogic-kubernetes-operator), read our [blogs](https://blogs.oracle.com/weblogicserver/updated-weblogic-kubernetes-support-with-operator-20), or try out the [samples](https://oracle.github.io/weblogic-kubernetes-operator/samples/). *** -The [current release of the operator](https://github.com/oracle/weblogic-kubernetes-operator/releases) is 3.1.3. -This release was published on February 12, 2021. +The [current release of the operator](https://github.com/oracle/weblogic-kubernetes-operator/releases) is 3.1.4. +This release was published on March 1, 2021. *** # Documentation diff --git a/buildDockerImage.sh b/buildDockerImage.sh index 5f47820ee76..5ff2ee248d5 100755 --- a/buildDockerImage.sh +++ b/buildDockerImage.sh @@ -33,7 +33,7 @@ while getopts "t:" optname; do esac done -IMAGE_NAME=${name:-ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3} +IMAGE_NAME=${name:-ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4} SCRIPTPATH="$( cd "$(dirname "$0")" > /dev/null 2>&1 ; pwd -P )" # Proxy settings diff --git a/buildtime-reports/pom.xml b/buildtime-reports/pom.xml index 1ba202eaffa..e6712b1762e 100644 --- a/buildtime-reports/pom.xml +++ b/buildtime-reports/pom.xml @@ -8,7 +8,7 @@ operator-parent oracle.kubernetes - 3.1.3 + 3.1.4 buildtime-reports diff --git a/docs-source/content/_index.md b/docs-source/content/_index.md index 65127a3ff7e..5d7250af74a 100644 --- a/docs-source/content/_index.md +++ b/docs-source/content/_index.md @@ -23,8 +23,8 @@ using the operator to deploy and run a WebLogic domain container-packaged web ap *** #### Current production release -The [current release of the operator](https://github.com/oracle/weblogic-kubernetes-operator/releases) is 3.1.3. -This release was published on February 12, 2021. See the operator prerequisites and supported environments [here]({{< relref "/userguide/introduction/introduction#operator-prerequisites" >}}). +The [current release of the operator](https://github.com/oracle/weblogic-kubernetes-operator/releases) is 3.1.4. +This release was published on March 1, 2021. See the operator prerequisites and supported environments [here]({{< relref "/userguide/introduction/introduction#operator-prerequisites" >}}). *** diff --git a/docs-source/content/faq/namespace-management.md b/docs-source/content/faq/namespace-management.md index 77a6be47d64..6670b98dec9 100644 --- a/docs-source/content/faq/namespace-management.md +++ b/docs-source/content/faq/namespace-management.md @@ -43,7 +43,7 @@ elkIntegrationEnabled: false externalDebugHttpPort: 30999 externalRestEnabled: false externalRestHttpsPort: 31001 -image: ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3 +image: ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4 imagePullPolicy: IfNotPresent internalDebugHttpPort: 30999 istioEnabled: false diff --git a/docs-source/content/quickstart/get-images.md b/docs-source/content/quickstart/get-images.md index a2ca41504b0..ff9a3a30022 100644 --- a/docs-source/content/quickstart/get-images.md +++ b/docs-source/content/quickstart/get-images.md @@ -10,7 +10,7 @@ weight: 3 1. Pull the operator image: ```bash - $ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3 + $ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4 ``` 1. Pull the Traefik ingress controller image: diff --git a/docs-source/content/quickstart/install.md b/docs-source/content/quickstart/install.md index 8c10b0ce560..cfadc37d5d3 100644 --- a/docs-source/content/quickstart/install.md +++ b/docs-source/content/quickstart/install.md @@ -51,7 +51,7 @@ $ helm install traefik-operator traefik/traefik \ ```bash $ helm install sample-weblogic-operator kubernetes/charts/weblogic-operator \ --namespace sample-weblogic-operator-ns \ - --set image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3 \ + --set image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4 \ --set serviceAccount=sample-weblogic-operator-sa \ --set "enableClusterRoleBinding=true" \ --set "domainNamespaceSelectionStrategy=LabelSelector" \ diff --git a/docs-source/content/release-notes.md b/docs-source/content/release-notes.md index 4250c0b8f59..74216536809 100644 --- a/docs-source/content/release-notes.md +++ b/docs-source/content/release-notes.md @@ -8,6 +8,7 @@ draft: false | Date | Version | Introduces backward incompatibilities? | Change | | --- | --- | --- | --- | +| March 1, 2021 | v3.1.4 | no | Resolved an issue where the operator would ignore live data that was older than cached data, such as following an etcd restore and updated Kubernetes Java Client and Bouncy Castle dependencies. | | February 12, 2021 | v3.1.3 | no | Resolved a pair of issues related to the operator running well in very large Kubernetes clusters. | | January 22, 2021 | v3.1.2 | no | Resolved an issue where the operator failed to start servers in which the pods were configured to have an annotation containing a forward slash. | | December 17, 2020 | v3.1.1 | no | Resolved an issue that caused unexpected server restarts when the domain had multiple WebLogic clusters. | @@ -35,6 +36,11 @@ draft: false ### Change log +#### Operator 3.1.4 + +* Resolved an issue where the operator would ignore live data that was older than cached data, such as following an etcd restore ([#2196](https://github.com/oracle/weblogic-kubernetes-operator/pull/2196)). +* Updated Kubernetes Java Client and Bouncy Castle dependencies. + #### Operator 3.1.3 * Resolved an issue that caused some WebLogic Servers to fail to start in large Kubernetes clusters where Kubernetes watch notifications were not reliably delivered ([#2188](https://github.com/oracle/weblogic-kubernetes-operator/pull/2188)). diff --git a/docs-source/content/userguide/introduction/architecture.md b/docs-source/content/userguide/introduction/architecture.md index c5de0869e97..83dccf541e8 100644 --- a/docs-source/content/userguide/introduction/architecture.md +++ b/docs-source/content/userguide/introduction/architecture.md @@ -17,7 +17,7 @@ The operator consists of the following parts: The operator is packaged in a [container image](https://github.com/orgs/oracle/packages/container/package/weblogic-kubernetes-operator) which you can access using the following `docker pull` commands: ``` -$ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3 +$ docker pull ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4 ``` For more details on acquiring the operator image and prerequisites for installing the operator, consult the [Quick Start guide]({{< relref "/quickstart/_index.md" >}}). diff --git a/docs-source/content/userguide/introduction/introduction.md b/docs-source/content/userguide/introduction/introduction.md index 9df2a8b0601..6d146b754cc 100644 --- a/docs-source/content/userguide/introduction/introduction.md +++ b/docs-source/content/userguide/introduction/introduction.md @@ -16,7 +16,7 @@ Detailed instructions are available [here]({{< relref "/userguide/managing-opera ### Operator prerequisites -For the current production release 3.1.3: +For the current production release 3.1.4: * Kubernetes 1.14.8+, 1.15.7+, 1.16.0+, 1.17.0+, and 1.18.0+ (check with `kubectl version`). * Flannel networking v0.9.1-amd64 or later (check with `docker images | grep flannel`), Calico networking (Calico v3.16.1), diff --git a/docs-source/content/userguide/managing-domains/domain-lifecycle/restarting.md b/docs-source/content/userguide/managing-domains/domain-lifecycle/restarting.md index 2bc06bcb9bd..ef1720b7357 100644 --- a/docs-source/content/userguide/managing-domains/domain-lifecycle/restarting.md +++ b/docs-source/content/userguide/managing-domains/domain-lifecycle/restarting.md @@ -188,7 +188,7 @@ d. Update the `image` field of the Domain YAML file, specifying the new image na ``` domain: spec: - image: ghcr.io/oracle/weblogic-updated:3.1.3 + image: ghcr.io/oracle/weblogic-updated:3.1.4 ``` e. The operator will now initiate a rolling restart, which will apply the updated image, for all the servers in the domain. diff --git a/docs-source/content/userguide/managing-operators/installation/_index.md b/docs-source/content/userguide/managing-operators/installation/_index.md index 7057bda4bad..9cee421c7ec 100644 --- a/docs-source/content/userguide/managing-operators/installation/_index.md +++ b/docs-source/content/userguide/managing-operators/installation/_index.md @@ -117,7 +117,7 @@ the `helm upgrade` command requires that you supply a new Helm chart and image. ``` $ helm upgrade \ --reuse-values \ - --set image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3 \ + --set image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4 \ --namespace weblogic-operator-namespace \ --wait \ weblogic-operator \ diff --git a/docs-source/content/userguide/managing-operators/using-the-operator/using-helm.md b/docs-source/content/userguide/managing-operators/using-the-operator/using-helm.md index 158a6045dbb..82eb15390c7 100644 --- a/docs-source/content/userguide/managing-operators/using-the-operator/using-helm.md +++ b/docs-source/content/userguide/managing-operators/using-the-operator/using-helm.md @@ -100,7 +100,7 @@ javaLoggingLevel: "FINE" ##### `image` Specifies the container image containing the operator code. -Defaults to `ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3`. +Defaults to `ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4`. Example: ``` diff --git a/docs/charts/index.yaml b/docs/charts/index.yaml index a26f77b5c9b..52fc665ce68 100644 --- a/docs/charts/index.yaml +++ b/docs/charts/index.yaml @@ -1,9 +1,19 @@ apiVersion: v1 entries: weblogic-operator: + - apiVersion: v1 + appVersion: 3.1.4 + created: "2021-02-16T15:11:42.543971-05:00" + description: Helm chart for configuring the WebLogic operator. + digest: 9695fd3c29cd4f006f8e75ae0053683c9aa7213440525002f4f3d36eb8d86633 + name: weblogic-operator + type: application + urls: + - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.1.4.tgz + version: 3.1.4 - apiVersion: v1 appVersion: 3.1.3 - created: "2021-02-10T17:50:16.488182-05:00" + created: "2021-02-16T15:11:42.542857-05:00" description: Helm chart for configuring the WebLogic operator. digest: e306bd590dbe84400c6b5bb7a64325330e597223dff63792bb5811c9cfae10ac name: weblogic-operator @@ -13,7 +23,7 @@ entries: version: 3.1.3 - apiVersion: v1 appVersion: 3.1.2 - created: "2021-02-10T17:50:16.486986-05:00" + created: "2021-02-16T15:11:42.541531-05:00" description: Helm chart for configuring the WebLogic operator. digest: 2d8b77038ba870cc66ddd45e07a593a5ac3159c8b9531b5309688028b5268a5f name: weblogic-operator @@ -23,7 +33,7 @@ entries: version: 3.1.2 - apiVersion: v1 appVersion: 3.1.1 - created: "2021-02-10T17:50:16.485923-05:00" + created: "2021-02-16T15:11:42.54047-05:00" description: Helm chart for configuring the WebLogic operator. digest: d839cb7bbce4421a59cd9c3df64b1df8649eeebcb6c6b7be34fec25ad00aa141 name: weblogic-operator @@ -33,7 +43,7 @@ entries: version: 3.1.1 - apiVersion: v1 appVersion: 3.1.0 - created: "2021-02-10T17:50:16.484888-05:00" + created: "2021-02-16T15:11:42.539408-05:00" description: Helm chart for configuring the WebLogic operator. digest: 9e105bec11bab249973370a4d5e653f9104cd9fbaaa0c2090fb173805fb3a692 name: weblogic-operator @@ -42,7 +52,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.1.0.tgz version: 3.1.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.483985-05:00" + created: "2021-02-16T15:11:42.538298-05:00" description: Helm chart for configuring the WebLogic operator. digest: 557d0df9958bbdd2f456134d8aff9edf33900bb65774fb0baf2054abd49fdc97 name: weblogic-operator @@ -50,7 +60,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.4.tgz version: 3.0.4 - apiVersion: v1 - created: "2021-02-10T17:50:16.4832-05:00" + created: "2021-02-16T15:11:42.537425-05:00" description: Helm chart for configuring the WebLogic operator. digest: 83a0ac84a033ddd9939d4bc5884cc60b22225d7326c43ce8e54a6f403b453814 name: weblogic-operator @@ -58,7 +68,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.3.tgz version: 3.0.3 - apiVersion: v1 - created: "2021-02-10T17:50:16.482401-05:00" + created: "2021-02-16T15:11:42.536587-05:00" description: Helm chart for configuring the WebLogic operator. digest: fa3af5d21f858ff93cc7d58664a6eb0a920207af09e4c669a7ffb12e9e15b88d name: weblogic-operator @@ -66,7 +76,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.2.tgz version: 3.0.2 - apiVersion: v1 - created: "2021-02-10T17:50:16.481218-05:00" + created: "2021-02-16T15:11:42.535498-05:00" description: Helm chart for configuring the WebLogic operator. digest: aa2b2afe75305bd69f6b07d61e64a37d3bfd249074c81f6a999cef6b4a217fd0 name: weblogic-operator @@ -74,7 +84,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.1.tgz version: 3.0.1 - apiVersion: v1 - created: "2021-02-10T17:50:16.480314-05:00" + created: "2021-02-16T15:11:42.534546-05:00" description: Helm chart for configuring the WebLogic operator. digest: 6540a3a7c6a1c34fcf2ff66679947a1964a35e61232b2a8dea3da087a2d5411d name: weblogic-operator @@ -82,7 +92,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.0.tgz version: 3.0.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.479539-05:00" + created: "2021-02-16T15:11:42.533725-05:00" description: Helm chart for configuring the WebLogic operator. digest: 5f4cd8f4f3282b52b5e90a1169f26986e8272671845053606ade9c855fb04151 name: weblogic-operator @@ -90,7 +100,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-3.0.0-rc1.tgz version: 3.0.0-rc1 - apiVersion: v1 - created: "2021-02-10T17:50:16.478481-05:00" + created: "2021-02-16T15:11:42.532636-05:00" description: Helm chart for configuring the WebLogic operator. digest: e3596b2380b264a0a70ba438858ca9af102a79689bf2e21e237eb63ea2997d66 name: weblogic-operator @@ -98,7 +108,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.6.0.tgz version: 2.6.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.476979-05:00" + created: "2021-02-16T15:11:42.531418-05:00" description: Helm chart for configuring the WebLogic operator. digest: fe41421b7dc45dc8a3b2888d3a626a37f5d3c8e1fa292fb6699deedc5e1db33d name: weblogic-operator @@ -106,7 +116,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.5.0.tgz version: 2.5.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.476056-05:00" + created: "2021-02-16T15:11:42.530436-05:00" description: Helm chart for configuring the WebLogic operator. digest: b36bd32083f67453a62d089a2c09ce38e6655d88ac8a7b38691230c55c40e672 name: weblogic-operator @@ -114,7 +124,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.4.0.tgz version: 2.4.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.474873-05:00" + created: "2021-02-16T15:11:42.529262-05:00" description: Helm chart for configuring the WebLogic operator. digest: a3eafe4c2c6ff49384e56421201e59a3737d651af8d5b605b87a19eb1f6f1dc3 name: weblogic-operator @@ -122,7 +132,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.3.1.tgz version: 2.3.1 - apiVersion: v1 - created: "2021-02-10T17:50:16.470949-05:00" + created: "2021-02-16T15:11:42.523748-05:00" description: Helm chart for configuring the WebLogic operator. digest: cbc6caaa6eb28e3c7e906ede14b2ae511a0b35fc12a8e3ab629155b09993e8b2 name: weblogic-operator @@ -130,7 +140,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.3.0.tgz version: 2.3.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.470037-05:00" + created: "2021-02-16T15:11:42.522793-05:00" description: Helm chart for configuring the WebLogic operator. digest: 23d5a1c554fa8211cc1e86b7ade09460917cb2069e68fb4bfdddafc8db44fdcd name: weblogic-operator @@ -138,7 +148,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.2.1.tgz version: 2.2.1 - apiVersion: v1 - created: "2021-02-10T17:50:16.468969-05:00" + created: "2021-02-16T15:11:42.521649-05:00" description: Helm chart for configuring the WebLogic operator. digest: bba303686cb55d84fe8c0d693a2436e7e686b028085b56e012f6381699a3911f name: weblogic-operator @@ -146,7 +156,7 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.2.0.tgz version: 2.2.0 - apiVersion: v1 - created: "2021-02-10T17:50:16.468145-05:00" + created: "2021-02-16T15:11:42.520707-05:00" description: Helm chart for configuring the WebLogic operator. digest: 391e23c0969ada5f0cd2a088ddc6f11f237f57521801ed3925db2149a8437a0d name: weblogic-operator @@ -154,11 +164,11 @@ entries: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.1.tgz version: "2.1" - apiVersion: v1 - created: "2021-02-10T17:50:16.467352-05:00" + created: "2021-02-16T15:11:42.519794-05:00" description: Helm chart for configuring the WebLogic operator. digest: 298acda78ab73db6b7ba6f2752311bfa40c65874e03fb196b70976192211c1a5 name: weblogic-operator urls: - https://oracle.github.io/weblogic-kubernetes-operator/charts/weblogic-operator-2.0.1.tgz version: 2.0.1 -generated: "2021-02-10T17:50:16.465537-05:00" +generated: "2021-02-16T15:11:42.51736-05:00" diff --git a/docs/charts/weblogic-operator-3.1.4.tgz b/docs/charts/weblogic-operator-3.1.4.tgz new file mode 100644 index 00000000000..65e5368712b Binary files /dev/null and b/docs/charts/weblogic-operator-3.1.4.tgz differ diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml index a7ffff6423e..11c8c397816 100644 --- a/integration-tests/pom.xml +++ b/integration-tests/pom.xml @@ -7,7 +7,7 @@ oracle.kubernetes operator-parent - 3.1.3 + 3.1.4 integration-tests diff --git a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java index 0537f55793b..3f46b22310f 100644 --- a/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java +++ b/integration-tests/src/test/java/oracle/weblogic/kubernetes/utils/CommonTestUtils.java @@ -1646,7 +1646,7 @@ public static void checkServiceDoesNotExist(String serviceName, String namespace * @param domainName Name of domain to which cluster belongs * @param namespace cluster's namespace * @param replicaCount replica count value to match - * @return + * @return true, if the cluster replica count is matched */ public static boolean checkClusterReplicaCountMatches(String clusterName, String domainName, String namespace, Integer replicaCount) throws ApiException { diff --git a/json-schema-maven-plugin/pom.xml b/json-schema-maven-plugin/pom.xml index 2c8ea716fe8..45ad0c3b56e 100644 --- a/json-schema-maven-plugin/pom.xml +++ b/json-schema-maven-plugin/pom.xml @@ -7,7 +7,7 @@ operator-parent oracle.kubernetes - 3.1.3 + 3.1.4 jsonschema-maven-plugin diff --git a/json-schema/pom.xml b/json-schema/pom.xml index d44b315d619..650db9e2296 100644 --- a/json-schema/pom.xml +++ b/json-schema/pom.xml @@ -7,7 +7,7 @@ operator-parent oracle.kubernetes - 3.1.3 + 3.1.4 json-schema diff --git a/kubernetes/charts/weblogic-operator/Chart.yaml b/kubernetes/charts/weblogic-operator/Chart.yaml index ab0e4716a99..73bc01b83ae 100644 --- a/kubernetes/charts/weblogic-operator/Chart.yaml +++ b/kubernetes/charts/weblogic-operator/Chart.yaml @@ -6,5 +6,5 @@ name: weblogic-operator description: Helm chart for configuring the WebLogic operator. type: application -version: 3.1.3 -appVersion: 3.1.3 +version: 3.1.4 +appVersion: 3.1.4 diff --git a/kubernetes/charts/weblogic-operator/values.yaml b/kubernetes/charts/weblogic-operator/values.yaml index d7b6fe627f6..a3101698aff 100644 --- a/kubernetes/charts/weblogic-operator/values.yaml +++ b/kubernetes/charts/weblogic-operator/values.yaml @@ -63,7 +63,7 @@ domainNamespaces: enableClusterRoleBinding: false # image specifies the container image containing the operator. -image: "ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3" +image: "ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4" # imagePullPolicy specifies the image pull policy for the operator's container image. imagePullPolicy: IfNotPresent diff --git a/kubernetes/hands-on-lab/tutorials/install.operator.ocishell.md b/kubernetes/hands-on-lab/tutorials/install.operator.ocishell.md index a2168408e95..ddfe7ebe0b0 100644 --- a/kubernetes/hands-on-lab/tutorials/install.operator.ocishell.md +++ b/kubernetes/hands-on-lab/tutorials/install.operator.ocishell.md @@ -65,7 +65,7 @@ Note the arguments and values: - The name of the Helm release. - The relative path to the Helm chart. - **namespace**: The namespace where the operator is to be deployed. -- **image**: The prebuilt operator 3.1.3 image, available on the public GitHub Container Registry. +- **image**: The prebuilt operator 3.1.4 image, available on the public GitHub Container Registry. - **serviceAccount**: The service account required to run the operator. - **enableClusterRoleBinding**: Grants the operator privileges in all cluster namespaces. - **domainNamespaceSelectionStrategy**: Chooses how the operator will select namespaces it manages. @@ -78,7 +78,7 @@ Execute the following `helm install`: helm install sample-weblogic-operator \ kubernetes/charts/weblogic-operator \ --namespace sample-weblogic-operator-ns \ - --set "image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.3" \ + --set "image=ghcr.io/oracle/weblogic-kubernetes-operator:3.1.4" \ --set "serviceAccount=sample-weblogic-operator-sa" \ --set "enableClusterRoleBinding=true" \ --set "domainNamespaceSelectionStrategy=LabelSelector" \ diff --git a/kubernetes/pom.xml b/kubernetes/pom.xml index 3f773df21f2..be5293d1c74 100644 --- a/kubernetes/pom.xml +++ b/kubernetes/pom.xml @@ -9,7 +9,7 @@ oracle.kubernetes operator-parent - 3.1.3 + 3.1.4 installation-tests diff --git a/kubernetes/samples/scripts/domain-lifecycle/helper.sh b/kubernetes/samples/scripts/domain-lifecycle/helper.sh index 6d949885e74..bcb57fc95e3 100644 --- a/kubernetes/samples/scripts/domain-lifecycle/helper.sh +++ b/kubernetes/samples/scripts/domain-lifecycle/helper.sh @@ -1,5 +1,5 @@ # !/bin/sh -# Copyright (c) 2020, Oracle Corporation and/or its affiliates. +# Copyright (c) 2020, 2021, Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. # @@ -111,14 +111,24 @@ function createServerStartPolicyPatch { local policy=$3 local __result=$4 local currentStartPolicy="" + local serverStartPolicyPatch="" # Get server start policy for this server getServerPolicy "${domainJson}" "${serverName}" currentStartPolicy - if [ -z "${currentStartPolicy}" ]; then + managedServers=$(echo ${domainJson} | jq -cr '(.spec.managedServers)') + if [[ -z "${currentStartPolicy}" && "${managedServers}" == "null" ]]; then # Server start policy doesn't exist, add a new policy addPolicyCmd=".[.| length] |= . + {\"serverName\":\"${serverName}\", \ \"serverStartPolicy\":\"${policy}\"}" serverStartPolicyPatch=$(echo ${domainJson} | jq .spec.managedServers | jq -c "${addPolicyCmd}") + elif [ "${managedServers}" != "null" ]; then + extractSpecCmd="(.spec.managedServers)" + mapCmd="\ + . |= (map(.serverName) | index (\"${serverName}\")) as \$idx | \ + if \$idx then \ + .[\$idx][\"serverStartPolicy\"] = \"${policy}\" \ + else .+ [{serverName: \"${serverName}\" , serverStartPolicy: \"${policy}\"}] end" + serverStartPolicyPatch=$(echo ${domainJson} | jq "${extractSpecCmd}" | jq "${mapCmd}") else # Server start policy exists, replace policy value replacePolicyCmd="(.spec.managedServers[] \ @@ -142,9 +152,7 @@ function createPatchJsonToUnsetPolicyAndUpdateReplica { local replicaPatch=$3 local __result=$4 - replacePolicyCmd="[(.spec.managedServers[] \ - | select (.serverName != \"${serverName}\"))]" - serverStartPolicyPatch=$(echo ${domainJson} | jq "${replacePolicyCmd}") + unsetServerStartPolicy "${domainJson}" "${serverName}" serverStartPolicyPatch patchJson="{\"spec\": {\"clusters\": "${replicaPatch}",\"managedServers\": "${serverStartPolicyPatch}"}}" eval $__result="'${patchJson}'" } @@ -199,13 +207,35 @@ function createPatchJsonToUnsetPolicy { local serverName=$2 local __result=$3 - replacePolicyCmd="[(.spec.managedServers[] \ - | select (.serverName != \"${serverName}\"))]" - serverStartPolicyPatch=$(echo ${domainJson} | jq "${replacePolicyCmd}") + unsetServerStartPolicy "${domainJson}" "${serverName}" serverStartPolicyPatch patchJson="{\"spec\": {\"managedServers\": "${serverStartPolicyPatch}"}}" eval $__result="'${patchJson}'" } +# +# Function to create patch string with server start policy unset +# $1 - Domain resource in json format +# $2 - Name of server whose policy will be unset +# $3 - Return value containing patch string with server start policy unset +# +function unsetServerStartPolicy { + local domainJson=$1 + local serverName=$2 + local __result=$3 + local unsetStartPolicyPatch="" + + unsetCmd="(.spec.managedServers[] | select (.serverName == \"${serverName}\") | del (.serverStartPolicy))" + replacePolicyCmd=$(echo ${domainJson} | jq -cr "${unsetCmd}") + replacePolicyCmdLen=$(echo "${replacePolicyCmd}" | jq -e keys_unsorted | jq length) + if [ ${replacePolicyCmdLen} == 1 ]; then + mapCmd=". |= map(if .serverName == \"${serverName}\" then del(.) else . end)" + else + mapCmd=". |= map(if .serverName == \"${serverName}\" then . = ${replacePolicyCmd} else . end)" + fi + unsetStartPolicyPatch=$(echo ${domainJson} | jq "(.spec.managedServers)" | jq "${mapCmd}") + eval $__result="'${unsetStartPolicyPatch}'" +} + # # Function to create patch json to update cluster server start policy # $1 - Domain resource in json format @@ -693,8 +723,6 @@ function timestamp() { local ymdhms="`echo $timestamp | awk '{ print $1 }'`" # convert nano to milli local milli="`echo $timestamp | awk '{ print $2 }' | sed 's/\(^...\).*/\1/'`" - local secs_since_epoch="`echo $timestamp | awk '{ print $3 }'`" - local millis_since_opoch="${secs_since_epoch}${milli}" local timezone="`echo $timestamp | awk '{ print $4 }'`" echo "${ymdhms}.${milli} ${timezone}" } diff --git a/operator/pom.xml b/operator/pom.xml index 1ab7d81001d..c1e6c31553d 100644 --- a/operator/pom.xml +++ b/operator/pom.xml @@ -7,7 +7,7 @@ oracle.kubernetes operator-parent - 3.1.3 + 3.1.4 weblogic-kubernetes-operator @@ -30,7 +30,7 @@ pl.project13.maven git-commit-id-plugin - 2.2.6 + ${git-commit-id-plugin-version} get-the-git-infos @@ -318,6 +318,19 @@ javaee-web-api + + org.bouncycastle + bcprov-ext-jdk15on + + + org.bouncycastle + bcpkix-jdk15on + + + com.google.guava + guava + + javax.xml.bind diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java b/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java index 68f56208af3..54ac956adf8 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java @@ -662,7 +662,8 @@ private boolean isShouldContinue() { LOGGER.fine("Stop introspection retry - MII Fatal Error: " + existingError); return false; - } else if (isCachedInfoNewer(liveInfo, cachedInfo)) { + } else if (!liveInfo.isPopulated() && isCachedInfoNewer(liveInfo, cachedInfo)) { + LOGGER.fine("Cached domain info is newer than the live info from the watch event ."); return false; // we have already cached this } else if (explicitRecheck || isSpecChanged(liveInfo, cachedInfo)) { if (exceededFailureRetryCount) { @@ -677,7 +678,7 @@ private boolean isShouldContinue() { currentIntrospectFailureRetryCount, DomainPresence.getDomainPresenceFailureRetryMaxCount()); } - + LOGGER.fine("Continue the make-right domain presence, explicitRecheck -> " + explicitRecheck); return true; } cachedInfo.setDomain(getDomain()); diff --git a/operator/src/main/java/oracle/kubernetes/operator/JobWatcher.java b/operator/src/main/java/oracle/kubernetes/operator/JobWatcher.java index f3c32342f87..31626ec91ab 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/JobWatcher.java +++ b/operator/src/main/java/oracle/kubernetes/operator/JobWatcher.java @@ -3,6 +3,7 @@ package oracle.kubernetes.operator; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Optional; @@ -10,6 +11,7 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Consumer; +import javax.annotation.Nonnull; import io.kubernetes.client.openapi.ApiException; import io.kubernetes.client.openapi.models.V1Job; @@ -137,16 +139,38 @@ static boolean isFailed(V1Job job) { return false; } - V1JobStatus status = job.getStatus(); - if (status != null) { - if (status.getFailed() != null && status.getFailed() > 0) { - LOGGER.severe(MessageKeys.JOB_IS_FAILED, job.getMetadata().getName()); - return true; - } + if (isStatusFailed(job) || isConditionFailed(job)) { + LOGGER.severe(MessageKeys.JOB_IS_FAILED, job.getMetadata().getName()); + return true; } return false; } + private static boolean isStatusFailed(V1Job job) { + return Optional.ofNullable(job.getStatus()).map(V1JobStatus::getFailed).map(failed -> (failed > 0)).orElse(false); + } + + private static boolean isConditionFailed(V1Job job) { + return getJobConditions(job).stream().anyMatch(JobWatcher::isJobConditionFailed); + } + + private static List getJobConditions(@Nonnull V1Job job) { + return Optional.ofNullable(job.getStatus()).map(V1JobStatus::getConditions).orElse(Collections.emptyList()); + } + + private static boolean isJobConditionFailed(V1JobCondition jobCondition) { + return getType(jobCondition).equals("Failed") && getStatus(jobCondition).equals("True"); + } + + private static String getType(V1JobCondition jobCondition) { + return Optional.ofNullable(jobCondition).map(V1JobCondition::getType).orElse(""); + } + + private static String getStatus(V1JobCondition jobCondition) { + return Optional.ofNullable(jobCondition).map(V1JobCondition::getStatus).orElse(""); + } + + static String getFailedReason(V1Job job) { V1JobStatus status = job.getStatus(); if (status != null && status.getConditions() != null) { @@ -305,4 +329,4 @@ private long getJobStartedSeconds() { return -1; } } -} +} \ No newline at end of file diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java index ac49c24dcef..5b272538753 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java +++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java @@ -370,7 +370,7 @@ protected Step patchPod(V1Pod currentPod, Step next) { return new CallBuilder() .patchPodAsync(getPodName(), getNamespace(), getDomainUid(), - new V1Patch(patchBuilder.build().toString()), patchResponse(next)); + new V1Patch(patchBuilder.build().toString()), patchResponse(next)); } private Map getNonHashedPodLabels() { diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/RollingHelper.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/RollingHelper.java index c52dd2fdf40..7ec6b1f8782 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/helpers/RollingHelper.java +++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/RollingHelper.java @@ -134,6 +134,7 @@ public NextAction apply(Packet packet) { } if (!clusteredRestarts.isEmpty()) { + LOGGER.fine("Restarting server " + packet.get(ProcessingConstants.SERVER_NAME)); for (Map.Entry> entry : clusteredRestarts.entrySet()) { work.add( new StepAndPacket( diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/ServiceHelper.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/ServiceHelper.java index 45ab3321e75..dfc21170ef9 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/helpers/ServiceHelper.java +++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/ServiceHelper.java @@ -4,16 +4,19 @@ package oracle.kubernetes.operator.helpers; import java.util.ArrayList; +import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; +import java.util.stream.Collectors; import javax.annotation.Nonnull; import io.kubernetes.client.openapi.models.V1DeleteOptions; import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1Service; +import io.kubernetes.client.openapi.models.V1ServiceList; import io.kubernetes.client.openapi.models.V1ServicePort; import io.kubernetes.client.openapi.models.V1ServiceSpec; import io.kubernetes.client.openapi.models.V1Status; @@ -24,7 +27,9 @@ import oracle.kubernetes.operator.calls.UnrecoverableErrorBuilder; import oracle.kubernetes.operator.logging.LoggingFacade; import oracle.kubernetes.operator.logging.LoggingFactory; +import oracle.kubernetes.operator.steps.ActionResponseStep; import oracle.kubernetes.operator.steps.DefaultResponseStep; +import oracle.kubernetes.operator.steps.DeleteServiceListStep; import oracle.kubernetes.operator.wlsconfig.NetworkAccessPoint; import oracle.kubernetes.operator.wlsconfig.WlsClusterConfig; import oracle.kubernetes.operator.wlsconfig.WlsDomainConfig; @@ -40,7 +45,10 @@ import oracle.kubernetes.weblogic.domain.model.ServerSpec; import org.apache.commons.lang3.builder.EqualsBuilder; +import static oracle.kubernetes.operator.LabelConstants.forDomainUidSelector; +import static oracle.kubernetes.operator.LabelConstants.getCreatedbyOperatorSelector; import static oracle.kubernetes.operator.helpers.KubernetesUtils.getDomainUidLabel; +import static oracle.kubernetes.operator.helpers.OperatorServiceType.EXTERNAL; import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_SERVICE_CREATED; import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_SERVICE_EXISTS; import static oracle.kubernetes.operator.logging.MessageKeys.ADMIN_SERVICE_REPLACED; @@ -527,10 +535,29 @@ private Step createNewService(Step next) { protected abstract String getServiceCreatedMessageKey(); private Step deleteAndReplaceService(Step next) { - V1DeleteOptions deleteOptions = new V1DeleteOptions(); + if (serviceType == EXTERNAL) { + return deleteAndReplaceNodePortService(); + } else { + V1DeleteOptions deleteOptions = new V1DeleteOptions(); + return new CallBuilder() + .deleteServiceAsync( + createServiceName(), getNamespace(), getDomainUid(), deleteOptions, new DeleteServiceResponse(next)); + } + } + + private Step deleteAndReplaceNodePortService() { return new CallBuilder() - .deleteServiceAsync( - createServiceName(), getNamespace(), getDomainUid(), deleteOptions, new DeleteServiceResponse(next)); + .withLabelSelectors(forDomainUidSelector(info.getDomainUid()), getCreatedbyOperatorSelector()) + .listServiceAsync( + getNamespace(), + new ActionResponseStep() { + public Step createSuccessStep(V1ServiceList result, Step next) { + Collection c = Optional.ofNullable(result).map(list -> list.getItems().stream() + .filter(s -> isNodePortType(s)) + .collect(Collectors.toList())).orElse(new ArrayList<>()); + return new DeleteServiceListStep(c, createReplacementService(next)); + } + }); } private Step createReplacementService(Step next) { @@ -798,7 +825,7 @@ private static class ExternalServiceStepContext extends ServiceStepContext { private final String adminServerName; ExternalServiceStepContext(Step conflictStep, Packet packet) { - super(conflictStep, packet, OperatorServiceType.EXTERNAL); + super(conflictStep, packet, EXTERNAL); adminServerName = (String) packet.get(ProcessingConstants.SERVER_NAME); } diff --git a/operator/src/main/java/oracle/kubernetes/operator/steps/ActionResponseStep.java b/operator/src/main/java/oracle/kubernetes/operator/steps/ActionResponseStep.java index e7fb9315f32..cd04c2b38ab 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/steps/ActionResponseStep.java +++ b/operator/src/main/java/oracle/kubernetes/operator/steps/ActionResponseStep.java @@ -27,7 +27,7 @@ public NextAction onSuccess(Packet packet, CallResponse callResponse) { return callResponse.getResult() == null ? doNext(packet) : doNext(createSuccessStep(callResponse.getResult(), - new ContinueOrNextStep(callResponse, getNext())), packet); + new ContinueOrNextStep(callResponse, getNext())), packet); } private class ContinueOrNextStep extends Step { diff --git a/operator/src/main/java/oracle/kubernetes/operator/steps/DeleteServiceListStep.java b/operator/src/main/java/oracle/kubernetes/operator/steps/DeleteServiceListStep.java index 56298bae316..e83635dfeac 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/steps/DeleteServiceListStep.java +++ b/operator/src/main/java/oracle/kubernetes/operator/steps/DeleteServiceListStep.java @@ -19,7 +19,7 @@ */ public class DeleteServiceListStep extends AbstractListStep { - DeleteServiceListStep(Collection c, Step next) { + public DeleteServiceListStep(Collection c, Step next) { super(c, next); } diff --git a/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsClusterConfig.java b/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsClusterConfig.java index add382641df..f85ad5015de 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsClusterConfig.java +++ b/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsClusterConfig.java @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates. +// Copyright (c) 2017, 2021, Oracle Corporation and/or its affiliates. // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. package oracle.kubernetes.operator.wlsconfig; @@ -8,6 +8,7 @@ import java.util.Comparator; import java.util.List; import java.util.Map; +import javax.annotation.Nonnull; import oracle.kubernetes.utils.OperatorUtils; import org.apache.commons.lang3.builder.EqualsBuilder; @@ -377,6 +378,17 @@ public String getUpdateDynamicClusterSizePayload(final int clusterSize) { return "{ dynamicClusterSize: " + clusterSize + " }"; } + /** + * Whether this cluster contains a server with the given server name, + * including servers that are both configured and dynamic servers. + * + * @param serverName server name to be checked + * @return True if the cluster contains a server with the given server name + */ + boolean containsServer(@Nonnull String serverName) { + return getServerConfigs().stream().anyMatch(c -> serverName.equals(c.getName())); + } + @Override public String toString() { return new ToStringBuilder(this) diff --git a/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfig.java b/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfig.java index 42e7093cc19..7df8f7a7221 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfig.java +++ b/operator/src/main/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfig.java @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates. +// Copyright (c) 2017, 2021, Oracle Corporation and/or its affiliates. // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. package oracle.kubernetes.operator.wlsconfig; @@ -11,6 +11,7 @@ import javax.annotation.Nonnull; import com.fasterxml.jackson.databind.ObjectMapper; +import com.google.common.base.Strings; import oracle.kubernetes.operator.logging.LoggingFacade; import oracle.kubernetes.operator.logging.LoggingFactory; import oracle.kubernetes.operator.logging.MessageKeys; @@ -392,18 +393,16 @@ public synchronized boolean containsCluster(String clusterName) { /** * Whether the WebLogic domain contains a server with the given server name, - * not including servers that are part of a dynamic cluster. + * including standalone servers, and servers that belong to a + * configured or dynamic cluster. * * @param serverName server name to be checked * @return True if the WebLogic domain contains a server with the given server name */ public synchronized boolean containsServer(String serverName) { - if (serverName != null && servers != null) { - for (WlsServerConfig serverConfig : servers) { - if (serverConfig.getName().equals(serverName)) { - return true; - } - } + if (!Strings.isNullOrEmpty(serverName)) { + return getServers().stream().anyMatch(s -> serverName.equals(s.getName())) + || getConfiguredClusters().stream().anyMatch(c -> c.containsServer(serverName)); } return false; } diff --git a/operator/src/test/java/oracle/kubernetes/operator/JobWatcherTest.java b/operator/src/test/java/oracle/kubernetes/operator/JobWatcherTest.java index 3a197d4f23b..90c18c17aac 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/JobWatcherTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/JobWatcherTest.java @@ -4,6 +4,8 @@ package oracle.kubernetes.operator; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.Function; @@ -128,6 +130,28 @@ public void whenJobConditionStatusFalse_reportNotComplete() { assertThat(JobWatcher.isComplete(cachedJob), is(false)); } + @Test + public void whenJobConditionTypeFailedWithTrueStatus_reportFailed() { + markJobConditionFailed(cachedJob); + + assertThat(JobWatcher.isFailed(cachedJob), is(true)); + } + + @Test + public void whenJobConditionTypeFailedWithNoStatus_reportNotFailed() { + cachedJob.status(new V1JobStatus().addConditionsItem(new V1JobCondition().type("Failed").status(""))); + + assertThat(JobWatcher.isFailed(cachedJob), is(false)); + } + + @Test + public void whenJobHasStatusWithNoConditionsAndNotFailed_reportNotFailed() { + cachedJob.status(new V1JobStatus().conditions(Collections.emptyList())); + + assertThat(JobWatcher.isFailed(cachedJob), is(false)); + } + + @Test public void whenJobRunningAndReadyConditionIsTrue_reportComplete() { markJobCompleted(cachedJob); @@ -151,6 +175,10 @@ private V1Job markJobFailed(V1Job job) { return setFailedWithReason(job, null); } + private V1Job markJobConditionFailed(V1Job job) { + return setFailedConditionWithReason(job, null); + } + private V1Job markJobTimedOut(V1Job job) { return markJobTimedOut(job, "DeadlineExceeded"); } @@ -163,6 +191,11 @@ private V1Job setFailedWithReason(V1Job job, String reason) { return job.status(new V1JobStatus().failed(1).addConditionsItem(createCondition("Failed").reason(reason))); } + private V1Job setFailedConditionWithReason(V1Job job, String reason) { + return job.status(new V1JobStatus().conditions( + new ArrayList<>(Arrays.asList(new V1JobCondition().type("Failed").status("True").reason(reason))))); + } + @Test public void whenJobHasNoStatus_reportNotFailed() { assertThat(JobWatcher.isFailed(cachedJob), is(false)); @@ -248,6 +281,13 @@ public void whenWaitForReadyAppliedToFailedJob_performNextStep() { assertThat(terminalStep.wasRun(), is(true)); } + @Test + public void whenWaitForReadyAppliedToJobWithFailedCondition_performNextStep() { + startWaitForReady(this::markJobConditionFailed); + + assertThat(terminalStep.wasRun(), is(true)); + } + // Starts the waitForReady step with job modified as needed private void startWaitForReady(Function jobFunction) { AtomicBoolean stopping = new AtomicBoolean(false); diff --git a/operator/src/test/java/oracle/kubernetes/operator/PodWatcherTest.java b/operator/src/test/java/oracle/kubernetes/operator/PodWatcherTest.java index ead3f5467ef..0f82f3bbbde 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/PodWatcherTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/PodWatcherTest.java @@ -21,6 +21,7 @@ import io.kubernetes.client.openapi.models.V1PodStatus; import io.kubernetes.client.util.Watch; import oracle.kubernetes.operator.builders.StubWatchFactory; +import oracle.kubernetes.operator.helpers.DomainPresenceInfo; import oracle.kubernetes.operator.helpers.KubernetesTestSupport; import oracle.kubernetes.operator.watcher.WatchListener; import oracle.kubernetes.operator.work.Step; @@ -237,6 +238,13 @@ public void whenPodReadyLater_runNextStep() { assertThat(terminalStep.wasRun(), is(true)); } + @Test + public void whenPodCreatedAndReadyLater_runNextStep() { + sendPodModifiedWatchAfterResourceCreatedAndWaitForReady(this::markPodReady); + + assertThat(terminalStep.wasRun(), is(true)); + } + @Test public void whenPodNotReadyLater_dontRunNextStep() { sendPodModifiedWatchAfterWaitForReady(this::dontChangePod); @@ -293,6 +301,23 @@ private void sendPodModifiedWatchAfterWaitForReady(Function... modi } } + // Starts the waitForReady step with an uncreated pod and sends a watch indicating that the pod has changed + @SafeVarargs + private void sendPodModifiedWatchAfterResourceCreatedAndWaitForReady(Function... modifiers) { + AtomicBoolean stopping = new AtomicBoolean(false); + PodWatcher watcher = createWatcher(stopping); + + try { + testSupport.addDomainPresenceInfo(new DomainPresenceInfo(NS, "domain1")); + testSupport.runSteps(watcher.waitForReady(NAME, terminalStep)); + for (Function modifier : modifiers) { + watcher.receivedResponse(new Watch.Response<>("MODIFIED", modifier.apply(createPod()))); + } + } finally { + stopping.set(true); + } + } + // Simulates a pod that is ready but where Kubernetes has failed to send the watch event @SafeVarargs private void makeModifiedPodReadyWithNoWatchEvent(Function... modifiers) { diff --git a/operator/src/test/java/oracle/kubernetes/operator/ThreadFactoryTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/ThreadFactoryTestBase.java index 4c179bcf2f4..621404ef79a 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/ThreadFactoryTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/ThreadFactoryTestBase.java @@ -33,7 +33,7 @@ public Thread newThread(@Nonnull Runnable r) { return thread; } - void shutDownThreads() { + protected void shutDownThreads() { for (Thread thread : threads) { shutDown(thread); } diff --git a/operator/src/test/java/oracle/kubernetes/operator/helpers/ServiceHelperTest.java b/operator/src/test/java/oracle/kubernetes/operator/helpers/ServiceHelperTest.java index f1c1a7f0fb0..db5991ba82a 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/helpers/ServiceHelperTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/helpers/ServiceHelperTest.java @@ -19,9 +19,11 @@ import javax.annotation.Nonnull; import io.kubernetes.client.openapi.ApiException; +import io.kubernetes.client.openapi.models.V1ObjectMeta; import io.kubernetes.client.openapi.models.V1OwnerReference; import io.kubernetes.client.openapi.models.V1Service; import io.kubernetes.client.openapi.models.V1ServicePort; +import io.kubernetes.client.openapi.models.V1ServiceSpec; import oracle.kubernetes.operator.KubernetesConstants; import oracle.kubernetes.operator.LabelConstants; import oracle.kubernetes.operator.calls.FailureStatusSourceException; @@ -76,6 +78,7 @@ import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsInAnyOrder; +import static org.hamcrest.Matchers.empty; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasEntry; import static org.hamcrest.Matchers.is; @@ -121,6 +124,8 @@ public class ServiceHelperTest extends ServiceHelperTestBase { private static final int NAP_PORT_1 = 7100; private static final int NAP_PORT_2 = 37100; private static final int NAP_PORT_3 = 37200; + public static final String STRANDED = "Stranded"; + public static final String NODE_PORT = "NodePort"; private final TerminalStep terminalStep = new TerminalStep(); @Parameter public String testType; @Parameter(1) @@ -399,11 +404,20 @@ public void whenConfiguredSslListenPortChanged_replaceService() { private void verifyServiceReplaced(Runnable configurationMutator) { recordInitialService(); + if (testFacade instanceof ExternalServiceTestFacade) { + recordStrandedService(); + } configurationMutator.run(); runServiceHelper(); assertThat(logRecords, containsInfo(testFacade.getServiceReplacedLogMessage())); + assertThat(getStrandedService(), empty()); + } + + private List getStrandedService() { + ArrayList svcList = (ArrayList)testSupport.getResources(SERVICE); + return svcList.stream().filter(s -> s.getMetadata().getName().equals(STRANDED)).collect(Collectors.toList()); } private void configureNewLabel() { @@ -436,6 +450,16 @@ private void recordInitialService() { testFacade.recordService(domainPresenceInfo, originalService); } + private void recordStrandedService() { + Map labels = new HashMap<>(); + labels.put(LabelConstants.DOMAINUID_LABEL, UID); + labels.put(LabelConstants.CREATEDBYOPERATOR_LABEL, "true"); + V1Service strandedService = new V1Service().metadata(new V1ObjectMeta().name(STRANDED).namespace(NS) + .labels(labels)).spec(new V1ServiceSpec().type(NODE_PORT)); + testSupport.defineResources(strandedService); + testFacade.recordService(domainPresenceInfo, strandedService); + } + @Test public void whenServiceLabelAdded_dontReplaceService() { verifyServiceNotReplaced(this::addNewLabel); diff --git a/operator/src/test/java/oracle/kubernetes/operator/steps/ManagedServerUpIteratorStepTest.java b/operator/src/test/java/oracle/kubernetes/operator/steps/ManagedServerUpIteratorStepTest.java index ab2698e145f..56fd306624d 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/steps/ManagedServerUpIteratorStepTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/steps/ManagedServerUpIteratorStepTest.java @@ -3,6 +3,7 @@ package oracle.kubernetes.operator.steps; +import java.math.BigInteger; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -11,6 +12,7 @@ import java.util.Objects; import java.util.Optional; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import java.util.stream.IntStream; import javax.annotation.Nonnull; @@ -23,14 +25,21 @@ import io.kubernetes.client.openapi.models.V1PodSpec; import io.kubernetes.client.openapi.models.V1PodStatus; import io.kubernetes.client.openapi.models.V1SecretReference; +import io.kubernetes.client.util.Watch; import oracle.kubernetes.operator.KubernetesConstants; +import oracle.kubernetes.operator.PodAwaiterStepFactory; +import oracle.kubernetes.operator.PodWatcher; import oracle.kubernetes.operator.ProcessingConstants; +import oracle.kubernetes.operator.ThreadFactoryTestBase; +import oracle.kubernetes.operator.TuningParameters; +import oracle.kubernetes.operator.builders.StubWatchFactory; import oracle.kubernetes.operator.helpers.DomainPresenceInfo; import oracle.kubernetes.operator.helpers.DomainPresenceInfo.ServerStartupInfo; import oracle.kubernetes.operator.helpers.KubernetesTestSupport; import oracle.kubernetes.operator.helpers.LegalNames; import oracle.kubernetes.operator.helpers.TuningParametersStub; import oracle.kubernetes.operator.utils.WlsDomainConfigSupport; +import oracle.kubernetes.operator.watcher.WatchListener; import oracle.kubernetes.operator.wlsconfig.WlsClusterConfig; import oracle.kubernetes.operator.wlsconfig.WlsDomainConfig; import oracle.kubernetes.operator.wlsconfig.WlsServerConfig; @@ -48,6 +57,7 @@ import static oracle.kubernetes.operator.LabelConstants.CLUSTERNAME_LABEL; import static oracle.kubernetes.operator.LabelConstants.SERVERNAME_LABEL; +import static oracle.kubernetes.operator.helpers.KubernetesTestSupport.POD; import static oracle.kubernetes.operator.steps.ManagedServerUpIteratorStep.SCHEDULING_DETECTION_DELAY; import static org.hamcrest.CoreMatchers.equalTo; import static org.hamcrest.CoreMatchers.notNullValue; @@ -55,7 +65,8 @@ import static org.hamcrest.Matchers.hasSize; import static org.hamcrest.junit.MatcherAssert.assertThat; -public class ManagedServerUpIteratorStepTest { +public class ManagedServerUpIteratorStepTest extends ThreadFactoryTestBase implements WatchListener, + StubWatchFactory.AllWatchesClosedListener { protected static final String DOMAIN_NAME = "domain1"; private static final String NS = "namespace"; @@ -81,6 +92,10 @@ public class ManagedServerUpIteratorStepTest { private static final String[] MANAGED_SERVER_NAMES = IntStream.rangeClosed(1, MAX_SERVERS) .mapToObj(ManagedServerUpIteratorStepTest::getManagedServerName).toArray(String[]::new); + private final AtomicBoolean stopping = new AtomicBoolean(false); + private static final BigInteger INITIAL_RESOURCE_VERSION = new BigInteger("234"); + private final PodWatcher watcher = createWatcher(NS, stopping, INITIAL_RESOURCE_VERSION); + final TuningParameters.WatchTuning tuning = new TuningParameters.WatchTuning(30, 0, 5); @Nonnull private static String getManagedServerName(int n) { @@ -158,32 +173,39 @@ private static V1ObjectMeta withNames(V1ObjectMeta objectMeta, String serverName @Before public void setUp() throws NoSuchFieldException { - mementos.add(TestUtils.silenceOperatorLogger().ignoringLoggedExceptions(ApiException.class)); + mementos.add(TestUtils.silenceOperatorLogger() + .ignoringLoggedExceptions(ApiException.class, InterruptedException.class)); mementos.add(TuningParametersStub.install()); mementos.add(testSupport.install()); + mementos.add(StubWatchFactory.install()); + StubWatchFactory.setListener(this); testSupport.defineResources(domain); testSupport .addToPacket(ProcessingConstants.DOMAIN_TOPOLOGY, domainConfig) .addDomainPresenceInfo(domainPresenceInfo); - testSupport.doOnCreate(KubernetesTestSupport.POD, p -> schedulePodUpdates((V1Pod) p)); + testSupport.doOnCreate(POD, p -> schedulePodUpdates((V1Pod) p)); + testSupport.addComponent( + ProcessingConstants.PODWATCHER_COMPONENT_NAME, + PodAwaiterStepFactory.class, + watcher); } // Invoked when a pod is created to simulate the Kubernetes behavior in which a pod is scheduled on a node // very quickly, and then takes much longer actually to become ready. void schedulePodUpdates(V1Pod pod) { - testSupport.schedule(() -> setPodScheduled(getServerName(pod)), SCHEDULING_DELAY_MSEC, TimeUnit.MILLISECONDS); - testSupport.schedule(() -> setPodReady(getServerName(pod)), POD_READY_DELAY_SEC, TimeUnit.SECONDS); + testSupport.schedule(() -> setPodScheduled(pod), SCHEDULING_DELAY_MSEC, TimeUnit.MILLISECONDS); + testSupport.schedule(() -> setPodReady(pod), POD_READY_DELAY_SEC, TimeUnit.SECONDS); } - // Marks the pod with the specified server name as having been scheduled on a Kubernetes node. - private void setPodScheduled(String serverName) { - Objects.requireNonNull(domainPresenceInfo.getServerPod(serverName).getSpec()).setNodeName("aNode"); + // Marks the specified pod as having been scheduled on a Kubernetes node. + private void setPodScheduled(V1Pod pod) { + Objects.requireNonNull(pod.getSpec()).setNodeName("aNode"); } - // Marks the pod with the specified server name as having become ready. - private void setPodReady(String serverName) { - domainPresenceInfo.getServerPod(serverName).status(createPodReadyStatus()); + // Marks the specified pod as having become ready. + private void setPodReady(V1Pod pod) { + pod.status(createPodReadyStatus()); } private V1PodStatus createPodReadyStatus() { @@ -194,11 +216,16 @@ private V1PodStatus createPodReadyStatus() { @After public void tearDown() throws Exception { + shutDownThreads(); mementos.forEach(Memento::revert); testSupport.throwOnCompletionFailure(); } + protected PodWatcher createWatcher(String ns, AtomicBoolean stopping, BigInteger rv) { + return PodWatcher.create(this, ns, rv.toString(), tuning, this, stopping); + } + @Test public void withMultipleServersAvailableToStart_onlyOneForEachClusterInitiallyStarts() { configureCluster(CLUSTER1).withMaxConcurrentStartup(0); @@ -358,4 +385,13 @@ private void addWlsCluster(String clusterName, String... serverNames) { ); } + + @Override + public void receivedResponse(Watch.Response response) { + } + + @Override + public void allWatchesClosed() { + stopping.set(true); + } } \ No newline at end of file diff --git a/operator/src/test/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfigTest.java b/operator/src/test/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfigTest.java index a2d773bfd37..0ed88ac0599 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfigTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/wlsconfig/WlsDomainConfigTest.java @@ -1,4 +1,4 @@ -// Copyright (c) 2017, 2020, Oracle Corporation and/or its affiliates. +// Copyright (c) 2017, 2021, Oracle Corporation and/or its affiliates. // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. package oracle.kubernetes.operator.wlsconfig; @@ -13,10 +13,6 @@ import com.meterware.simplestub.Memento; import oracle.kubernetes.operator.utils.WlsDomainConfigSupport; import oracle.kubernetes.utils.TestUtils; -import oracle.kubernetes.weblogic.domain.DomainConfigurator; -import oracle.kubernetes.weblogic.domain.DomainConfiguratorFactory; -import oracle.kubernetes.weblogic.domain.model.Domain; -import oracle.kubernetes.weblogic.domain.model.DomainSpec; import org.hamcrest.Description; import org.junit.After; import org.junit.Before; @@ -346,11 +342,10 @@ public class WlsDomainConfigTest { + " \"networkAccessPoints\": {\"items\": []}\n" + " }\n" + "]}}"; - private Domain domain = new Domain().withSpec(new DomainSpec()); - private DomainConfigurator configurator = DomainConfiguratorFactory.forDomain(domain); - private WlsDomainConfig wlsDomainConfig = new WlsDomainConfig(null); private List logRecords = new ArrayList<>(); private List mementos = new ArrayList<>(); + private WlsDomainConfig wlsDomainConfig = new WlsDomainConfig("test-domain"); + private WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); /** * Setup test. @@ -602,7 +597,6 @@ public void verifyGetMachineConfigsReturnNullIfNotFound() { @Test public void whenNoClustersDefined_returnEmptyArray() { - WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); support.addWlsServer("server1"); support.addWlsServer("server2"); @@ -611,7 +605,6 @@ public void whenNoClustersDefined_returnEmptyArray() { @Test public void whenOneClusterDefined_returnItsName() { - WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); support.addWlsCluster("cluster1", "ms1", "ms2", "ms3"); support.addWlsServer("server2"); @@ -620,7 +613,6 @@ public void whenOneClusterDefined_returnItsName() { @Test public void whenTwoClustersDefined_returnBothNames() { - WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); support.addWlsCluster("cluster1", "ms1", "ms2", "ms3"); support.addWlsCluster("cluster2", "ms4", "ms5"); @@ -631,7 +623,6 @@ public void whenTwoClustersDefined_returnBothNames() { @Test public void whenTwoClustersDefined_returnReplicaLimits() { - WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); support.addWlsCluster("cluster1", "ms1", "ms2", "ms3"); support.addWlsCluster("cluster2", "ms4", "ms5"); @@ -641,8 +632,6 @@ public void whenTwoClustersDefined_returnReplicaLimits() { @Test public void whenUnknownClusterName_returnZeroReplicaLimit() { - WlsDomainConfigSupport support = new WlsDomainConfigSupport("test-domain"); - assertThat(support.createDomainConfig().getReplicaLimit("cluster3"), equalTo(0)); } @@ -668,66 +657,111 @@ private boolean containsNetworkAccessPoint(WlsServerConfig wlsServerConfig, Stri @Test public void whenTopologyGenerated_containsDomainValidFlag() { - WlsDomainConfig domainConfig = new WlsDomainConfig(); - - assertThat(domainConfig.toTopology(), hasJsonPath("domainValid", equalTo("true"))); + assertThat(wlsDomainConfig.toTopology(), hasJsonPath("domainValid", equalTo("true"))); } @Test public void whenTopologyGenerated_containsDomainName() { - WlsDomainConfig domainConfig = new WlsDomainConfig("test-domain"); - - assertThat(domainConfig.toTopology(), hasJsonPath("domain.name", equalTo("test-domain"))); + assertThat(wlsDomainConfig.toTopology(), hasJsonPath("domain.name", equalTo("test-domain"))); } @Test public void whenTopologyGenerated_containsAdminServerName() { - WlsDomainConfig domainConfig = - new WlsDomainConfig("test-domain").withAdminServer("admin-server", "admin-host", 7001); + wlsDomainConfig.withAdminServer("admin-server", "admin-host", 7001); assertThat( - domainConfig.toTopology(), hasJsonPath("domain.adminServerName", equalTo("admin-server"))); + wlsDomainConfig.toTopology(), hasJsonPath("domain.adminServerName", equalTo("admin-server"))); } @Test public void whenTopologyGenerated_containsAdminServerSpec() { - WlsDomainConfig domainConfig = - new WlsDomainConfig("test-domain").withAdminServer("admin-server", "admin-host", 7001); + wlsDomainConfig.withAdminServer("admin-server", "admin-host", 7001); assertThat( - domainConfig.toTopology(), + wlsDomainConfig.toTopology(), hasJsonPath("domain.servers", withServerConfig("admin-server", "admin-host", 7001))); } @Test public void whenYamlGenerated_containsClusterConfig() { - WlsDomainConfig domainConfig = - new WlsDomainConfig("test-domain").withCluster(new WlsClusterConfig("cluster1")); + wlsDomainConfig.withCluster(new WlsClusterConfig("cluster1")); assertThat( - domainConfig.toTopology(), + wlsDomainConfig.toTopology(), hasJsonPath("domain.configuredClusters[*].name", contains("cluster1"))); } @Test public void whenYamlGenerated_containsClusteredServerConfigs() { - WlsDomainConfig domainConfig = - new WlsDomainConfig("test-domain") - .withCluster( + wlsDomainConfig.withCluster( new WlsClusterConfig("cluster1") .addServerConfig(new WlsServerConfig("ms1", "host1", 8001)) .addServerConfig(new WlsServerConfig("ms2", "host2", 8001))); assertThat( - domainConfig.toTopology(), + wlsDomainConfig.toTopology(), hasJsonPath( "domain.configuredClusters[0].servers", withServerConfig("ms1", "host1", 8001))); assertThat( - domainConfig.toTopology(), + wlsDomainConfig.toTopology(), hasJsonPath( "domain.configuredClusters[0].servers", withServerConfig("ms2", "host2", 8001))); } + @Test + public void containsServer_returnsTrue_forExistingStandaloneServer() { + wlsDomainConfig.addWlsServer("ms1","host1", 8001); + + assertThat(wlsDomainConfig.containsServer("ms1"), equalTo(true)); + } + + @Test + public void containsServer_returnsTrue_forExistingConfiguredClusteredServer() { + support.addWlsCluster("cluster-1", "ms1"); + + assertThat(support.createDomainConfig().containsServer("ms1"), equalTo(true)); + } + + @Test + public void containsServer_returnsTrue_forExistingDynamicClusterServer() { + support.addDynamicWlsCluster("cluster-1", "ms1"); + + assertThat(support.createDomainConfig().containsServer("ms1"), equalTo(true)); + } + + @Test + public void containsServer_returnsFalse_forNonExistingServer() { + support.addWlsCluster("cluster-1", "ms1"); + support.addDynamicWlsCluster("dynamic-cluster", "dyn1"); + support.addWlsServer("standalone"); + + assertThat(support.createDomainConfig().containsServer("notthere"), equalTo(false)); + } + + @Test + public void containsServer_returnsFalse_forNullServerName() { + assertThat(wlsDomainConfig.containsServer(null), equalTo(false)); + } + + @Test + public void containsCluster_returnsFalse_forNonExistingCluster() { + support.addWlsCluster("cluster-1", "ms1"); + + assertThat(support.createDomainConfig().containsCluster("notthere"), equalTo(false)); + } + + @Test + public void containsCluster_returnsTrue_forExistingCluster() { + support.addWlsCluster("cluster-1", "ms1"); + + assertThat(support.createDomainConfig().containsCluster("cluster-1"), equalTo(true)); + } + + @Test + public void containsCluster_returnsFalse_forNullServerName() { + assertThat(wlsDomainConfig.containsCluster(null), equalTo(false)); + } + @SuppressWarnings("unused") static class WlsServerConfigMatcher extends org.hamcrest.TypeSafeDiagnosingMatcher< diff --git a/pom.xml b/pom.xml index 5d28a916655..b32cb503c2f 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,4 @@ - oracle.kubernetes operator-parent - 3.1.3 + 3.1.4 operator @@ -271,7 +271,7 @@ false true - Copyright (c) 2018, {currentYear}, Oracle Corporation and/or its affiliates.
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

]]> + Copyright (c) 2018, {currentYear}, Oracle and/or its affiliates.
Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.

]]> Oracle WebLogic Server Kubernetes Operator API @@ -634,6 +634,21 @@ awaitility ${awaitility-version} + + org.bouncycastle + bcprov-ext-jdk15on + ${bouncycastle.version} + + + org.bouncycastle + bcpkix-jdk15on + ${bouncycastle.version} + + + com.google.guava + guava + ${guava.version} + @@ -672,8 +687,8 @@ 3.1.2 3.0.0 4.1.4 - 4.1.4 - 8.36.2 + 4.2.0 + 8.38 6.21.0 0.1 3.0.0 @@ -697,7 +712,7 @@ 3.17.2 2.6 4.0.3 - 10.0.0 + 10.0.1 5.7.0 5.7.0 1.7.0 @@ -710,7 +725,10 @@ ${root-generated-swagger}/main/java ${project.basedir}/swagger/domain.json false - 0.8.5 + 0.8.6 + 4.0.0 + 1.68 + 30.1-jre buildtime-reports/target/site/jacoco-aggregate/jacoco.xml ${root.basedir}/build-tools/checkstyle/customized_google_checks.xml diff --git a/swagger/pom.xml b/swagger/pom.xml index 209c34d5012..fbc88348144 100644 --- a/swagger/pom.xml +++ b/swagger/pom.xml @@ -7,7 +7,7 @@ oracle.kubernetes operator-parent - 3.1.3 + 3.1.4 operator-swagger