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