Skip to content

Commit 8382dda

Browse files
ankediarjeberhard
authored andcommitted
OWLS-109755 - Changes for Operator Dedicated Mode to suppress readCRD call failed message and clarify webhook configuration.
1 parent 7d93fee commit 8382dda

File tree

9 files changed

+104
-6
lines changed

9 files changed

+104
-6
lines changed

common/src/main/java/oracle/kubernetes/common/CommonConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55

66
public class CommonConstants {
77

8+
public static final String CRD = "CRD";
9+
810
private CommonConstants() {
911
//not called
1012
}

documentation/site/content/managing-operators/conversion-webhook.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,10 @@ Beginning with operator version 4.0, when you [install the operator]({{<relref
4646
The `helm install` step requires cluster-level permissions for listing and reading all Namespaces and Deployments to search for existing conversion webhook deployments. If you cannot grant the cluster-level permissions and have multiple operators deployed, then install the conversion webhook separately and set the Helm configuration value `operatorOnly` to `true` in the `helm install` command to prevent multiple conversion webhook deployments. In addition, the webhook uses a service account that is usually the same service account as an operator running in the same namespace. This service account requires permissions to create and read events in the conversion webhook namespace. For more information, see [RBAC]({{<relref "/managing-operators/rbac.md" >}}).
4747
{{% /notice %}}
4848

49+
{{% notice note %}}
50+
The Operator version 4.x requires a conversion webhook installation. The `operatorOnly` Helm configuration value is an advanced setting and should be used only when a conversion webhook is already installed.
51+
{{% /notice %}}
52+
4953

5054
If you want to install _only_ the conversion webhook (and not the operator) in the given namespace, set the Helm configuration value `webhookOnly` to `true` in the `helm install` command. After meeting the [prerequisite requirements]({{<relref "/managing-operators/preparation.md">}}), call:
5155
```

documentation/site/content/managing-operators/installation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ See [Prepare for installation]({{<relref "/managing-operators/preparation.md">}}
2424
{{% notice note %}}
2525
By default, installing the operator also configures a deployment and supporting resources for the
2626
[conversion webhook]({{<relref "/managing-operators/conversion-webhook">}})
27-
and deploys the conversion webhook.
28-
To skip the conversion webhook installation, set helm configuration value `operatorOnly` to `true`
27+
and deploys the conversion webhook. The conversion webhook deployment is required for Operator version 4.x.
28+
To skip the conversion webhook installation when a conversion webhook is already installed, set the helm configuration value `operatorOnly` to `true`
2929
in the `helm install` command.
3030
For more details, see [install the conversion webhook]({{<relref "/managing-operators/conversion-webhook#install-the-conversion-webhook">}}).
3131
{{% /notice %}}

documentation/site/content/managing-operators/troubleshooting.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,38 @@ weblogic-operator-webhook-svc ClusterIP 10.106.89.198 <none> 8084/T
324324
```
325325
If the conversion webhook Deployment status is not ready, then [check the conversion webhook log]({{<relref "/managing-operators/troubleshooting#check-the-conversion-webhook-log">}}) and the [conversion webhook events]({{<relref "/managing-operators/troubleshooting#check-for-conversion-webhook-events">}}) in the conversion webhook namespace. If the conversion webhook service doesn't exist, make sure that the conversion webhook was installed correctly and reinstall the conversion webhook to see if it resolves the issue.
326326
327+
#### X509: Certificate signed by unknown authority error from the webhook
328+
The following `x509: certificate signed by unknown authority` error from the conversion webhook can be due to the incorrect proxy configuration of the Kubernetes API server in your environment or incorrect self-signed certificate in the conversion webhook configuration in the Domain CustomResourceDefinition (CRD).
329+
330+
```
331+
Error from server (InternalError): error when creating "./weblogic-domains/sample-domain1/domain.yaml": Internal error occurred: conversion webhook for weblogic.oracle/v8, Kind=Domain failed: Post "https://weblogic-operator-webhook-svc.sample-weblogic-operator-ns.svc:8084/webhook?timeout=30s": x509: certificate signed by unknown authority
332+
```
333+
- If your environment uses a PROXY server, then ensure that the NO_PROXY settings of the Kubernetes API server include `.svc` value. The Kubernetes API server makes a REST request to the conversion webhook REST end-point using the hostname `weblogic-operator-webhook-svc.${NAMESPACE}.svc` in the POST URL. If the REST request is routed through a PROXY server, then you will see an "x509: certificate signed by unknown authority" error. As this REST request is internal to your Kubernetes cluster, ensure that it doesn't get routed through a PROXY server by adding `.svc` to the `NO_PROXY` settings.
334+
- If your CRD conversion webhook configuration has an incorrect self-signed certificate for some reason, then you can patch the CRD to remove the existing conversion webhook configuration. The operator will re-create the CRD conversion webhook configuration using the correct self-signed certificate. Use the below patch command to remove the conversion webhook configuration in the CRD to see if it resolves the error.
335+
336+
```
337+
kubectl patch crd domains.weblogic.oracle --type=merge --patch '{"spec": {"conversion": {"strategy": "None", "webhook": null}}}'
338+
```
339+
340+
#### Webhook errors in older operator versions
341+
When you install Operator version 4.x or upgrade to Operator 4.x, a conversion webhook configuration is added to your Domain CRD. If you downgrade or switch back to the operator version 3.x, the conversion webhook configuration is not removed from the CRD. This is to support the environments with multiple Operator installations potentially with different versions. For environments having a single Operator installation, use the below patch command to manually remove the conversion webhook configuration from Domain CRD.
342+
343+
```
344+
kubectl patch crd domains.weblogic.oracle --type=merge --patch '{"spec": {"conversion": {"strategy": "None", "webhook": null}}}'
345+
```
346+
347+
#### Webhook errors in operator Dedicated Mode
348+
If the Operator is running in the `Dedicated` mode, the operator's service account will not have the permission to read or update the CRD. If you need to convert the domain resources with `weblogic.oracle/v8` schema to `weblogic.oracle/v9` schema using conversion webhook in `Dedicated` mode, then you can manually add the conversion webhook configuration to the Domain CRD. Use the below patch command to add the conversion webhook configuration to the Domain CRD.
349+
350+
**Note**: Substitute `YOUR_OPERATOR_NS` in the below command with the namespace where the operator is installed.
351+
352+
```
353+
export OPERATOR_NS=YOUR_OPERATOR_NS
354+
```
355+
```
356+
kubectl patch crd domains.weblogic.oracle --type=merge --patch '{"spec": {"conversion": {"strategy": "Webhook", "webhook": {"clientConfig": { "caBundle": "'$(kubectl get secret weblogic-webhook-secrets -n ${OPERATOR_NS} -o=jsonpath="{.data.webhookCert}"| base64 --decode)'", "service": {"name": "weblogic-operator-webhook-svc", "namespace": "'${OPERATOR_NS}'", "path": "/webhook", "port": 8084}}, "conversionReviewVersions": ["v1"]}}}}'
357+
```
358+
327359
#### Check for runtime errors during conversion
328360
If you see a `WebLogic Domain custom resource conversion webhook failed` error when creating a Domain with a `weblogic.oracle/v8` schema domain resource, then [check the conversion webhook runtime Pod logs]({{<relref "/managing-operators/troubleshooting#check-the-conversion-webhook-log">}}) and [check for the generated events]({{<relref "/managing-operators/troubleshooting#check-for-conversion-webhook-events">}}) in the conversion webhook namespace. Assuming that the conversion webhook is deployed in the `sample-weblogic-operator-ns` namespace, run the following commands to check for logs and events.
329361

documentation/site/content/managing-operators/using-helm.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,8 @@ If set to `true`, the `helm install` will install _only_ the conversion webhook
265265
Defaults to `false`.
266266

267267
##### `operatorOnly`
268+
**Note**: This is an advanced setting and should be used only in environments where a conversion webhook is already installed. The operator version 4.x requires a conversion webhook to be installed.
269+
268270
Specifies whether only the operator should be installed during the `helm install` and that the conversion webhook installation should be skipped. By default, the `helm install` command installs both the operator and the conversion webhook.
269271
If set to `true`, the `helm install` will install _only_ the operator (and not the conversion webhook).
270272

kubernetes/charts/weblogic-operator/templates/_operator-dep.tpl

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ spec:
224224
namespace: {{ .Release.Namespace | quote }}
225225
data:
226226
serviceaccount: {{ .serviceAccount | quote }}
227+
{{- if .featureGates }}
228+
featureGates: {{ .featureGates | quote }}
229+
{{- end }}
230+
{{- if .domainNamespaceSelectionStrategy }}
231+
domainNamespaceSelectionStrategy: {{ .domainNamespaceSelectionStrategy | quote }}
232+
{{- end }}
227233
---
228234
# webhook does not exist or chart version is newer, create a new webhook
229235
apiVersion: "apps/v1"

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
public class Namespaces {
4848
private static final LoggingFacade LOGGER = LoggingFactory.getLogger("Operator", "Operator");
4949

50-
static final String SELECTION_STRATEGY_KEY = "domainNamespaceSelectionStrategy";
50+
public static final String SELECTION_STRATEGY_KEY = "domainNamespaceSelectionStrategy";
5151
/**
5252
* The key in a Packet of the collection of existing namespaces that are designated as domain namespaces.
5353
*/

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

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import io.kubernetes.client.common.KubernetesObject;
1313
import io.kubernetes.client.openapi.ApiException;
1414
import oracle.kubernetes.common.logging.MessageKeys;
15+
import oracle.kubernetes.operator.OperatorMain;
1516
import oracle.kubernetes.operator.builders.CallParams;
1617
import oracle.kubernetes.operator.calls.AsyncRequestStep;
1718
import oracle.kubernetes.operator.calls.CallResponse;
@@ -26,6 +27,7 @@
2627
import oracle.kubernetes.weblogic.domain.model.DomainCondition;
2728
import oracle.kubernetes.weblogic.domain.model.DomainResource;
2829

30+
import static oracle.kubernetes.common.CommonConstants.CRD;
2931
import static oracle.kubernetes.operator.KubernetesConstants.HTTP_CONFLICT;
3032
import static oracle.kubernetes.operator.KubernetesConstants.HTTP_FORBIDDEN;
3133
import static oracle.kubernetes.operator.KubernetesConstants.HTTP_NOT_FOUND;
@@ -178,9 +180,7 @@ private NextAction doPotentialRetry(Step conflictStep, Packet packet, CallRespon
178180
}
179181

180182
private NextAction logNoRetry(Packet packet, CallResponse<T> callResponse) {
181-
if ((callResponse != null)
182-
&& (callResponse.getStatusCode() != HTTP_NOT_FOUND)
183-
&& (callResponse.getStatusCode() != HTTP_CONFLICT)) {
183+
if (shouldLogNoRetryWarning(callResponse)) {
184184
addDomainFailureStatus(packet, callResponse.getRequestParams(), callResponse.getE());
185185
if (LOGGER.isWarningEnabled()) {
186186
LOGGER.warning(
@@ -206,6 +206,25 @@ private NextAction logNoRetry(Packet packet, CallResponse<T> callResponse) {
206206
return null;
207207
}
208208

209+
private boolean shouldLogNoRetryWarning(CallResponse<T> callResponse) {
210+
return (callResponse != null)
211+
&& (callResponse.getStatusCode() != HTTP_NOT_FOUND)
212+
&& (callResponse.getStatusCode() != HTTP_CONFLICT)
213+
&& (isNotCrdForbiddenWhenDedicated(callResponse));
214+
}
215+
216+
private boolean isNotCrdForbiddenWhenDedicated(CallResponse<T> callResponse) {
217+
if (OperatorMain.isDedicated() && isCRDCall(callResponse)) {
218+
return callResponse.getStatusCode() != HTTP_FORBIDDEN && callResponse.getStatusCode() != HTTP_UNAUTHORIZED;
219+
}
220+
return true;
221+
}
222+
223+
private boolean isCRDCall(CallResponse<T> callResponse) {
224+
return Optional.ofNullable(callResponse.getRequestParams()).map(r -> r.call)
225+
.map(c -> c.toUpperCase().contains(CRD)).orElse(false);
226+
}
227+
209228
private void addDomainFailureStatus(Packet packet, RequestParams requestParams, ApiException apiException) {
210229
DomainPresenceInfo.fromPacket(packet)
211230
.map(DomainPresenceInfo::getDomain)

operator/src/test/java/oracle/kubernetes/operator/helpers/CrdHelperTest.java

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import io.kubernetes.client.openapi.models.V1ObjectMeta;
2222
import oracle.kubernetes.operator.KubernetesConstants;
2323
import oracle.kubernetes.operator.LabelConstants;
24+
import oracle.kubernetes.operator.Namespaces;
2425
import oracle.kubernetes.operator.logging.LoggingFactory;
2526
import oracle.kubernetes.operator.tuning.TuningParametersStub;
2627
import oracle.kubernetes.operator.utils.Certificates;
@@ -37,6 +38,7 @@
3738
import org.junit.jupiter.params.provider.EnumSource;
3839

3940
import static com.meterware.simplestub.Stub.createStrictStub;
41+
import static java.net.HttpURLConnection.HTTP_FORBIDDEN;
4042
import static java.net.HttpURLConnection.HTTP_UNAUTHORIZED;
4143
import static oracle.kubernetes.common.logging.MessageKeys.ASYNC_NO_RETRY;
4244
import static oracle.kubernetes.common.logging.MessageKeys.CREATE_CRD_FAILED;
@@ -233,6 +235,37 @@ void whenNotAuthorizedToReadCrd_retryOnFailureAndLogWarningMessageInOnFailureNoR
233235
assertThat(logRecords, containsWarning(ASYNC_NO_RETRY));
234236
}
235237

238+
@ParameterizedTest
239+
@EnumSource(value = TestSubject.class)
240+
void whenNotAuthorizedToReadCrdDedicatedMode_dontLogWarningMessageInOnFailureNoRetry(TestSubject testSubject) {
241+
consoleHandlerMemento.collectLogMessages(logRecords, ASYNC_NO_RETRY);
242+
defineSelectionStrategy(Namespaces.SelectionStrategy.DEDICATED);
243+
testSupport.addRetryStrategy(retryStrategy);
244+
testSupport.failOnResource(CUSTOM_RESOURCE_DEFINITION, null, null, HTTP_UNAUTHORIZED);
245+
246+
Step scriptCrdStep = testSubject.createCrdStep(PRODUCT_VERSION);
247+
testSupport.runSteps(scriptCrdStep);
248+
assertThat(logRecords, not(containsWarning(ASYNC_NO_RETRY)));
249+
}
250+
251+
private void defineSelectionStrategy(Namespaces.SelectionStrategy selectionStrategy) {
252+
TuningParametersStub.setParameter(Namespaces.SELECTION_STRATEGY_KEY, selectionStrategy.toString());
253+
}
254+
255+
@ParameterizedTest
256+
@EnumSource(value = TestSubject.class)
257+
void whenForbiddenToReadCrdDedicatedMode_dontLogWarningMessageInOnFailureNoRetry(TestSubject testSubject) {
258+
consoleHandlerMemento.collectLogMessages(logRecords, ASYNC_NO_RETRY);
259+
defineSelectionStrategy(Namespaces.SelectionStrategy.DEDICATED);
260+
testSupport.addRetryStrategy(retryStrategy);
261+
testSupport.failOnResource(CUSTOM_RESOURCE_DEFINITION, null, null, HTTP_FORBIDDEN);
262+
263+
Step scriptCrdStep = testSubject.createCrdStep(PRODUCT_VERSION);
264+
testSupport.runSteps(scriptCrdStep);
265+
assertThat(logRecords, not(containsWarning(ASYNC_NO_RETRY)));
266+
}
267+
268+
236269
@ParameterizedTest
237270
@EnumSource(value = TestSubject.class)
238271
void whenNotAuthorizedToReadCrdAndWarningNotEnabled_DontLogWarningInOnFailureNoRetry(TestSubject testSubject) {

0 commit comments

Comments
 (0)