diff --git a/docs-source/content/userguide/managing-domains/domain-lifecycle/introspection.md b/docs-source/content/userguide/managing-domains/domain-lifecycle/introspection.md index 9981d45ea7d..46d1af838ab 100644 --- a/docs-source/content/userguide/managing-domains/domain-lifecycle/introspection.md +++ b/docs-source/content/userguide/managing-domains/domain-lifecycle/introspection.md @@ -44,6 +44,21 @@ Set `introspectVersion` to a new value. As with `restartVersion`, the `introspectVersion` field has no required format; however, we recommend using a value likely to be unique such as a continually increasing number or a timestamp. +Beginning with operator 3.1.0, if a domain resource's `spec.introspectVersion` is set, each of the domain's WebLogic Server pods will have a label with the key `weblogic.introspectVersion` to indicate the `introspectVersion` at which the pod is running. + +``` +Name: domain1-admin-server +Namespace: domain1-ns +Labels: weblogic.createdByOperator=true + weblogic.domainName=domain1 + weblogic.domainRestartVersion=abcdef + weblogic.domainUID=domain1 + weblogic.introspectVersion=12345 + weblogic.serverName=admin-server +``` + +When a domain's `spec.introspectVersion` is changed, the `weblogic.introspectVersion` label of each WebLogic Server pod is updated to the new `introspectVersion` value, either when the operator restarts the pod or when the operator determines that the pod does not need to be restarted. + #### Failed introspection Sometimes the Kubernetes Job, named `DOMAIN_UID-introspector`, created for the introspection will fail. diff --git a/docs-source/content/userguide/managing-domains/domain-resource.md b/docs-source/content/userguide/managing-domains/domain-resource.md index 293c784aac8..f2b5b3c4867 100644 --- a/docs-source/content/userguide/managing-domains/domain-resource.md +++ b/docs-source/content/userguide/managing-domains/domain-resource.md @@ -161,14 +161,14 @@ Elements related to domain [startup and shutdown]({{< relref "/userguide/managin * `replicas`: The default number of cluster member Managed Server instances to start for each WebLogic cluster in the domain configuration, unless `replicas` is specified for that cluster under the `clusters` field. For each cluster, the operator will sort cluster member Managed Server names from the WebLogic domain configuration by normalizing any numbers in the Managed Server name and then sorting alphabetically. This is done so that server names such as "managed-server10" come after "managed-server9". The operator will then start Managed Servers from the sorted list, up to the `replicas` count, unless specific Managed Servers are specified as starting in their entry under the `managedServers` field. In that case, the specified Managed Servers will be started and then additional cluster members will be started, up to the `replicas` count, by finding further cluster members in the sorted list that are not already started. If cluster members are started because of their entries under `managedServers`, then a cluster may have more cluster members running than its `replicas` count. Defaults to 0. * `maxClusterConcurrentStartup`: The maximum number of cluster member Managed Server instances that the operator will start in parallel for a given cluster, if `maxConcurrentStartup` is not specified for a specific cluster under the `clusters` field. A value of 0 means there is no configured limit. Defaults to 0. * `allowReplicasBelowMinDynClusterSize`: Whether to allow the number of running cluster member Managed Server instances to drop below the minimum dynamic cluster size configured in the WebLogic domain configuration, if this is not specified for a specific cluster under the `clusters` field. Defaults to true. -* `introspectVersion`: Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields [listed here]({{< relref "/userguide/managing-domains/domain-lifecycle/startup#fields-that-cause-servers-to-be-restarted" >}}). See also `overridesConfigurationStrategy`. +* `introspectVersion`: Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration (see [Initiating introspection]({{< relref "/userguide/managing-domains/domain-lifecycle/introspection/_index.md#initiating-introspection" >}})). Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields [listed here]({{< relref "/userguide/managing-domains/domain-lifecycle/startup#fields-that-cause-servers-to-be-restarted" >}}). See also `overrideDistributionStrategy`. Elements related to specifying and overriding WebLogic domain configuration: * These elements are under `configuration`. * `overridesConfigMap`: The name of the ConfigMap for WebLogic [configuration overrides]({{< relref "/userguide/managing-domains/configoverrides/_index.md" >}}). If this field is specified, then the value of `spec.configOverrides` is ignored. - * `overrideDistributionStrategy`: Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overrideConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server's next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `introspectVersion`. Defaults to DYNAMIC. + * `overrideDistributionStrategy`: Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server's next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `introspectVersion`. Defaults to DYNAMIC. * `secrets`: A list of names of the Secrets for WebLogic [configuration overrides]({{< relref "/userguide/managing-domains/configoverrides/_index.md" >}}) or model. If this field is specified, then the value of `spec.configOverrideSecrets` is ignored. * `introspectorJobActiveDeadlineSeconds`: The introspector job timeout value in seconds. If this field is specified, then the operator's ConfigMap `data.introspectorJobActiveDeadlineSeconds` value is ignored. Defaults to 120 seconds. diff --git a/docs/domains/Domain.json b/docs/domains/Domain.json index 7b5ca4339b8..94b49c95e3b 100644 --- a/docs/domains/Domain.json +++ b/docs/domains/Domain.json @@ -182,7 +182,7 @@ "type": "object", "properties": { "overrideDistributionStrategy": { - "description": "Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overrideConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server\u0027s next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC.", + "description": "Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server\u0027s next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC.", "type": "string", "enum": [ "DYNAMIC", @@ -383,7 +383,7 @@ "type": "string" }, "introspectVersion": { - "description": "Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overridesConfigurationStrategy`.", + "description": "Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overrideDistributionStrategy`.", "type": "string" }, "dataHome": { diff --git a/docs/domains/Domain.md b/docs/domains/Domain.md index 796bd879f70..d6e703f0a82 100644 --- a/docs/domains/Domain.md +++ b/docs/domains/Domain.md @@ -30,7 +30,7 @@ The specification of the operation of the WebLogic domain. Required. | `imagePullPolicy` | string | The image pull policy for the WebLogic container image. Legal values are Always, Never, and IfNotPresent. Defaults to Always if image ends in :latest; IfNotPresent, otherwise. | | `imagePullSecrets` | array of [Local Object Reference](k8s1.13.5.md#local-object-reference) | A list of image pull Secrets for the WebLogic container image. | | `includeServerOutInPodLog` | Boolean | Specifies whether the server .out file will be included in the Pod's log. Defaults to true. | -| `introspectVersion` | string | Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overridesConfigurationStrategy`. | +| `introspectVersion` | string | Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overrideDistributionStrategy`. | | `logHome` | string | The directory in a server's container in which to store the domain, Node Manager, server logs, server *.out, introspector .out, and optionally HTTP access log files if `httpAccessLogInLogHome` is true. Ignored if `logHomeEnabled` is false. | | `logHomeEnabled` | Boolean | Specifies whether the log home folder is enabled. Defaults to true if `domainHomeSourceType` is PersistentVolume; false, otherwise. | | `managedServers` | array of [Managed Server](#managed-server) | Lifecycle options for individual Managed Servers, including Java options, environment variables, additional Pod content, and the ability to explicitly start, stop, or restart a named server instance. The `serverName` field of each entry must match a Managed Server that already exists in the WebLogic domain configuration or that matches a dynamic cluster member based on the server template. | @@ -95,7 +95,7 @@ The current status of the operation of the WebLogic domain. Updated automaticall | `istio` | [Istio](#istio) | The Istio service mesh integration settings. | | `model` | [Model](#model) | Model in image model files and properties. | | `opss` | [Opss](#opss) | Settings for OPSS security. | -| `overrideDistributionStrategy` | string | Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overrideConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server's next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC. | +| `overrideDistributionStrategy` | string | Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server's next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC. | | `overridesConfigMap` | string | The name of the ConfigMap for WebLogic configuration overrides. If this field is specified, then the value of `spec.configOverrides` is ignored. | | `secrets` | array of string | A list of names of the Secrets for WebLogic configuration overrides or model. If this field is specified, then the value of `spec.configOverrideSecrets` is ignored. | diff --git a/docs/domains/index.html b/docs/domains/index.html index 77d6c54fce3..f4f53269507 100644 --- a/docs/domains/index.html +++ b/docs/domains/index.html @@ -1103,7 +1103,7 @@ "type": "object", "properties": { "overrideDistributionStrategy": { - "description": "Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overrideConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server\u0027s next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC.", + "description": "Determines how updated configuration overrides are distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration overrides only after the server\u0027s next restart. The selection of ON_RESTART will not cause servers to restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. Defaults to DYNAMIC.", "type": "string", "enum": [ "DYNAMIC", @@ -1304,7 +1304,7 @@ "type": "string" }, "introspectVersion": { - "description": "Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overridesConfigurationStrategy`.", + "description": "Changes to this field cause the operator to repeat its introspection of the WebLogic domain configuration. Repeating introspection is required for the operator to recognize changes to the domain configuration, such as adding a new WebLogic cluster or Managed Server instance, to regenerate configuration overrides, or to regenerate the WebLogic domain home when the `domainHomeSourceType` is FromModel. Introspection occurs automatically, without requiring change to this field, when servers are first started or restarted after a full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. See also `domains.spec.configuration.overrideDistributionStrategy`.", "type": "string" }, "dataHome": { diff --git a/kubernetes/crd/domain-crd.yaml b/kubernetes/crd/domain-crd.yaml index ce500aeb9a2..b028f5fd264 100644 --- a/kubernetes/crd/domain-crd.yaml +++ b/kubernetes/crd/domain-crd.yaml @@ -36,7 +36,7 @@ spec: distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection - from Secrets, the `overrideConfigMap` field, and WebLogic domain + from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers @@ -5253,7 +5253,7 @@ spec: full domain shut down. For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. - See also `domains.spec.configuration.overridesConfigurationStrategy`.' + See also `domains.spec.configuration.overrideDistributionStrategy`.' dataHome: type: string description: An optional directory in a server's container for data diff --git a/kubernetes/crd/domain-v1beta1-crd.yaml b/kubernetes/crd/domain-v1beta1-crd.yaml index 42b5b007799..eef26db2252 100644 --- a/kubernetes/crd/domain-v1beta1-crd.yaml +++ b/kubernetes/crd/domain-v1beta1-crd.yaml @@ -39,7 +39,7 @@ spec: distributed to already running WebLogic Server instances following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides are generated during introspection - from Secrets, the `overrideConfigMap` field, and WebLogic domain + from Secrets, the `overridesConfigMap` field, and WebLogic domain topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides dynamically to running servers, and ON_RESTART, which means that servers will @@ -5238,7 +5238,7 @@ spec: For the FromModel `domainHomeSourceType`, introspection also occurs when a running server must be restarted because of changes to any of the fields listed here: https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. - See also `domains.spec.configuration.overridesConfigurationStrategy`.' + See also `domains.spec.configuration.overrideDistributionStrategy`.' dataHome: type: string description: An optional directory in a server's container for data diff --git a/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java b/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java index ee266e06c56..1ef309448e2 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java +++ b/operator/src/main/java/oracle/kubernetes/operator/DomainProcessorImpl.java @@ -884,7 +884,7 @@ Step createDomainUpPlan(DomainPresenceInfo info) { Step domainUpStrategy = Step.chain( domainIntrospectionSteps(info), - DomainValidationSteps.createAfterIntrospectValidationSteps(info.getDomainUid()), + DomainValidationSteps.createAfterIntrospectValidationSteps(), new DomainStatusStep(info, null), bringAdminServerUp(info, delegate.getPodAwaiterStepFactory(info.getNamespace())), managedServerStrategy); diff --git a/operator/src/main/java/oracle/kubernetes/operator/helpers/DomainValidationSteps.java b/operator/src/main/java/oracle/kubernetes/operator/helpers/DomainValidationSteps.java index f926514e52b..301294abdba 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/helpers/DomainValidationSteps.java +++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/DomainValidationSteps.java @@ -48,8 +48,8 @@ public static Step createAdditionalDomainValidationSteps(V1PodSpec podSpec) { return new DomainAdditionalValidationStep(podSpec); } - public static Step createAfterIntrospectValidationSteps(String domainUid) { - return new DomainAfterIntrospectValidationStep(domainUid); + public static Step createAfterIntrospectValidationSteps() { + return new DomainAfterIntrospectValidationStep(); } private static Step createListSecretsStep(String domainNamespace) { @@ -230,11 +230,6 @@ private boolean hasMatchingMetadata(V1ObjectMeta metadata, String name, String n } private static class DomainAfterIntrospectValidationStep extends Step { - private String domainUid; - - public DomainAfterIntrospectValidationStep(String domainUid) { - this.domainUid = domainUid; - } @Override public NextAction apply(Packet packet) { 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 bafcb49fcf6..144ed80ce37 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java +++ b/operator/src/main/java/oracle/kubernetes/operator/helpers/PodStepContext.java @@ -7,6 +7,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Objects; @@ -58,6 +59,8 @@ import oracle.kubernetes.weblogic.domain.model.Shutdown; import org.apache.commons.lang3.builder.EqualsBuilder; +import static oracle.kubernetes.operator.LabelConstants.INTROSPECTION_STATE_LABEL; + public abstract class PodStepContext extends BasePodStepContext { private static final LoggingFacade LOGGER = LoggingFactory.getLogger("Operator", "Operator"); @@ -86,6 +89,10 @@ public abstract class PodStepContext extends BasePodStepContext { scan = (WlsServerConfig) packet.get(ProcessingConstants.SERVER_SCAN); } + private static boolean isPatchableItem(Map.Entry entry) { + return isCustomerItem(entry) || entry.getKey().equals(INTROSPECTION_STATE_LABEL); + } + private static boolean isCustomerItem(Map.Entry entry) { return !entry.getKey().startsWith("weblogic."); } @@ -355,7 +362,7 @@ protected Step patchPod(V1Pod currentPod, Step next) { JsonPatchBuilder patchBuilder = Json.createPatchBuilder(); KubernetesUtils.addPatches( - patchBuilder, "/metadata/labels/", getLabels(currentPod), getPodLabels()); + patchBuilder, "/metadata/labels/", getLabels(currentPod), getNonHashedPodLabels()); KubernetesUtils.addPatches( patchBuilder, "/metadata/annotations/", getAnnotations(currentPod), getPodAnnotations()); @@ -364,6 +371,15 @@ protected Step patchPod(V1Pod currentPod, Step next) { new V1Patch(patchBuilder.build().toString()), patchResponse(next)); } + private Map getNonHashedPodLabels() { + Map result = new HashMap<>(getPodLabels()); + + Optional.ofNullable(getDomain().getSpec().getIntrospectVersion()) + .ifPresent(version -> result.put(INTROSPECTION_STATE_LABEL, version)); + + return result; + } + private Map getLabels(V1Pod pod) { return Optional.ofNullable(pod.getMetadata()).map(V1ObjectMeta::getLabels).orElseGet(Collections::emptyMap); } @@ -401,7 +417,7 @@ Step createCyclePodStep(Step next) { } private boolean mustPatchPod(V1Pod currentPod) { - return KubernetesUtils.isMissingValues(getLabels(currentPod), getPodLabels()) + return KubernetesUtils.isMissingValues(getLabels(currentPod), getNonHashedPodLabels()) || KubernetesUtils.isMissingValues(getAnnotations(currentPod), getPodAnnotations()); } @@ -455,11 +471,11 @@ protected Map augmentSubVars(Map vars) { V1Pod withNonHashedElements(V1Pod pod) { V1ObjectMeta metadata = Objects.requireNonNull(pod.getMetadata()); // Adds labels and annotations to a pod, skipping any whose names begin with "weblogic." - getPodLabels().entrySet().stream() - .filter(PodStepContext::isCustomerItem) + getNonHashedPodLabels().entrySet().stream() + .filter(PodStepContext::isPatchableItem) .forEach(e -> metadata.putLabelsItem(e.getKey(), e.getValue())); getPodAnnotations().entrySet().stream() - .filter(PodStepContext::isCustomerItem) + .filter(PodStepContext::isPatchableItem) .forEach(e -> metadata.putAnnotationsItem(e.getKey(), e.getValue())); setTerminationGracePeriod(pod); @@ -531,7 +547,7 @@ protected V1ObjectMeta createMetadata() { + getServerSpec().getDomainRestartVersion()); LOGGER.finest("PodStepContext.createMetaData domainIntrospectVersion from spec " + getDomain().getIntrospectVersion()); - + metadata .putLabelsItem(LabelConstants.DOMAINUID_LABEL, getDomainUid()) .putLabelsItem(LabelConstants.DOMAINNAME_LABEL, getDomainName()) @@ -829,7 +845,7 @@ public NextAction apply(Packet packet) { V1Pod currentPod = info.getServerPod(getServerName()); // reset introspect failure job count - if any - + Optional.ofNullable(packet.getSpi(DomainPresenceInfo.class)) .map(DomainPresenceInfo::getDomain) .map(Domain::getStatus) @@ -924,45 +940,48 @@ public NextAction onSuccess(Packet packet, CallResponse callResponses) { } } - private class ReplacePodResponseStep extends BaseResponseStep { + private class ReplacePodResponseStep extends PatchPodResponseStep { ReplacePodResponseStep(Step next) { super(next); } @Override - public NextAction onSuccess(Packet packet, CallResponse callResponse) { - - V1Pod newPod = callResponse.getResult(); + public void logPodChanged() { logPodReplaced(); - if (newPod != null) { - setRecordedPod(newPod); - } + } - PodAwaiterStepFactory pw = packet.getSpi(PodAwaiterStepFactory.class); - return doNext(pw.waitForReady(newPod, getNext()), packet); + @Override + public NextAction onSuccess(Packet packet, CallResponse callResponse) { + return doNext( + packet.getSpi(PodAwaiterStepFactory.class).waitForReady(processResponse(callResponse), getNext()), + packet); } } private class PatchPodResponseStep extends BaseResponseStep { - private final Step next; PatchPodResponseStep(Step next) { super(next); - this.next = next; + } + + public void logPodChanged() { + logPodPatched(); } @Override public NextAction onSuccess(Packet packet, CallResponse callResponse) { + processResponse(callResponse); + return doNext(getNext(), packet); + } + protected V1Pod processResponse(CallResponse callResponse) { V1Pod newPod = callResponse.getResult(); - logPodPatched(); + logPodChanged(); if (newPod != null) { setRecordedPod(newPod); } - - return doNext(next, packet); + return newPod; } } - } diff --git a/operator/src/main/java/oracle/kubernetes/operator/logging/MessageKeys.java b/operator/src/main/java/oracle/kubernetes/operator/logging/MessageKeys.java index ea197bb5270..26e81545b6e 100644 --- a/operator/src/main/java/oracle/kubernetes/operator/logging/MessageKeys.java +++ b/operator/src/main/java/oracle/kubernetes/operator/logging/MessageKeys.java @@ -133,7 +133,7 @@ public class MessageKeys { public static final String INTROSPECTOR_JOB_FAILED = "WLSKO-0175"; public static final String INTROSPECTOR_JOB_FAILED_DETAIL = "WLSKO-0176"; public static final String INTROSPECTOR_POD_FAILED = "WLSKO-0177"; - public static final String CRD_NOT_INSTALLED = "WLSKO-0180"; + public static final String CRD_NOT_INSTALLED = "WLSKO-0178"; // domain status messages public static final String DUPLICATE_SERVER_NAME_FOUND = "WLSDO-0001"; diff --git a/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/Configuration.java b/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/Configuration.java index 0b35002a2ce..2e6cd16b056 100644 --- a/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/Configuration.java +++ b/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/Configuration.java @@ -36,12 +36,12 @@ public class Configuration { @Description( "Determines how updated configuration overrides are distributed to already running WebLogic Server instances " + "following introspection when the `domainHomeSourceType` is PersistentVolume or Image. Configuration overrides " - + "are generated during introspection from Secrets, the `overrideConfigMap` field, and WebLogic domain topology. " - + "Legal values are DYNAMIC, which means that the operator will distribute updated configuration overrides " - + "dynamically to running servers, and ON_RESTART, which means that servers will use updated configuration " - + "overrides only after the server's next restart. The selection of ON_RESTART will not cause servers to " - + "restart when there are updated configuration overrides available. See also `domains.spec.introspectVersion`. " - + "Defaults to DYNAMIC.") + + "are generated during introspection from Secrets, the `overridesConfigMap` field, and WebLogic domain " + + "topology. Legal values are DYNAMIC, which means that the operator will distribute updated configuration " + + "overrides dynamically to running servers, and ON_RESTART, which means that servers will use updated " + + "configuration overrides only after the server's next restart. The selection of ON_RESTART will not cause " + + "servers to restart when there are updated configuration overrides available. See also " + + "`domains.spec.introspectVersion`. Defaults to DYNAMIC.") private OverrideDistributionStrategy overrideDistributionStrategy; @Description("The Istio service mesh integration settings.") diff --git a/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/DomainSpec.java b/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/DomainSpec.java index cc1e660ce44..a77dd860961 100644 --- a/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/DomainSpec.java +++ b/operator/src/main/java/oracle/kubernetes/weblogic/domain/model/DomainSpec.java @@ -256,7 +256,7 @@ public class DomainSpec extends BaseConfiguration { + "server must be restarted because of changes to any of the fields listed here: " + "https://oracle.github.io/weblogic-kubernetes-operator/userguide/managing-domains/" + "domain-lifecycle/startup/#properties-that-cause-servers-to-be-restarted. " - + "See also `domains.spec.configuration.overridesConfigurationStrategy`.") + + "See also `domains.spec.configuration.overrideDistributionStrategy`.") private String introspectVersion; @Description("Models and overrides affecting the WebLogic domain configuration.") diff --git a/operator/src/main/resources/Operator.properties b/operator/src/main/resources/Operator.properties index eeddcedc08d..4fe1edc2168 100644 --- a/operator/src/main/resources/Operator.properties +++ b/operator/src/main/resources/Operator.properties @@ -187,7 +187,7 @@ WLSKO-0175=Job {0} in namespace {1} failed with status {2}. Check log messages \ copied from the introspector pod {3} log for additional information. WLSKO-0176=Job {1} in namespace {0} failed, job details are {2} WLSKO-0177=Pod {0} in namespace {1} failed, the pod status is {2} -WLSKO-0180=Operator cannot start. 'Dedicated' namespace strategy selected, but the CRD is not installed +WLSKO-0178=Operator cannot start. Operator 'domainNamespaceSelectionStrategy' is set to 'Dedicated', but the Custom Resource Definition for ''domains.weblogic.oracle'' is not installed. # Domain status messages diff --git a/operator/src/test/java/oracle/kubernetes/operator/DomainProcessorTest.java b/operator/src/test/java/oracle/kubernetes/operator/DomainProcessorTest.java index 5a65aa542c9..99faa844899 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/DomainProcessorTest.java +++ b/operator/src/test/java/oracle/kubernetes/operator/DomainProcessorTest.java @@ -446,6 +446,88 @@ private Stream getConfigMaps() { return testSupport.getResources(CONFIG_MAP).stream(); } + @Test + public void afterInitialIntrospection_serverPodsHaveInitialIntrospectVersionLabel() throws Exception { + domainConfigurator.withIntrospectVersion(OLD_INTROSPECTION_STATE); + testSupport.doOnCreate(POD, p -> recordPodCreation((V1Pod) p)); + domainConfigurator.configureCluster(CLUSTER).withReplicas(MIN_REPLICAS); + DomainPresenceInfo info = new DomainPresenceInfo(newDomain); + processor.createMakeRightOperation(info).withExplicitRecheck().execute(); + + List runningPods = getRunningPods(); + //one introspector pod, one admin server pod and two managed server pods + assertThat(runningPods.size(), equalTo(4)); + for (V1Pod pod: runningPods) { + if (!pod.getMetadata().getName().contains(LegalNames.getIntrospectorJobNameSuffix())) { + assertThat(getServerPodIntrospectionVersion(pod), equalTo(OLD_INTROSPECTION_STATE)); + } + } + } + + @Test + public void afterIntrospection_serverPodsHaveUpToDateIntrospectVersionLabel() throws Exception { + establishPreviousIntrospection(null); + + domainConfigurator.withIntrospectVersion(NEW_INTROSPECTION_STATE); + DomainPresenceInfo info = new DomainPresenceInfo(newDomain); + processor.createMakeRightOperation(info).withExplicitRecheck().execute(); + + List runningPods = getRunningPods(); + //one introspector pod, one admin server pod and two managed server pods + assertThat(runningPods.size(), equalTo(4)); + for (V1Pod pod: runningPods) { + if (!pod.getMetadata().getName().contains(LegalNames.getIntrospectorJobNameSuffix())) { + assertThat(getServerPodIntrospectionVersion(pod), equalTo(NEW_INTROSPECTION_STATE)); + } + } + } + + @Test + public void afterScaleupClusterIntrospection_serverPodsHaveUpToDateIntrospectVersionLabel() throws Exception { + establishPreviousIntrospection(null); + + domainConfigurator.configureCluster(CLUSTER).withReplicas(3); + domainConfigurator.withIntrospectVersion("after-scaleup"); + DomainPresenceInfo info = new DomainPresenceInfo(newDomain); + processor.createMakeRightOperation(info).withExplicitRecheck().execute(); + + List runningPods = getRunningPods(); + //one introspector pod, one admin server pod and three managed server pods + assertThat(runningPods.size(), equalTo(5)); + for (V1Pod pod: runningPods) { + if (!pod.getMetadata().getName().contains(LegalNames.getIntrospectorJobNameSuffix())) { + assertThat(getServerPodIntrospectionVersion(pod), equalTo("after-scaleup")); + } + } + } + + @Test + public void afterScaledownClusterIntrospection_serverPodsHaveUpToDateIntrospectVersionLabel() throws Exception { + establishPreviousIntrospection(null); + + domainConfigurator.configureCluster(CLUSTER).withReplicas(1); + domainConfigurator.withIntrospectVersion("after-scaledown"); + DomainPresenceInfo info = new DomainPresenceInfo(newDomain); + processor.createMakeRightOperation(info).withExplicitRecheck().execute(); + + List runningPods = getRunningPods(); + //one introspector pod, one admin server pod and one managed server pod + assertThat(runningPods.size(), equalTo(3)); + for (V1Pod pod: runningPods) { + if (!pod.getMetadata().getName().contains(LegalNames.getIntrospectorJobNameSuffix())) { + assertThat(getServerPodIntrospectionVersion(pod), equalTo("after-scaledown")); + } + } + } + + private String getServerPodIntrospectionVersion(V1Pod pod) { + return Optional.ofNullable(pod) + .map(V1Pod::getMetadata) + .map(V1ObjectMeta::getLabels) + .map(m -> m.get(INTROSPECTION_STATE_LABEL)) + .orElse(null); + } + private boolean isIntrospectorMeta(@Nullable V1ObjectMeta meta) { return meta != null && NS.equals(meta.getNamespace()) && INTROSPECTOR_MAP_NAME.equals(meta.getName()); } diff --git a/operator/src/test/java/oracle/kubernetes/operator/helpers/PodHelperTestBase.java b/operator/src/test/java/oracle/kubernetes/operator/helpers/PodHelperTestBase.java index 171a9ec627a..a9c6dd7911d 100644 --- a/operator/src/test/java/oracle/kubernetes/operator/helpers/PodHelperTestBase.java +++ b/operator/src/test/java/oracle/kubernetes/operator/helpers/PodHelperTestBase.java @@ -547,9 +547,24 @@ public void whenPodCreationFailsDueToQuotaExceeded_abortFiber() { // todo set property to indicate dynamic/on_restart copying protected abstract void verifyPodReplaced(); + protected void verifyPodPatched() { + testSupport.runSteps(getStepFactory(), terminalStep); + + assertThat(logRecords, not(containsFine(getExistsMessageKey()))); + assertThat(logRecords, containsInfo(getPatchedMessageKey())); + } + + protected void verifyPodNotPatched() { + testSupport.runSteps(getStepFactory(), terminalStep); + + assertThat(logRecords, containsFine(getExistsMessageKey())); + assertThat(logRecords, not(containsInfo(getPatchedMessageKey()))); + } + protected void verifyPodNotReplaced() { testSupport.runSteps(getStepFactory(), terminalStep); + assertThat(logRecords, not(containsInfo(getReplacedMessageKey()))); assertThat(logRecords, containsFine(getExistsMessageKey())); } @@ -770,6 +785,16 @@ void initializeExistingPod(V1Pod pod) { domainPresenceInfo.setServerPod(getServerName(), pod); } + void initializeExistingPodWithIntrospectVersion(String introspectVersion) { + initializeExistingPodWithIntrospectVersion(createPodModel(), introspectVersion); + } + + void initializeExistingPodWithIntrospectVersion(V1Pod pod, String introspectVersion) { + testSupport.defineResources(pod); + pod.getMetadata().getLabels().put(LabelConstants.INTROSPECTION_STATE_LABEL, introspectVersion); + domainPresenceInfo.setServerPod(getServerName(), pod); + } + private V1Pod createPodModel() { return createPod(testSupport.getPacket()); } @@ -944,12 +969,21 @@ public void whenServerConfigurationAddsRestartVersion_replacePod() { } @Test - public void whenServerConfigurationAddsIntrospectionVersion_dontReplacePod() { + public void whenServerConfigurationAddsIntrospectionVersion_patchPod() { initializeExistingPod(); configurator.withIntrospectVersion("123"); - verifyPodNotReplaced(); + verifyPodPatched(); + } + + @Test + public void whenServerConfigurationIntrospectionVersionTheSame_dontPatchPod() { + initializeExistingPodWithIntrospectVersion("123"); + + configurator.withIntrospectVersion("123"); + + verifyPodNotPatched(); } @Test