Skip to content

Commit 22e5d74

Browse files
committed
Merge branch 'develop' into owls-69919-domain-resource-properties
2 parents 216b470 + ec58713 commit 22e5d74

39 files changed

+1098
-1420
lines changed

integration-tests/src/test/java/oracle/kubernetes/operator/utils/Operator.java

Lines changed: 37 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -202,18 +202,48 @@ private void callHelmInstall() throws Exception {
202202
logger.info("Running " + cmd);
203203
ExecResult result = ExecCommand.exec(cmd.toString());
204204
if (result.exitValue() != 0) {
205-
throw new RuntimeException(
206-
"FAILURE: command "
207-
+ cmd
208-
+ " failed, returned "
209-
+ result.stdout()
210-
+ "\n"
211-
+ result.stderr());
205+
reportHelmInstallFailure(cmd.toString(), result);
212206
}
213207
String outputStr = result.stdout().trim();
214208
logger.info("Command returned " + outputStr);
215209
}
216210

211+
private void reportHelmInstallFailure(String cmd, ExecResult result) throws Exception {
212+
String cause = getExecFailure(cmd, result);
213+
if (result.stderr().contains("Error: Job failed: BackoffLimitExceeded")) {
214+
// The operator helm chart pre-install hook probably failed.
215+
// This is probably because there is a problem with the values passed in,
216+
// for example a listed domain namespace does not exist.
217+
// Fetch the pre-install hook's results and return it too.
218+
String hookResults = getOperatorHelmChartHookResults("pre-install");
219+
cause = cause + "\n pre-install-hook returned\n" + hookResults;
220+
}
221+
throw new RuntimeException(cause);
222+
}
223+
224+
private String getOperatorHelmChartHookResults(String hookType) throws Exception {
225+
String cmd =
226+
"kubectl logs job/"
227+
+ operatorMap.get("releaseName")
228+
+ "-weblogic-operator-"
229+
+ hookType
230+
+ "-hook -n kube-system";
231+
ExecResult result = ExecCommand.exec(cmd);
232+
if (result.exitValue() != 0) {
233+
return getExecFailure(cmd, result);
234+
}
235+
return result.stdout();
236+
}
237+
238+
private String getExecFailure(String cmd, ExecResult result) throws Exception {
239+
return "FAILURE: command "
240+
+ cmd
241+
+ " failed, stdout:\n"
242+
+ result.stdout()
243+
+ "stderr:\n"
244+
+ result.stderr();
245+
}
246+
217247
private void generateInputYaml() throws Exception {
218248
Path parentDir =
219249
Files.createDirectories(Paths.get(userProjectsDir + "/weblogic-operators/" + operatorNS));

integration-tests/src/test/resources/operator1.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,4 @@ serviceAccount: weblogic-operator
77
namespace: weblogic-operator1
88
domainNamespaces: [ "default", "test1" ]
99
externalRestEnabled: true
10-
javaLoggingLevel: FINE
10+
javaLoggingLevel: FINE

integration-tests/src/test/resources/operator2.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ namespace: weblogic-operator2
88
domainNamespaces: [ "test2" ]
99
externalRestEnabled: true
1010
externalRestHttpsPort: 32001
11-
javaLoggingLevel: FINE
11+
javaLoggingLevel: FINE
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# Copyright 2018 Oracle Corporation and/or its affiliates. All rights reserved.
2+
# Licensed under the Universal Permissive License v 1.0 as shown at http://oss.oracle.com/licenses/upl.
3+
4+
{{- define "operator.operatorVerificationHook" }}
5+
{{- $scope := index . 0 }}
6+
{{- $hookType := index . 1 }}
7+
---
8+
apiVersion: "batch/v1"
9+
kind: "Job"
10+
metadata:
11+
name: {{ "OPERATOR_RELEASE-weblogic-operator-HOOK_TYPE-hook" | replace "OPERATOR_RELEASE" $scope.Release.Name | replace "HOOK_TYPE" $hookType | quote }}
12+
namespace: {{ $scope.tillerNamespace | quote }}
13+
labels:
14+
weblogic.resourceVersion: "operator-v2"
15+
weblogic.operatorName: {{ $scope.Release.Namespace | quote }}
16+
annotations:
17+
"helm.sh/hook": {{ $hookType | quote }}
18+
"helm.sh/hook-delete-policy": "before-hook-creation,hook-succeeded"
19+
spec:
20+
backoffLimit: 0
21+
template:
22+
metadata:
23+
labels:
24+
weblogic.resourceVersion: "operator-v2"
25+
weblogic.operatorName: {{ $scope.Release.Namespace | quote }}
26+
spec:
27+
restartPolicy: Never
28+
serviceAccount: {{ $scope.tillerServiceAccount | quote }}
29+
containers:
30+
- name: "weblogic-operator"
31+
command:
32+
- "/operator/operator-helm-verification-hook.sh"
33+
- {{ $hookType | quote }}
34+
- {{ $scope.Release.Namespace | quote }}
35+
- {{ $scope.serviceAccount | quote }}
36+
{{- range $key := $scope.domainNamespaces }}
37+
- {{ $key | quote }}
38+
{{- end }}
39+
image: {{ $scope.image | quote }}
40+
imagePullPolicy: {{ $scope.imagePullPolicy | quote }}
41+
{{- if $scope.imagePullSecrets }}
42+
imagePullSecrets:
43+
{{ $scope.imagePullSecrets | toYaml }}
44+
{{- end }}
45+
{{- end }}

kubernetes/charts/weblogic-operator/templates/_validate-inputs.tpl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@
3333
{{- $ignore := include "utils.verifyInteger" (list $scope "elasticSearchPort") -}}
3434
{{- end -}}
3535
{{- end -}}
36+
{{- $ignore := include "utils.verifyString" (list $scope "tillerNamespace") -}}
37+
{{- $ignore := include "utils.verifyString" (list $scope "tillerServiceAccount") -}}
3638
{{- $ignore:= include "utils.endValidation" $scope -}}
39+
{{- include "operator.operatorVerificationHook" (list $scope "pre-upgrade") }}
40+
{{- include "operator.operatorVerificationHook" (list $scope "pre-install") }}
3741
{{- end -}}

kubernetes/charts/weblogic-operator/values.yaml

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
# serviceAccount specifies the name of the service account that the operator will use to
55
# make requests to the Kubernetes API server.
6-
# The name must be lowercase
6+
# The name must be lowercase.
77
serviceAccount: "default"
88

99
# domainNamespaces specifies list of WebLogic Domain namespaces which the operator manages
@@ -96,3 +96,9 @@ elasticSearchHost: "elasticsearch.default.svc.cluster.local"
9696

9797
# elasticSearchPort specifies the port number of where elasticsearch is running
9898
elasticSearchPort: 9200
99+
100+
# tillerNamespace is the name of the namespace that tiller is configured to use.
101+
tillerNamespace: "kube-system"
102+
103+
# tillerServiceAccount is the name of the service account that tiller is configured to use.
104+
tillerServiceAccount: "default"

kubernetes/src/test/java/oracle/kubernetes/operator/create/CreateOperatorGeneratedFilesOptionalFeaturesEnabledTestBase.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
import io.kubernetes.client.models.ExtensionsV1beta1Deployment;
1515
import io.kubernetes.client.models.V1Container;
16+
import io.kubernetes.client.models.V1Job;
1617
import io.kubernetes.client.models.V1Service;
1718
import oracle.kubernetes.operator.utils.OperatorYamlFactory;
1819

@@ -50,6 +51,18 @@ protected V1Service getExpectedExternalWeblogicOperatorService() {
5051
return getExpectedExternalWeblogicOperatorService(true, true);
5152
}
5253

54+
@Override
55+
protected V1Job getExpectedWeblogicOperatorHookJob(String hookType) {
56+
V1Job expected = super.getExpectedWeblogicOperatorHookJob(hookType);
57+
expected
58+
.getSpec()
59+
.getTemplate()
60+
.getSpec()
61+
.addImagePullSecretsItem(
62+
newLocalObjectReference().name(getInputs().getWeblogicOperatorImagePullSecretName()));
63+
return expected;
64+
}
65+
5366
@Override
5467
public ExtensionsV1beta1Deployment getExpectedWeblogicOperatorDeployment() {
5568
ExtensionsV1beta1Deployment expected = super.getExpectedWeblogicOperatorDeployment();
@@ -66,14 +79,17 @@ public ExtensionsV1beta1Deployment getExpectedWeblogicOperatorDeployment() {
6679
.addContainersItem(
6780
newContainer()
6881
.name("logstash")
69-
.image("logstash:5")
82+
.image(getInputs().getLogStashImage())
7083
.addArgsItem("-f")
7184
.addArgsItem("/logs/logstash.conf")
7285
.addEnvItem(
7386
newEnvVar()
7487
.name("ELASTICSEARCH_HOST")
75-
.value("elasticsearch.default.svc.cluster.local"))
76-
.addEnvItem(newEnvVar().name("ELASTICSEARCH_PORT").value("9200"))
88+
.value(getInputs().getElasticSearchHost()))
89+
.addEnvItem(
90+
newEnvVar()
91+
.name("ELASTICSEARCH_PORT")
92+
.value(getInputs().getElasticSearchPort()))
7793
.addVolumeMountsItem(newVolumeMount().name("log-dir").mountPath("/logs")))
7894
.addVolumesItem(
7995
newVolume().name("log-dir").emptyDir(newEmptyDirVolumeSource().medium("Memory")))

kubernetes/src/test/java/oracle/kubernetes/operator/create/CreateOperatorGeneratedFilesTestBase.java

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newEnvVar;
2222
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newEnvVarSource;
2323
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newExecAction;
24+
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newJob;
25+
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newJobSpec;
2426
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newNamespace;
2527
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newObjectFieldSelector;
2628
import static oracle.kubernetes.operator.utils.KubernetesArtifactUtils.newObjectMeta;
@@ -48,6 +50,8 @@
4850
import io.kubernetes.client.models.V1ClusterRole;
4951
import io.kubernetes.client.models.V1ClusterRoleBinding;
5052
import io.kubernetes.client.models.V1ConfigMap;
53+
import io.kubernetes.client.models.V1Container;
54+
import io.kubernetes.client.models.V1Job;
5155
import io.kubernetes.client.models.V1Namespace;
5256
import io.kubernetes.client.models.V1Role;
5357
import io.kubernetes.client.models.V1RoleBinding;
@@ -68,6 +72,8 @@
6872
*/
6973
public abstract class CreateOperatorGeneratedFilesTestBase {
7074

75+
private static String OPERATOR_RELEASE = "weblogic-operator";
76+
7177
private static OperatorValues inputs;
7278
private static GeneratedOperatorObjects generatedFiles;
7379
private static OperatorYamlFactory factory;
@@ -86,6 +92,79 @@ protected static void setup(OperatorYamlFactory factory, OperatorValues val) thr
8692
generatedFiles = factory.generate(val);
8793
}
8894

95+
@Test
96+
public void generatesCorrect_operatorPreInstallHookJob() {
97+
assertThat(
98+
getActualWeblogicOperatorPreInstallHookJob(),
99+
yamlEqualTo(getExpectedWeblogicOperatorPreInstallHookJob()));
100+
}
101+
102+
private V1Job getActualWeblogicOperatorPreInstallHookJob() {
103+
return getGeneratedFiles().getOperatorPreInstallHookJob();
104+
}
105+
106+
protected V1Job getExpectedWeblogicOperatorPreInstallHookJob() {
107+
return getExpectedWeblogicOperatorHookJob("pre-install");
108+
}
109+
110+
@Test
111+
public void generatesCorrect_operatorPreUpgradeHookJob() {
112+
assertThat(
113+
getActualWeblogicOperatorPreUpgradeHookJob(),
114+
yamlEqualTo(getExpectedWeblogicOperatorPreUpgradeHookJob()));
115+
}
116+
117+
private V1Job getActualWeblogicOperatorPreUpgradeHookJob() {
118+
return getGeneratedFiles().getOperatorPreUpgradeHookJob();
119+
}
120+
121+
protected V1Job getExpectedWeblogicOperatorPreUpgradeHookJob() {
122+
return getExpectedWeblogicOperatorHookJob("pre-upgrade");
123+
}
124+
125+
protected V1Job getExpectedWeblogicOperatorHookJob(String hookType) {
126+
V1Job job =
127+
newJob()
128+
.metadata(
129+
newObjectMeta()
130+
.name(OPERATOR_RELEASE + "-weblogic-operator-" + hookType + "-hook")
131+
.namespace(getInputs().getTillerNamespace())
132+
.putLabelsItem(RESOURCE_VERSION_LABEL, OPERATOR_V2)
133+
.putLabelsItem(OPERATORNAME_LABEL, getInputs().getNamespace())
134+
.putAnnotationsItem("helm.sh/hook", hookType)
135+
.putAnnotationsItem(
136+
"helm.sh/hook-delete-policy", "before-hook-creation,hook-succeeded"))
137+
.spec(
138+
newJobSpec()
139+
.backoffLimit(0)
140+
.template(
141+
newPodTemplateSpec()
142+
.metadata(
143+
newObjectMeta()
144+
.putLabelsItem(RESOURCE_VERSION_LABEL, OPERATOR_V2)
145+
.putLabelsItem(OPERATORNAME_LABEL, getInputs().getNamespace()))
146+
.spec(
147+
newPodSpec()
148+
.restartPolicy("Never")
149+
.serviceAccount(getInputs().getTillerServiceAccount())
150+
.addContainersItem(
151+
newContainer()
152+
.name("weblogic-operator")
153+
.image(getInputs().getWeblogicOperatorImage())
154+
.imagePullPolicy(
155+
getInputs().getWeblogicOperatorImagePullPolicy())
156+
.addCommandItem(
157+
"/operator/operator-helm-verification-hook.sh")
158+
.addCommandItem(hookType)
159+
.addCommandItem(getInputs().getNamespace())
160+
.addCommandItem(getInputs().getServiceAccount())))));
161+
V1Container container = job.getSpec().getTemplate().getSpec().getContainers().get(0);
162+
for (String targetNamespace : getInputs().getTargetNamespaces().split(",")) {
163+
container.addCommandItem(targetNamespace);
164+
}
165+
return job;
166+
}
167+
89168
@Test
90169
public void generatesCorrect_operatorConfigMap() {
91170
assertThat(
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
// Copyright 2018, Oracle Corporation and/or its affiliates. All rights reserved.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at
3+
// http://oss.oracle.com/licenses/upl.
4+
5+
package oracle.kubernetes.operator.helm;
6+
7+
import java.io.BufferedReader;
8+
import java.io.File;
9+
import java.io.InputStream;
10+
import java.io.InputStreamReader;
11+
import java.util.stream.Collectors;
12+
import oracle.kubernetes.operator.utils.PathUtils;
13+
14+
/** Gets a helm chart's default values */
15+
@SuppressWarnings({"unchecked", "SameParameterValue"})
16+
public class ChartDefaultValues {
17+
18+
private String chartName;
19+
20+
ChartDefaultValues(String chartName) {
21+
this.chartName = chartName;
22+
}
23+
24+
/**
25+
* Returns the default values that the chart creates.
26+
*
27+
* @return a yaml string
28+
*/
29+
String getDefaultValuesAsYaml() throws Exception {
30+
processChart();
31+
return getDefaultValuesFromDebugProcessStdout(processChart());
32+
}
33+
34+
private String getDefaultValuesFromDebugProcessStdout(String stdout) throws Exception {
35+
String BEGIN_MARKER = "\nCOMPUTED VALUES:\n";
36+
int begin = stdout.indexOf(BEGIN_MARKER);
37+
if (begin == -1) {
38+
reportProcessError("stdout does not contain " + BEGIN_MARKER + "\nstdout:\n" + stdout);
39+
}
40+
begin = begin + BEGIN_MARKER.length();
41+
String END_MARKER = "\nHOOKS:\n";
42+
int end = stdout.indexOf(END_MARKER, begin);
43+
if (end == -1) {
44+
reportProcessError(
45+
"stdout does not contain \""
46+
+ END_MARKER
47+
+ " after "
48+
+ BEGIN_MARKER
49+
+ ".\nstdout:\n"
50+
+ stdout);
51+
}
52+
return stdout.substring(begin, end);
53+
}
54+
55+
private String processChart() throws Exception {
56+
ProcessBuilder pb = new ProcessBuilder(createCommandLine());
57+
Process p = pb.start();
58+
p.waitFor();
59+
String stdout = read(p.getInputStream());
60+
if (p.exitValue() != 0) {
61+
String stderr = read(p.getErrorStream());
62+
reportProcessError(
63+
"Non-zero exit value.\nexit value: "
64+
+ p.exitValue()
65+
+ "\nstdout:\n"
66+
+ stdout
67+
+ "\nstderr:\n"
68+
+ stderr);
69+
}
70+
return stdout;
71+
}
72+
73+
private void reportProcessError(String msg) throws Exception {
74+
String cmd = String.join(" ", createCommandLine());
75+
throw new Exception(cmd + ": " + msg);
76+
}
77+
78+
private String read(InputStream is) throws Exception {
79+
return new BufferedReader(new InputStreamReader(is)).lines().collect(Collectors.joining("\n"));
80+
}
81+
82+
private String[] createCommandLine() throws Exception {
83+
File chartDir = getChartDir(this.chartName);
84+
return new String[] {"helm", "template", chartDir.getAbsolutePath(), "--debug"};
85+
}
86+
87+
private File getChartDir(String chartName) throws Exception {
88+
return new File(getChartsParentDir(), chartName);
89+
}
90+
91+
private File getChartsParentDir() throws Exception {
92+
return new File(PathUtils.getModuleDir(getClass()), "charts");
93+
}
94+
}

0 commit comments

Comments
 (0)