Skip to content

Commit 96c913c

Browse files
authored
Support for Kubernetes exec command (#1604)
* Add support for Kubernetes exec API * Update processing input stream and adding ExecResult return type * clean up reading output thread join * add test to call exec * First code review changes * Remove set/get methods in KubernetesExec
1 parent 7db2126 commit 96c913c

File tree

5 files changed

+358
-12
lines changed

5 files changed

+358
-12
lines changed

new-integration-tests/src/test/java/oracle/weblogic/kubernetes/ItMiiDomain.java

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import io.kubernetes.client.openapi.models.V1EnvVar;
1818
import io.kubernetes.client.openapi.models.V1LocalObjectReference;
1919
import io.kubernetes.client.openapi.models.V1ObjectMeta;
20+
import io.kubernetes.client.openapi.models.V1Pod;
2021
import io.kubernetes.client.openapi.models.V1Secret;
2122
import io.kubernetes.client.openapi.models.V1SecretReference;
2223
import io.kubernetes.client.openapi.models.V1ServiceAccount;
@@ -36,6 +37,7 @@
3637
import oracle.weblogic.kubernetes.annotations.tags.MustNotRunInParallel;
3738
import oracle.weblogic.kubernetes.annotations.tags.Slow;
3839
import oracle.weblogic.kubernetes.extensions.LoggedTest;
40+
import oracle.weblogic.kubernetes.utils.ExecResult;
3941
import org.awaitility.core.ConditionFactory;
4042
import org.junit.jupiter.api.AfterAll;
4143
import org.junit.jupiter.api.BeforeAll;
@@ -74,6 +76,7 @@
7476
import static oracle.weblogic.kubernetes.actions.TestActions.deleteServiceAccount;
7577
import static oracle.weblogic.kubernetes.actions.TestActions.dockerLogin;
7678
import static oracle.weblogic.kubernetes.actions.TestActions.dockerPush;
79+
import static oracle.weblogic.kubernetes.actions.TestActions.execCommand;
7780
import static oracle.weblogic.kubernetes.actions.TestActions.getOperatorImageName;
7881
import static oracle.weblogic.kubernetes.actions.TestActions.installOperator;
7982
import static oracle.weblogic.kubernetes.actions.TestActions.uninstallOperator;
@@ -88,9 +91,11 @@
8891
import static oracle.weblogic.kubernetes.utils.FileUtils.checkDirectory;
8992
import static org.awaitility.Awaitility.with;
9093
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
94+
import static org.junit.jupiter.api.Assertions.assertEquals;
9195
import static org.junit.jupiter.api.Assertions.assertFalse;
9296
import static org.junit.jupiter.api.Assertions.assertNotNull;
9397
import static org.junit.jupiter.api.Assertions.assertTrue;
98+
import static org.junit.jupiter.api.Assertions.fail;
9499

95100
// Test to create model in image domain and verify the domain started successfully
96101
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
@@ -107,6 +112,8 @@ class ItMiiDomain implements LoggedTest {
107112
private static final String DOMAIN_VERSION = "v7";
108113
private static final String API_VERSION = "weblogic.oracle/" + DOMAIN_VERSION;
109114

115+
private static final String READ_STATE_COMMAND = "/weblogic-operator/scripts/readState.sh";
116+
110117
private static HelmParams opHelmParams = null;
111118
private static V1ServiceAccount serviceAccount = null;
112119
private String serviceAccountName = null;
@@ -300,6 +307,9 @@ public void testCreateMiiDomain() {
300307
adminServerPodName, domainNamespace);
301308
checkPodReady(adminServerPodName, domainUid, domainNamespace);
302309

310+
logger.info("Check admin server status by calling read state command");
311+
checkServerReadyStatusByExec(adminServerPodName, domainNamespace);
312+
303313
// check managed server pods are ready
304314
for (int i = 1; i <= replicaCount; i++) {
305315
logger.info("Wait for managed server pod {0} to be ready in namespace {1}",
@@ -757,4 +767,23 @@ private void checkServiceCreated(String serviceName, String domNamespace) {
757767

758768
}
759769

770+
private void checkServerReadyStatusByExec(String podName, String namespace) {
771+
final V1Pod pod = assertDoesNotThrow(() -> oracle.weblogic.kubernetes.assertions.impl.Kubernetes
772+
.getPod(namespace, null, podName));
773+
774+
if (pod != null) {
775+
ExecResult execResult = assertDoesNotThrow(
776+
() -> execCommand(pod, null, true, READ_STATE_COMMAND));
777+
if (execResult.exitValue() == 0) {
778+
logger.info("execResult: " + execResult);
779+
assertEquals("RUNNING", execResult.stdout(),
780+
"Expected " + podName + ", in namespace " + namespace + ", to be in RUNNING ready status");
781+
} else {
782+
fail("Ready command failed with exit status code: " + execResult.exitValue());
783+
}
784+
} else {
785+
fail("Did not find pod " + podName + " in namespace " + namespace);
786+
}
787+
}
788+
760789
}

new-integration-tests/src/test/java/oracle/weblogic/kubernetes/actions/TestActions.java

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
package oracle.weblogic.kubernetes.actions;
55

6+
import java.io.IOException;
67
import java.util.List;
78

89
import com.google.gson.JsonObject;
@@ -12,6 +13,7 @@
1213
import io.kubernetes.client.openapi.models.V1ConfigMap;
1314
import io.kubernetes.client.openapi.models.V1PersistentVolume;
1415
import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim;
16+
import io.kubernetes.client.openapi.models.V1Pod;
1517
import io.kubernetes.client.openapi.models.V1Secret;
1618
import io.kubernetes.client.openapi.models.V1Service;
1719
import io.kubernetes.client.openapi.models.V1ServiceAccount;
@@ -21,6 +23,7 @@
2123
import oracle.weblogic.kubernetes.actions.impl.ClusterRoleBinding;
2224
import oracle.weblogic.kubernetes.actions.impl.ConfigMap;
2325
import oracle.weblogic.kubernetes.actions.impl.Domain;
26+
import oracle.weblogic.kubernetes.actions.impl.Exec;
2427
import oracle.weblogic.kubernetes.actions.impl.Namespace;
2528
import oracle.weblogic.kubernetes.actions.impl.Operator;
2629
import oracle.weblogic.kubernetes.actions.impl.OperatorParams;
@@ -36,6 +39,7 @@
3639
import oracle.weblogic.kubernetes.actions.impl.primitive.HelmParams;
3740
import oracle.weblogic.kubernetes.actions.impl.primitive.WebLogicImageTool;
3841
import oracle.weblogic.kubernetes.actions.impl.primitive.WitParams;
42+
import oracle.weblogic.kubernetes.utils.ExecResult;
3943

4044
// this class essentially delegates to the impl classes, and "hides" all of the
4145
// detail impl classes - tests would only ever call methods in here, never
@@ -492,10 +496,10 @@ public static boolean buildAppArchive(AppParams params) {
492496

493497
/**
494498
* Log in to a Docker registry.
495-
* @param registryName registry name
496-
* @param username user
497-
* @param password password
498-
* @return true if successfull
499+
* @param registryName name of Docker registry
500+
* @param username username for the Docker registry
501+
* @param password password for the Docker registry
502+
* @return true if successful, false otherwise
499503
*/
500504
public static boolean dockerLogin(String registryName, String username, String password) {
501505
return Docker.login(registryName, username, password);
@@ -531,6 +535,27 @@ public static JsonObject createDockerConfigJson(String username, String password
531535
return Docker.createDockerConfigJson(username, password, email, registry);
532536
}
533537

538+
// ----------------------- Execute a Command ---------------------------
539+
540+
/**
541+
* Execute a command in a container.
542+
*
543+
* @param pod The pod where the command is to be run
544+
* @param containerName The container in the Pod where the command is to be run. If no
545+
* container name is provided than the first container in the Pod is used.
546+
* @param redirectToStdout copy process output to stdout
547+
* @param command The command to run
548+
* @return result of command execution
549+
* @throws IOException if an I/O error occurs.
550+
* @throws ApiException if Kubernetes client API call fails
551+
* @throws InterruptedException if any thread has interrupted the current thread
552+
*/
553+
public static ExecResult execCommand(V1Pod pod, String containerName, boolean redirectToStdout,
554+
String... command)
555+
throws IOException, ApiException, InterruptedException {
556+
return Exec.exec(pod, containerName, redirectToStdout, command);
557+
}
558+
534559
// ------------------------ where does this go -------------------------
535560

536561
/**
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// Copyright (c) 2020, Oracle Corporation and/or its affiliates.
2+
// Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
3+
4+
package oracle.weblogic.kubernetes.actions.impl;
5+
6+
import java.io.IOException;
7+
8+
import io.kubernetes.client.openapi.ApiException;
9+
import io.kubernetes.client.openapi.models.V1Pod;
10+
import oracle.weblogic.kubernetes.actions.impl.primitive.Kubernetes;
11+
import oracle.weblogic.kubernetes.utils.ExecResult;
12+
13+
public class Exec {
14+
15+
/**
16+
* Execute a command in a container.
17+
*
18+
* @param pod The pod where the command is to be run
19+
* @param containerName The container in the Pod where the command is to be run. If no
20+
* container name is provided than the first container in the Pod is used.
21+
* @param redirectToStdout copy process output to stdout
22+
* @param command The command to run
23+
* @return result of command execution
24+
* @throws IOException if an I/O error occurs.
25+
* @throws ApiException if Kubernetes client API call fails
26+
* @throws InterruptedException if any thread has interrupted the current thread
27+
*/
28+
public static ExecResult exec(V1Pod pod, String containerName, boolean redirectToStdout,
29+
String... command)
30+
throws IOException, ApiException, InterruptedException {
31+
return Kubernetes.exec(pod, containerName, redirectToStdout, command);
32+
}
33+
}

0 commit comments

Comments
 (0)