1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertFalse;
22 import static org.junit.Assert.assertTrue;
23 import com.google.protobuf.RpcController;
24 import com.google.protobuf.ServiceException;
25 import java.io.File;
26 import java.io.IOException;
27 import java.nio.file.Files;
28 import java.nio.file.Path;
29 import java.nio.file.Paths;
30 import org.apache.commons.io.IOUtils;
31 import org.apache.hadoop.conf.Configuration;
32 import org.apache.hadoop.hbase.client.Admin;
33 import org.apache.hadoop.hbase.client.Connection;
34 import org.apache.hadoop.hbase.coprocessor.protobuf.generated.ShellExecEndpoint.ShellExecRequest;
35 import org.apache.hadoop.hbase.coprocessor.protobuf.generated.ShellExecEndpoint.ShellExecResponse;
36 import org.apache.hadoop.hbase.coprocessor.protobuf.generated.ShellExecEndpoint.ShellExecService;
37 import org.apache.hadoop.hbase.ipc.HBaseRpcControllerImpl;
38 import org.apache.hadoop.hbase.testclassification.MediumTests;
39 import org.junit.AfterClass;
40 import org.junit.BeforeClass;
41 import org.junit.Test;
42 import org.junit.experimental.categories.Category;
43
44
45
46
47 @Category(MediumTests.class)
48 public class TestShellExecEndpointCoprocessor {
49
50 private static IntegrationTestingUtility util;
51 private static Connection connection;
52
53 @BeforeClass
54 public static void setUp() throws Exception {
55
56 if (util == null) {
57 util = new IntegrationTestingUtility(createConfiguration());
58 util.initializeCluster(3);
59 connection = util.getConnection();
60 }
61 }
62
63
64 @AfterClass
65 public static void teardown() throws Exception {
66 IOUtils.closeQuietly(connection);
67
68 if (util != null) {
69 util.restoreCluster();
70 util = null;
71 }
72 }
73 @Test
74 public void testShellExecUnspecified() throws IOException, ServiceException {
75 testShellExecForeground(ShellExecRequest.newBuilder());
76 }
77
78 @Test
79 public void testShellExecForeground() throws IOException, ServiceException {
80 testShellExecForeground(ShellExecRequest.newBuilder().setAwaitResponse(true));
81 }
82
83 private void testShellExecForeground(final ShellExecRequest.Builder builder)
84 throws IOException, ServiceException {
85 final Admin admin = connection.getAdmin();
86
87 final String command = "echo -n \"hello world\"";
88 builder.setCommand(command);
89 ShellExecService.BlockingInterface stub =
90 ShellExecService.newBlockingStub(admin.coprocessorService());
91 RpcController controller = new HBaseRpcControllerImpl();
92 ShellExecResponse resp = stub.shellExec(controller, builder.build());
93 assertEquals(0, resp.getExitCode());
94 assertEquals("hello world", resp.getStdout());
95 }
96
97 @Test
98 public void testShellExecBackground() throws IOException, ServiceException {
99 Admin admin = connection.getAdmin();
100 final File testDataDir = ensureTestDataDirExists(util);
101 final File testFile = new File(testDataDir, "shell_exec_background.txt");
102 assertTrue(testFile.createNewFile());
103 assertEquals(0, testFile.length());
104
105 final String command = "echo \"hello world\" >> " + testFile.getAbsolutePath();
106 final ShellExecRequest req = ShellExecRequest.newBuilder()
107 .setCommand(command)
108 .setAwaitResponse(false)
109 .build();
110
111 ShellExecService.BlockingInterface stub =
112 ShellExecService.newBlockingStub(admin.coprocessorService());
113 RpcController controller = new HBaseRpcControllerImpl();
114 ShellExecResponse resp = stub.shellExec(controller, req);
115 assertFalse("the response from a background task should have no exit code", resp.hasExitCode());
116 assertFalse("the response from a background task should have no stdout", resp.hasStdout());
117 assertFalse("the response from a background task should have no stderr", resp.hasStderr());
118
119 Waiter.waitFor(util.getConfiguration(), 5_000, new Waiter.Predicate<Exception>() {
120 @Override
121 public boolean evaluate() throws Exception {
122 return testFile.length() > 0;
123 }
124 });
125 final String content = new String(Files.readAllBytes(testFile.toPath())).trim();
126 assertEquals("hello world", content);
127 }
128
129 private static File ensureTestDataDirExists(final HBaseTestingUtility testingUtility)
130 throws IOException {
131 final Path testDataDir = Paths.get(testingUtility.getDataTestDir().toString());
132 final File testDataDirFile = Files.createDirectories(testDataDir).toFile();
133 assertTrue(testDataDirFile.exists());
134 return testDataDirFile;
135 }
136
137 private static Configuration createConfiguration() {
138 final Configuration conf = HBaseConfiguration.create();
139 conf.set("hbase.coprocessor.master.classes", ShellExecEndpointCoprocessor.class.getName());
140 return conf;
141 }
142 }