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