3
3
4
4
package oracle .weblogic .kubernetes ;
5
5
6
+ import java .io .IOException ;
7
+ import java .nio .charset .StandardCharsets ;
8
+ import java .nio .file .Files ;
9
+ import java .nio .file .Path ;
10
+ import java .nio .file .Paths ;
11
+ import java .util .ArrayList ;
12
+ import java .util .HashMap ;
6
13
import java .util .List ;
7
14
15
+ import io .kubernetes .client .custom .IntOrString ;
16
+ import io .kubernetes .client .openapi .models .NetworkingV1beta1HTTPIngressPath ;
17
+ import io .kubernetes .client .openapi .models .NetworkingV1beta1HTTPIngressRuleValue ;
18
+ import io .kubernetes .client .openapi .models .NetworkingV1beta1IngressBackend ;
19
+ import io .kubernetes .client .openapi .models .NetworkingV1beta1IngressRule ;
20
+ import oracle .weblogic .kubernetes .actions .impl .primitive .HelmParams ;
8
21
import oracle .weblogic .kubernetes .annotations .IntegrationTest ;
9
22
import oracle .weblogic .kubernetes .annotations .Namespaces ;
10
23
import oracle .weblogic .kubernetes .logging .LoggingFacade ;
24
+ import oracle .weblogic .kubernetes .utils .ExecCommand ;
25
+ import oracle .weblogic .kubernetes .utils .ExecResult ;
26
+ import org .awaitility .core .ConditionFactory ;
11
27
import org .junit .jupiter .api .AfterAll ;
12
28
import org .junit .jupiter .api .BeforeAll ;
13
29
import org .junit .jupiter .api .DisplayName ;
14
30
import org .junit .jupiter .api .Test ;
15
31
32
+ import static java .util .concurrent .TimeUnit .MINUTES ;
33
+ import static java .util .concurrent .TimeUnit .SECONDS ;
16
34
import static oracle .weblogic .kubernetes .TestConstants .ADMIN_SERVER_NAME_BASE ;
17
35
import static oracle .weblogic .kubernetes .TestConstants .K8S_NODEPORT_HOST ;
18
36
import static oracle .weblogic .kubernetes .TestConstants .MANAGED_SERVER_NAME_BASE ;
19
37
import static oracle .weblogic .kubernetes .TestConstants .MII_BASIC_IMAGE_NAME ;
20
38
import static oracle .weblogic .kubernetes .TestConstants .MII_BASIC_IMAGE_TAG ;
39
+ import static oracle .weblogic .kubernetes .TestConstants .RESULTS_ROOT ;
40
+ import static oracle .weblogic .kubernetes .TestConstants .VOYAGER_CHART_NAME ;
41
+ import static oracle .weblogic .kubernetes .actions .ActionConstants .RESOURCE_DIR ;
42
+ import static oracle .weblogic .kubernetes .actions .TestActions .createIngress ;
43
+ import static oracle .weblogic .kubernetes .actions .TestActions .listIngresses ;
21
44
import static oracle .weblogic .kubernetes .actions .impl .Service .getServiceNodePort ;
45
+ import static oracle .weblogic .kubernetes .assertions .TestAssertions .isVoyagerReady ;
22
46
import static oracle .weblogic .kubernetes .utils .CommonMiiTestUtils .createMiiDomainAndVerify ;
47
+ import static oracle .weblogic .kubernetes .utils .CommonTestUtils .createIngressAndRetryIfFail ;
23
48
import static oracle .weblogic .kubernetes .utils .CommonTestUtils .getExternalServicePodName ;
49
+ import static oracle .weblogic .kubernetes .utils .CommonTestUtils .installAndVerifyNginx ;
24
50
import static oracle .weblogic .kubernetes .utils .CommonTestUtils .installAndVerifyOperator ;
51
+ import static oracle .weblogic .kubernetes .utils .CommonTestUtils .installAndVerifyTraefik ;
52
+ import static oracle .weblogic .kubernetes .utils .CommonTestUtils .installAndVerifyVoyager ;
25
53
import static oracle .weblogic .kubernetes .utils .CommonTestUtils .installAndVerifyWlsRemoteConsole ;
26
54
import static oracle .weblogic .kubernetes .utils .CommonTestUtils .shutdownWlsRemoteConsole ;
55
+ import static oracle .weblogic .kubernetes .utils .TestUtils .callWebAppAndWaitTillReady ;
27
56
import static oracle .weblogic .kubernetes .utils .TestUtils .callWebAppAndWaitTillReturnedCode ;
28
57
import static oracle .weblogic .kubernetes .utils .ThreadSafeLogger .getLogger ;
58
+ import static org .assertj .core .api .Assertions .assertThat ;
59
+ import static org .awaitility .Awaitility .with ;
60
+ import static org .junit .jupiter .api .Assertions .assertDoesNotThrow ;
61
+ import static org .junit .jupiter .api .Assertions .assertEquals ;
29
62
import static org .junit .jupiter .api .Assertions .assertNotNull ;
30
63
import static org .junit .jupiter .api .Assertions .assertTrue ;
31
64
34
67
class ItRemoteConsole {
35
68
36
69
private static String domainNamespace = null ;
70
+ private static String traefikNamespace = null ;
71
+ private static String voyagerNamespace = null ;
72
+ private static String nginxNamespace = null ;
73
+ private static HelmParams traefikHelmParams = null ;
74
+ private static HelmParams voyagerHelmParams = null ;
75
+ private static HelmParams nginxHelmParams = null ;
76
+ private static int voyagerNodePort ;
77
+ private static int nginxNodePort ;
37
78
38
79
// domain constants
39
80
private static final String domainUid = "domain1" ;
40
- private static final String clusterName = "cluster-1" ;
41
81
private static final int replicaCount = 1 ;
42
82
private static final String adminServerPodName = domainUid + "-" + ADMIN_SERVER_NAME_BASE ;
43
83
private static final String managedServerPrefix = domainUid + "-" + MANAGED_SERVER_NAME_BASE ;
44
84
private static LoggingFacade logger = null ;
85
+ private static final int ADMIN_SERVER_PORT = 7001 ;
86
+ private static final String voyagerIngressName = "voyager-path-routing" ;
87
+
88
+ private static ConditionFactory withStandardRetryPolicy =
89
+ with ().pollDelay (2 , SECONDS )
90
+ .and ().with ().pollInterval (10 , SECONDS )
91
+ .atMost (5 , MINUTES ).await ();
45
92
46
93
/**
47
94
* Get namespaces for operator and WebLogic domain.
@@ -50,7 +97,7 @@ class ItRemoteConsole {
50
97
* JUnit engine parameter resolution mechanism
51
98
*/
52
99
@ BeforeAll
53
- public static void initAll (@ Namespaces (2 ) List <String > namespaces ) {
100
+ public static void initAll (@ Namespaces (5 ) List <String > namespaces ) {
54
101
logger = getLogger ();
55
102
// get a unique operator namespace
56
103
logger .info ("Getting a unique namespace for operator" );
@@ -62,9 +109,36 @@ public static void initAll(@Namespaces(2) List<String> namespaces) {
62
109
assertNotNull (namespaces .get (1 ), "Namespace list is null" );
63
110
domainNamespace = namespaces .get (1 );
64
111
112
+ logger .info ("Assign a unique namespace for Traefik" );
113
+ assertNotNull (namespaces .get (2 ), "Namespace list is null" );
114
+ traefikNamespace = namespaces .get (2 );
115
+
116
+ // get a unique Voyager namespace
117
+ logger .info ("Assign a unique namespace for Voyager" );
118
+ assertNotNull (namespaces .get (3 ), "Namespace list is null" );
119
+ voyagerNamespace = namespaces .get (3 );
120
+
121
+ // get a unique Nginx namespace
122
+ logger .info ("Assign a unique namespace for Nginx" );
123
+ assertNotNull (namespaces .get (4 ), "Namespace list is null" );
124
+ nginxNamespace = namespaces .get (4 );
125
+
65
126
// install and verify operator
66
127
installAndVerifyOperator (opNamespace , domainNamespace );
67
128
129
+ // install and verify Traefik
130
+ logger .info ("Installing Traefik controller using helm" );
131
+ traefikHelmParams = installAndVerifyTraefik (traefikNamespace , 0 , 0 );
132
+
133
+ // install and verify Voyager
134
+ final String cloudProvider = "baremetal" ;
135
+ final boolean enableValidatingWebhook = false ;
136
+ voyagerHelmParams =
137
+ installAndVerifyVoyager (voyagerNamespace , cloudProvider , enableValidatingWebhook );
138
+
139
+ // install and verify Nginx
140
+ nginxHelmParams = installAndVerifyNginx (nginxNamespace , 0 , 0 );
141
+
68
142
// create a basic model in image domain
69
143
createMiiDomainAndVerify (
70
144
domainNamespace ,
@@ -74,32 +148,77 @@ public static void initAll(@Namespaces(2) List<String> namespaces) {
74
148
managedServerPrefix ,
75
149
replicaCount );
76
150
151
+ // create ingress rules with path routing for Traefik, Voyager and NGINX
152
+ createTraefikIngressRoutingRules (domainNamespace );
153
+ createVoyagerIngressPathRoutingRules ();
154
+ createNginxIngressPathRoutingRules ();
155
+
156
+ // install WebLogic remote console
157
+ assertTrue (installAndVerifyWlsRemoteConsole (), "Remote Console installation failed" );
158
+
159
+ // Verify k8s WebLogic domain is accessible through remote console using admin server nodeport
160
+ verifyWlsRemoteConsoleConnection ();
77
161
}
78
162
79
163
/**
80
- * Verify WLS Remote Console installation is successful.
81
- * Verify k8s WebLogic domain is accessible through remote console.
164
+ * Verify k8s WebLogic domain is accessible through remote console using Traefik.
82
165
*/
83
166
@ Test
84
- @ DisplayName ("Verify Connecting to Mii domain through WLS Remote Console is successful" )
85
- public void testWlsRemoteConsoleConnection () {
86
-
87
- assertTrue (installAndVerifyWlsRemoteConsole (), "Remote Console installation failed" );
167
+ @ DisplayName ("Verify Connecting to Mii domain WLS Remote Console through Traefik is successful" )
168
+ public void testWlsRemoteConsoleConnectionThroughTraefik () {
88
169
89
- int nodePort = getServiceNodePort (
90
- domainNamespace , getExternalServicePodName (adminServerPodName ), "default" );
91
- assertTrue (nodePort != -1 ,
170
+ int traefikNodePort = getServiceNodePort (traefikNamespace , traefikHelmParams .getReleaseName (), "web" );
171
+ assertTrue (traefikNodePort != -1 ,
92
172
"Could not get the default external service node port" );
93
- logger .info ("Found the default service nodePort {0}" , nodePort );
173
+ logger .info ("Found the Traefik service nodePort {0}" , traefikNodePort );
94
174
logger .info ("The K8S_NODEPORT_HOST is {0}" , K8S_NODEPORT_HOST );
95
175
String curlCmd = "curl -v --user weblogic:welcome1 -H Content-Type:application/json -d "
96
176
+ "\" { \\ " + "\" domainUrl\\ " + "\" " + ": " + "\\ " + "\" " + "http://"
97
- + K8S_NODEPORT_HOST + ":" + nodePort + "\\ " + "\" }" + "\" "
177
+ + K8S_NODEPORT_HOST + ":" + traefikNodePort + "\\ " + "\" }" + "\" "
98
178
+ " http://localhost:8012/api/connection --write-out %{http_code} -o /dev/null" ;
99
- logger .info ("Executing default nodeport curl command {0}" , curlCmd );
179
+ logger .info ("Executing Traefik nodeport curl command {0}" , curlCmd );
100
180
assertTrue (callWebAppAndWaitTillReturnedCode (curlCmd , "201" , 10 ), "Calling web app failed" );
101
- logger .info ("WebLogic domain is accessible through remote console" );
181
+ logger .info ("WebLogic domain is accessible through remote console using Traefik" );
182
+ }
102
183
184
+ /**
185
+ * Verify k8s WebLogic domain is accessible through remote console using Voyager.
186
+ */
187
+ @ Test
188
+ @ DisplayName ("Verify Connecting to Mii domain WLS Remote Console through Voyager is successful" )
189
+ public void testWlsRemoteConsoleConnectionThroughVoyager () {
190
+
191
+ assertTrue (voyagerNodePort != -1 , "Could not get the default external service node port" );
192
+ logger .info ("Found the Voyager service nodePort {0}" , voyagerNodePort );
193
+ logger .info ("The K8S_NODEPORT_HOST is {0}" , K8S_NODEPORT_HOST );
194
+
195
+ String curlCmd = "curl -v --user weblogic:welcome1 -H Content-Type:application/json -d "
196
+ + "\" { \\ " + "\" domainUrl\\ " + "\" " + ": " + "\\ " + "\" " + "http://"
197
+ + K8S_NODEPORT_HOST + ":" + voyagerNodePort + "\\ " + "\" }" + "\" "
198
+ + " http://localhost:8012/api/connection --write-out %{http_code} -o /dev/null" ;
199
+ logger .info ("Executing Voyager nodeport curl command {0}" , curlCmd );
200
+ assertTrue (callWebAppAndWaitTillReturnedCode (curlCmd , "201" , 10 ), "Calling web app failed" );
201
+ logger .info ("WebLogic domain is accessible through remote console using Voyager" );
202
+ }
203
+
204
+ /**
205
+ * Verify k8s WebLogic domain is accessible through remote console using NGINX.
206
+ */
207
+ @ Test
208
+ @ DisplayName ("Verify Connecting to Mii domain WLS Remote Console through NGINX is successful" )
209
+ public void testWlsRemoteConsoleConnectionThroughNginx () {
210
+
211
+ assertTrue (nginxNodePort != -1 , "Could not get the default external service node port" );
212
+ logger .info ("Found the NGINX service nodePort {0}" , nginxNodePort );
213
+ logger .info ("The K8S_NODEPORT_HOST is {0}" , K8S_NODEPORT_HOST );
214
+
215
+ String curlCmd = "curl -v --user weblogic:welcome1 -H Content-Type:application/json -d "
216
+ + "\" { \\ " + "\" domainUrl\\ " + "\" " + ": " + "\\ " + "\" " + "http://"
217
+ + K8S_NODEPORT_HOST + ":" + nginxNodePort + "\\ " + "\" }" + "\" "
218
+ + " http://localhost:8012/api/connection --write-out %{http_code} -o /dev/null" ;
219
+ logger .info ("Executing NGINX nodeport curl command {0}" , curlCmd );
220
+ assertTrue (callWebAppAndWaitTillReturnedCode (curlCmd , "201" , 10 ), "Calling web app failed" );
221
+ logger .info ("WebLogic domain is accessible through remote console using NGINX" );
103
222
}
104
223
105
224
/**
@@ -114,4 +233,151 @@ public void tearDownAll() {
114
233
}
115
234
}
116
235
236
+ private static void createTraefikIngressRoutingRules (String domainNamespace ) {
237
+ logger .info ("Creating ingress rules for domain traffic routing" );
238
+ Path srcFile = Paths .get (RESOURCE_DIR , "traefik/traefik-ingress-rules-remoteconsole.yaml" );
239
+ Path dstFile = Paths .get (RESULTS_ROOT , "traefik/traefik-ingress-rules-remoteconsole.yaml" );
240
+ assertDoesNotThrow (() -> {
241
+ Files .deleteIfExists (dstFile );
242
+ Files .createDirectories (dstFile .getParent ());
243
+ Files .write (dstFile , Files .readString (srcFile ).replaceAll ("@NS@" , domainNamespace )
244
+ .replaceAll ("@domain1uid@" , domainUid )
245
+ .getBytes (StandardCharsets .UTF_8 ));
246
+ });
247
+ String command = "kubectl create -f " + dstFile ;
248
+ logger .info ("Running {0}" , command );
249
+ ExecResult result ;
250
+ try {
251
+ result = ExecCommand .exec (command , true );
252
+ String response = result .stdout ().trim ();
253
+ logger .info ("exitCode: {0}, \n stdout: {1}, \n stderr: {2}" ,
254
+ result .exitValue (), response , result .stderr ());
255
+ assertEquals (0 , result .exitValue (), "Command didn't succeed" );
256
+ } catch (IOException | InterruptedException ex ) {
257
+ logger .severe (ex .getMessage ());
258
+ }
259
+ }
260
+
261
+ private static void createVoyagerIngressPathRoutingRules () {
262
+
263
+ // set the annotations for Voyager
264
+ HashMap <String , String > annotations = new HashMap <>();
265
+ annotations .put ("ingress.appscode.com/type" , "NodePort" );
266
+ annotations .put ("kubernetes.io/ingress.class" , "voyager" );
267
+ annotations .put ("ingress.appscode.com/rewrite-target" , "/" );
268
+
269
+ List <NetworkingV1beta1IngressRule > ingressRules = new ArrayList <>();
270
+ List <NetworkingV1beta1HTTPIngressPath > httpIngressPaths = new ArrayList <>();
271
+
272
+ NetworkingV1beta1HTTPIngressPath httpIngressPath = new NetworkingV1beta1HTTPIngressPath ()
273
+ .path ("/" )
274
+ .backend (new NetworkingV1beta1IngressBackend ()
275
+ .serviceName (domainUid + "-admin-server" )
276
+ .servicePort (new IntOrString (ADMIN_SERVER_PORT ))
277
+ );
278
+ httpIngressPaths .add (httpIngressPath );
279
+
280
+ NetworkingV1beta1IngressRule ingressRule = new NetworkingV1beta1IngressRule ()
281
+ .host ("" )
282
+ .http (new NetworkingV1beta1HTTPIngressRuleValue ()
283
+ .paths (httpIngressPaths ));
284
+
285
+ ingressRules .add (ingressRule );
286
+
287
+ assertDoesNotThrow (() -> createIngress (voyagerIngressName , domainNamespace , annotations , ingressRules , null ));
288
+
289
+ // wait until voyager ingress pod is ready
290
+ withStandardRetryPolicy
291
+ .conditionEvaluationListener (
292
+ condition -> logger .info (
293
+ "Waiting for Voyager ingress to be ready in namespace {0} (elapsed time {1}ms, remaining time {2}ms)" ,
294
+ domainNamespace ,
295
+ condition .getElapsedTimeInMS (),
296
+ condition .getRemainingTimeInMS ()))
297
+ .until (assertDoesNotThrow (() -> isVoyagerReady (domainNamespace , voyagerIngressName ),
298
+ "isVoyagerReady failed with ApiException" ));
299
+
300
+ // check the ingress was found in the domain namespace
301
+ assertThat (assertDoesNotThrow (() -> listIngresses (domainNamespace )))
302
+ .as (String .format ("Test ingress %s was found in namespace %s" , voyagerIngressName , domainNamespace ))
303
+ .withFailMessage (String .format ("Ingress %s was not found in namespace %s" , voyagerIngressName , domainNamespace ))
304
+ .contains (voyagerIngressName );
305
+
306
+ logger .info ("ingress {0} was created in namespace {1}" , voyagerIngressName , domainNamespace );
307
+
308
+ // check the ingress is ready to route the app to the server pod
309
+ voyagerNodePort = assertDoesNotThrow (() ->
310
+ getServiceNodePort (domainNamespace , VOYAGER_CHART_NAME + "-" + voyagerIngressName , "tcp-80" ),
311
+ "Getting voyager loadbalancer service node port failed" );
312
+ String curlCmd = "curl --silent --show-error --noproxy '*' http://" + K8S_NODEPORT_HOST + ":" + voyagerNodePort
313
+ + "/weblogic/ready --write-out %{http_code} -o /dev/null" ;
314
+
315
+ logger .info ("Executing curl command {0}" , curlCmd );
316
+ assertTrue (callWebAppAndWaitTillReady (curlCmd , 60 ));
317
+ }
318
+
319
+ private static void createNginxIngressPathRoutingRules () {
320
+
321
+ // create an ingress in domain namespace
322
+ String ingressName = domainNamespace + "-nginx-path-routing" ;
323
+
324
+ HashMap <String , String > annotations = new HashMap <>();
325
+ annotations .put ("kubernetes.io/ingress.class" , "nginx" );
326
+
327
+ // create ingress rules for two domains
328
+ List <NetworkingV1beta1IngressRule > ingressRules = new ArrayList <>();
329
+ List <NetworkingV1beta1HTTPIngressPath > httpIngressPaths = new ArrayList <>();
330
+
331
+ NetworkingV1beta1HTTPIngressPath httpIngressPath = new NetworkingV1beta1HTTPIngressPath ()
332
+ .path ("/" )
333
+ .backend (new NetworkingV1beta1IngressBackend ()
334
+ .serviceName (domainUid + "-admin-server" )
335
+ .servicePort (new IntOrString (ADMIN_SERVER_PORT ))
336
+ );
337
+ httpIngressPaths .add (httpIngressPath );
338
+
339
+ NetworkingV1beta1IngressRule ingressRule = new NetworkingV1beta1IngressRule ()
340
+ .host ("" )
341
+ .http (new NetworkingV1beta1HTTPIngressRuleValue ()
342
+ .paths (httpIngressPaths ));
343
+
344
+ ingressRules .add (ingressRule );
345
+
346
+ createIngressAndRetryIfFail (60 , false , ingressName , domainNamespace , annotations , ingressRules , null );
347
+
348
+ // check the ingress was found in the domain namespace
349
+ assertThat (assertDoesNotThrow (() -> listIngresses (domainNamespace )))
350
+ .as (String .format ("Test ingress %s was found in namespace %s" , ingressName , domainNamespace ))
351
+ .withFailMessage (String .format ("Ingress %s was not found in namespace %s" , ingressName , domainNamespace ))
352
+ .contains (ingressName );
353
+
354
+ logger .info ("ingress {0} was created in namespace {1}" , ingressName , domainNamespace );
355
+
356
+ // check the ingress is ready to route the app to the server pod
357
+ String nginxServiceName = nginxHelmParams .getReleaseName () + "-ingress-nginx-controller" ;
358
+ nginxNodePort = assertDoesNotThrow (() -> getServiceNodePort (nginxNamespace , nginxServiceName , "http" ),
359
+ "Getting Nginx loadbalancer service node port failed" );
360
+ String curlCmd = "curl --silent --show-error --noproxy '*' http://" + K8S_NODEPORT_HOST + ":" + nginxNodePort
361
+ + "/weblogic/ready --write-out %{http_code} -o /dev/null" ;
362
+
363
+ logger .info ("Executing curl command {0}" , curlCmd );
364
+ assertTrue (callWebAppAndWaitTillReady (curlCmd , 60 ));
365
+ }
366
+
367
+ private static void verifyWlsRemoteConsoleConnection () {
368
+
369
+ int nodePort = getServiceNodePort (
370
+ domainNamespace , getExternalServicePodName (adminServerPodName ), "default" );
371
+ assertTrue (nodePort != -1 ,
372
+ "Could not get the default external service node port" );
373
+ logger .info ("Found the default service nodePort {0}" , nodePort );
374
+ logger .info ("The K8S_NODEPORT_HOST is {0}" , K8S_NODEPORT_HOST );
375
+ String curlCmd = "curl -v --user weblogic:welcome1 -H Content-Type:application/json -d "
376
+ + "\" { \\ " + "\" domainUrl\\ " + "\" " + ": " + "\\ " + "\" " + "http://"
377
+ + K8S_NODEPORT_HOST + ":" + nodePort + "\\ " + "\" }" + "\" "
378
+ + " http://localhost:8012/api/connection --write-out %{http_code} -o /dev/null" ;
379
+ logger .info ("Executing default nodeport curl command {0}" , curlCmd );
380
+ assertTrue (callWebAppAndWaitTillReturnedCode (curlCmd , "201" , 10 ), "Calling web app failed" );
381
+ logger .info ("WebLogic domain is accessible through remote console" );
382
+ }
117
383
}
0 commit comments