1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.hadoop.hbase.rest;
19
20 import static org.junit.Assert.assertEquals;
21 import static org.junit.Assert.assertNotNull;
22 import static org.junit.Assert.assertNull;
23 import static org.junit.Assert.assertTrue;
24
25 import com.fasterxml.jackson.databind.ObjectMapper;
26
27 import java.io.ByteArrayInputStream;
28 import java.io.IOException;
29 import java.io.StringWriter;
30 import java.util.ArrayList;
31 import java.util.Arrays;
32 import java.util.HashMap;
33 import java.util.List;
34 import java.util.Map;
35
36 import javax.ws.rs.core.MediaType;
37 import javax.xml.bind.JAXBContext;
38 import javax.xml.bind.JAXBException;
39
40 import org.apache.hadoop.conf.Configuration;
41 import org.apache.hadoop.hbase.HBaseTestingUtility;
42 import org.apache.hadoop.hbase.HColumnDescriptor;
43 import org.apache.hadoop.hbase.HTableDescriptor;
44 import org.apache.hadoop.hbase.NamespaceDescriptor;
45 import org.apache.hadoop.hbase.TableName;
46 import org.apache.hadoop.hbase.client.Admin;
47 import org.apache.hadoop.hbase.rest.client.Client;
48 import org.apache.hadoop.hbase.rest.client.Cluster;
49 import org.apache.hadoop.hbase.rest.client.Response;
50 import org.apache.hadoop.hbase.rest.model.NamespacesInstanceModel;
51 import org.apache.hadoop.hbase.rest.model.TableListModel;
52 import org.apache.hadoop.hbase.rest.model.TableModel;
53 import org.apache.hadoop.hbase.rest.model.TestNamespacesInstanceModel;
54 import org.apache.hadoop.hbase.rest.provider.JacksonProvider;
55 import org.apache.hadoop.hbase.testclassification.MediumTests;
56 import org.apache.hadoop.hbase.util.Bytes;
57
58 import org.junit.AfterClass;
59 import org.junit.BeforeClass;
60 import org.junit.Test;
61 import org.junit.experimental.categories.Category;
62
63 @Category(MediumTests.class)
64 public class TestNamespacesInstanceResource {
65 private static String NAMESPACE1 = "TestNamespacesInstanceResource1";
66 private static Map<String,String> NAMESPACE1_PROPS = new HashMap<>();
67 private static String NAMESPACE2 = "TestNamespacesInstanceResource2";
68 private static Map<String,String> NAMESPACE2_PROPS = new HashMap<>();
69 private static String NAMESPACE3 = "TestNamespacesInstanceResource3";
70 private static Map<String,String> NAMESPACE3_PROPS = new HashMap<>();
71 private static String NAMESPACE4 = "TestNamespacesInstanceResource4";
72 private static Map<String,String> NAMESPACE4_PROPS = new HashMap<>();
73
74 private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
75 private static final HBaseRESTTestingUtility REST_TEST_UTIL =
76 new HBaseRESTTestingUtility();
77 private static Client client;
78 private static JAXBContext context;
79 private static Configuration conf;
80 private static TestNamespacesInstanceModel testNamespacesInstanceModel;
81 protected static ObjectMapper jsonMapper;
82
83 @BeforeClass
84 public static void setUpBeforeClass() throws Exception {
85 conf = TEST_UTIL.getConfiguration();
86 TEST_UTIL.startMiniCluster();
87 REST_TEST_UTIL.startServletContainer(conf);
88 client = new Client(new Cluster().add("localhost",
89 REST_TEST_UTIL.getServletPort()));
90 testNamespacesInstanceModel = new TestNamespacesInstanceModel();
91 context = JAXBContext.newInstance(NamespacesInstanceModel.class, TableListModel.class);
92 jsonMapper = new JacksonProvider().locateMapper(NamespacesInstanceModel.class,
93 MediaType.APPLICATION_JSON_TYPE);
94 NAMESPACE1_PROPS.put("key1", "value1");
95 NAMESPACE2_PROPS.put("key2a", "value2a");
96 NAMESPACE2_PROPS.put("key2b", "value2b");
97 NAMESPACE3_PROPS.put("key3", "value3");
98 NAMESPACE4_PROPS.put("key4a", "value4a");
99 NAMESPACE4_PROPS.put("key4b", "value4b");
100 }
101
102 @AfterClass
103 public static void tearDownAfterClass() throws Exception {
104 REST_TEST_UTIL.shutdownServletContainer();
105 TEST_UTIL.shutdownMiniCluster();
106 }
107
108 private static byte[] toXML(NamespacesInstanceModel model) throws JAXBException {
109 StringWriter writer = new StringWriter();
110 context.createMarshaller().marshal(model, writer);
111 return Bytes.toBytes(writer.toString());
112 }
113
114 @SuppressWarnings("unchecked")
115 private static <T> T fromXML(byte[] content)
116 throws JAXBException {
117 return (T) context.createUnmarshaller().unmarshal(new ByteArrayInputStream(content));
118 }
119
120 private NamespaceDescriptor findNamespace(Admin admin, String namespaceName) throws IOException{
121 NamespaceDescriptor[] nd = admin.listNamespaceDescriptors();
122 for (NamespaceDescriptor namespaceDescriptor : nd) {
123 if (namespaceDescriptor.getName().equals(namespaceName)) {
124 return namespaceDescriptor;
125 }
126 }
127 return null;
128 }
129
130 private void checkNamespaceProperties(NamespaceDescriptor nd, Map<String,String> testProps){
131 checkNamespaceProperties(nd.getConfiguration(), testProps);
132 }
133
134 private void checkNamespaceProperties(Map<String,String> namespaceProps,
135 Map<String,String> testProps){
136 assertTrue(namespaceProps.size() == testProps.size());
137 for (String key: testProps.keySet()) {
138 assertEquals(testProps.get(key), namespaceProps.get(key));
139 }
140 }
141
142 private void checkNamespaceTables(List<TableModel> namespaceTables, List<String> testTables){
143 assertEquals(namespaceTables.size(), testTables.size());
144 for (TableModel namespaceTable : namespaceTables) {
145 String tableName = namespaceTable.getName();
146 assertTrue(testTables.contains(tableName));
147 }
148 }
149
150 @Test
151 public void testCannotDeleteDefaultAndHbaseNamespaces() throws IOException {
152 String defaultPath = "/namespaces/default";
153 String hbasePath = "/namespaces/hbase";
154 Response response;
155
156
157 Admin admin = TEST_UTIL.getHBaseAdmin();
158 assertNotNull(findNamespace(admin, "default"));
159 assertNotNull(findNamespace(admin, "hbase"));
160
161
162 response = client.delete(defaultPath);
163 assertEquals(503, response.getCode());
164 response = client.delete(hbasePath);
165 assertEquals(503, response.getCode());
166
167 assertNotNull(findNamespace(admin, "default"));
168 assertNotNull(findNamespace(admin, "hbase"));
169 }
170
171 @Test
172 public void testGetNamespaceTablesAndCannotDeleteNamespace() throws IOException, JAXBException {
173 Admin admin = TEST_UTIL.getHBaseAdmin();
174 String nsName = "TestNamespacesInstanceResource5";
175 Response response;
176
177
178 NamespaceDescriptor.Builder nsBuilder = NamespaceDescriptor.create(nsName);
179 NamespaceDescriptor nsd = nsBuilder.build();
180 nsd.setConfiguration("key1", "value1");
181 admin.createNamespace(nsd);
182
183
184 HColumnDescriptor colDesc = new HColumnDescriptor("cf1");
185 TableName tn1 = TableName.valueOf(nsName + ":table1");
186 HTableDescriptor table = new HTableDescriptor(tn1);
187 table.addFamily(colDesc);
188 admin.createTable(table);
189 TableName tn2 = TableName.valueOf(nsName + ":table2");
190 table = new HTableDescriptor(tn2);
191 table.addFamily(colDesc);
192 admin.createTable(table);
193
194 Map<String, String> nsProperties = new HashMap<>();
195 nsProperties.put("key1", "value1");
196 List<String> nsTables = Arrays.asList("table1", "table2");
197
198
199 String namespacePath = "/namespaces/" + nsName;
200 response = client.get(namespacePath);
201 assertEquals(200, response.getCode());
202
203 response = client.get(namespacePath, Constants.MIMETYPE_XML);
204 assertEquals(200, response.getCode());
205 NamespacesInstanceModel model = fromXML(response.getBody());
206 checkNamespaceProperties(model.getProperties(), nsProperties);
207
208 response = client.get(namespacePath, Constants.MIMETYPE_JSON);
209 assertEquals(200, response.getCode());
210 model = jsonMapper.readValue(response.getBody(), NamespacesInstanceModel.class);
211 checkNamespaceProperties(model.getProperties(), nsProperties);
212
213 response = client.get(namespacePath, Constants.MIMETYPE_PROTOBUF);
214 assertEquals(200, response.getCode());
215 model.getObjectFromMessage(response.getBody());
216 checkNamespaceProperties(model.getProperties(), nsProperties);
217
218
219 namespacePath = "/namespaces/" + nsName + "/tables";
220 response = client.get(namespacePath);
221 assertEquals(200, response.getCode());
222
223 response = client.get(namespacePath, Constants.MIMETYPE_XML);
224 assertEquals(200, response.getCode());
225 TableListModel tablemodel = fromXML(response.getBody());
226 checkNamespaceTables(tablemodel.getTables(), nsTables);
227
228 response = client.get(namespacePath, Constants.MIMETYPE_JSON);
229 assertEquals(200, response.getCode());
230 tablemodel = jsonMapper.readValue(response.getBody(), TableListModel.class);
231 checkNamespaceTables(tablemodel.getTables(), nsTables);
232
233 response = client.get(namespacePath, Constants.MIMETYPE_PROTOBUF);
234 assertEquals(200, response.getCode());
235 tablemodel.setTables(new ArrayList<TableModel>());
236 tablemodel.getObjectFromMessage(response.getBody());
237 checkNamespaceTables(tablemodel.getTables(), nsTables);
238
239
240 response = client.delete(namespacePath);
241 namespacePath = "/namespaces/" + nsName;
242 assertEquals(503, response.getCode());
243 }
244
245 @Test
246 public void testInvalidNamespacePostsAndPuts() throws IOException, JAXBException {
247 String namespacePath1 = "/namespaces/" + NAMESPACE1;
248 String namespacePath2 = "/namespaces/" + NAMESPACE2;
249 String namespacePath3 = "/namespaces/" + NAMESPACE3;
250 NamespacesInstanceModel model1;
251 NamespacesInstanceModel model2;
252 NamespacesInstanceModel model3;
253 Response response;
254
255
256 Admin admin = TEST_UTIL.getHBaseAdmin();
257 assertNull(findNamespace(admin, NAMESPACE1));
258 assertNull(findNamespace(admin, NAMESPACE2));
259 assertNull(findNamespace(admin, NAMESPACE3));
260
261 model1 = testNamespacesInstanceModel.buildTestModel(NAMESPACE1, NAMESPACE1_PROPS);
262 testNamespacesInstanceModel.checkModel(model1, NAMESPACE1, NAMESPACE1_PROPS);
263 model2 = testNamespacesInstanceModel.buildTestModel(NAMESPACE2, NAMESPACE2_PROPS);
264 testNamespacesInstanceModel.checkModel(model2, NAMESPACE2, NAMESPACE2_PROPS);
265 model3 = testNamespacesInstanceModel.buildTestModel(NAMESPACE3, NAMESPACE3_PROPS);
266 testNamespacesInstanceModel.checkModel(model3, NAMESPACE3, NAMESPACE3_PROPS);
267
268
269 response = client.post(namespacePath1, Constants.MIMETYPE_JSON, toXML(model1));
270 assertEquals(500, response.getCode());
271 String jsonString = jsonMapper.writeValueAsString(model2);
272 response = client.put(namespacePath2, Constants.MIMETYPE_XML, Bytes.toBytes(jsonString));
273 assertEquals(400, response.getCode());
274 response = client.post(namespacePath3, Constants.MIMETYPE_PROTOBUF, toXML(model1));
275 assertEquals(500, response.getCode());
276
277 NamespaceDescriptor nd1 = findNamespace(admin, NAMESPACE1);
278 NamespaceDescriptor nd2 = findNamespace(admin, NAMESPACE2);
279 NamespaceDescriptor nd3 = findNamespace(admin, NAMESPACE3);
280 assertNull(nd1);
281 assertNull(nd2);
282 assertNull(nd3);
283 }
284
285 @Test
286 public void testNamespaceCreateAndDeleteXMLAndJSON() throws IOException, JAXBException {
287 String namespacePath1 = "/namespaces/" + NAMESPACE1;
288 String namespacePath2 = "/namespaces/" + NAMESPACE2;
289 NamespacesInstanceModel model1;
290 NamespacesInstanceModel model2;
291 Response response;
292
293
294 Admin admin = TEST_UTIL.getHBaseAdmin();
295 assertNull(findNamespace(admin, NAMESPACE1));
296 assertNull(findNamespace(admin, NAMESPACE2));
297
298 model1 = testNamespacesInstanceModel.buildTestModel(NAMESPACE1, NAMESPACE1_PROPS);
299 testNamespacesInstanceModel.checkModel(model1, NAMESPACE1, NAMESPACE1_PROPS);
300 model2 = testNamespacesInstanceModel.buildTestModel(NAMESPACE2, NAMESPACE2_PROPS);
301 testNamespacesInstanceModel.checkModel(model2, NAMESPACE2, NAMESPACE2_PROPS);
302
303
304 response = client.put(namespacePath1, Constants.MIMETYPE_XML, toXML(model1));
305 assertEquals(403, response.getCode());
306 String jsonString = jsonMapper.writeValueAsString(model2);
307 response = client.put(namespacePath2, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString));
308 assertEquals(403, response.getCode());
309
310
311 conf.set("hbase.rest.readonly", "true");
312 response = client.post(namespacePath1, Constants.MIMETYPE_XML, toXML(model1));
313 assertEquals(403, response.getCode());
314 jsonString = jsonMapper.writeValueAsString(model2);
315 response = client.post(namespacePath2, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString));
316 assertEquals(403, response.getCode());
317 NamespaceDescriptor nd1 = findNamespace(admin, NAMESPACE1);
318 NamespaceDescriptor nd2 = findNamespace(admin, NAMESPACE2);
319 assertNull(nd1);
320 assertNull(nd2);
321 conf.set("hbase.rest.readonly", "false");
322
323
324 response = client.post(namespacePath1, Constants.MIMETYPE_XML, toXML(model1));
325 assertEquals(201, response.getCode());
326 jsonString = jsonMapper.writeValueAsString(model2);
327 response = client.post(namespacePath2, Constants.MIMETYPE_JSON, Bytes.toBytes(jsonString));
328 assertEquals(201, response.getCode());
329
330
331 nd1 = findNamespace(admin, NAMESPACE1);
332 nd2 = findNamespace(admin, NAMESPACE2);
333 assertNotNull(nd1);
334 assertNotNull(nd2);
335 checkNamespaceProperties(nd1, NAMESPACE1_PROPS);
336 checkNamespaceProperties(nd1, NAMESPACE1_PROPS);
337
338
339 conf.set("hbase.rest.readonly", "true");
340 response = client.delete(namespacePath1);
341 assertEquals(403, response.getCode());
342 response = client.delete(namespacePath2);
343 assertEquals(403, response.getCode());
344 nd1 = findNamespace(admin, NAMESPACE1);
345 nd2 = findNamespace(admin, NAMESPACE2);
346 assertNotNull(nd1);
347 assertNotNull(nd2);
348 conf.set("hbase.rest.readonly", "false");
349
350
351 response = client.delete(namespacePath1);
352 assertEquals(200, response.getCode());
353 response = client.delete(namespacePath2);
354 assertEquals(200, response.getCode());
355 nd1 = findNamespace(admin, NAMESPACE1);
356 nd2 = findNamespace(admin, NAMESPACE2);
357 assertNull(nd1);
358 assertNull(nd2);
359 }
360
361 @Test
362 public void testNamespaceCreateAndDeletePBAndNoBody() throws IOException {
363 String namespacePath3 = "/namespaces/" + NAMESPACE3;
364 String namespacePath4 = "/namespaces/" + NAMESPACE4;
365 NamespacesInstanceModel model3;
366 NamespacesInstanceModel model4;
367 Response response;
368
369
370 Admin admin = TEST_UTIL.getHBaseAdmin();
371 assertNull(findNamespace(admin, NAMESPACE3));
372 assertNull(findNamespace(admin, NAMESPACE4));
373
374 model3 = testNamespacesInstanceModel.buildTestModel(NAMESPACE3, NAMESPACE3_PROPS);
375 testNamespacesInstanceModel.checkModel(model3, NAMESPACE3, NAMESPACE3_PROPS);
376 model4 = testNamespacesInstanceModel.buildTestModel(NAMESPACE4, NAMESPACE4_PROPS);
377 testNamespacesInstanceModel.checkModel(model4, NAMESPACE4, NAMESPACE4_PROPS);
378
379
380 response = client.put(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
381 assertEquals(403, response.getCode());
382 response = client.put(namespacePath4, Constants.MIMETYPE_PROTOBUF,
383 model4.createProtobufOutput());
384 assertEquals(403, response.getCode());
385
386
387 conf.set("hbase.rest.readonly", "true");
388 response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
389 assertEquals(403, response.getCode());
390 response = client.put(namespacePath4, Constants.MIMETYPE_PROTOBUF,
391 model4.createProtobufOutput());
392 assertEquals(403, response.getCode());
393 NamespaceDescriptor nd3 = findNamespace(admin, NAMESPACE3);
394 NamespaceDescriptor nd4 = findNamespace(admin, NAMESPACE4);
395 assertNull(nd3);
396 assertNull(nd4);
397 conf.set("hbase.rest.readonly", "false");
398
399
400 response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
401 assertEquals(201, response.getCode());
402 response = client.post(namespacePath4, Constants.MIMETYPE_PROTOBUF,
403 model4.createProtobufOutput());
404 assertEquals(201, response.getCode());
405
406
407 nd3 = findNamespace(admin, NAMESPACE3);
408 nd4 = findNamespace(admin, NAMESPACE4);
409 assertNotNull(nd3);
410 assertNotNull(nd4);
411 checkNamespaceProperties(nd3, new HashMap<String,String>());
412 checkNamespaceProperties(nd4, NAMESPACE4_PROPS);
413
414
415 response = client.post(namespacePath3, Constants.MIMETYPE_BINARY, new byte[]{});
416 assertEquals(403, response.getCode());
417 response = client.post(namespacePath4, Constants.MIMETYPE_PROTOBUF,
418 model4.createProtobufOutput());
419 assertEquals(403, response.getCode());
420
421
422 conf.set("hbase.rest.readonly", "true");
423 response = client.delete(namespacePath3);
424 assertEquals(403, response.getCode());
425 response = client.delete(namespacePath4);
426 assertEquals(403, response.getCode());
427 nd3 = findNamespace(admin, NAMESPACE3);
428 nd4 = findNamespace(admin, NAMESPACE4);
429 assertNotNull(nd3);
430 assertNotNull(nd4);
431 conf.set("hbase.rest.readonly", "false");
432
433
434 response = client.delete(namespacePath3);
435 assertEquals(200, response.getCode());
436 response = client.delete(namespacePath4);
437 assertEquals(200, response.getCode());
438 nd3 = findNamespace(admin, NAMESPACE3);
439 nd4 = findNamespace(admin, NAMESPACE4);
440 assertNull(nd3);
441 assertNull(nd4);
442 }
443 }