001/*
002 * Licensed to the Apache Software Foundation (ASF) under one
003 * or more contributor license agreements.  See the NOTICE file
004 * distributed with this work for additional information
005 * regarding copyright ownership.  The ASF licenses this file
006 * to you under the Apache License, Version 2.0 (the
007 * "License"); you may not use this file except in compliance
008 * with the License.  You may obtain a copy of the License at
009 *
010 *     http://www.apache.org/licenses/LICENSE-2.0
011 *
012 * Unless required by applicable law or agreed to in writing, software
013 * distributed under the License is distributed on an "AS IS" BASIS,
014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015 * See the License for the specific language governing permissions and
016 * limitations under the License.
017 */
018package org.apache.hadoop.hbase.rest;
019
020import static org.junit.Assert.assertEquals;
021import static org.junit.Assert.assertFalse;
022
023import java.io.ByteArrayInputStream;
024import java.io.IOException;
025import javax.xml.bind.JAXBContext;
026import javax.xml.bind.JAXBException;
027import org.apache.hadoop.conf.Configuration;
028import org.apache.hadoop.hbase.HBaseClassTestRule;
029import org.apache.hadoop.hbase.HBaseTestingUtility;
030import org.apache.hadoop.hbase.NamespaceDescriptor;
031import org.apache.hadoop.hbase.client.Admin;
032import org.apache.hadoop.hbase.rest.client.Client;
033import org.apache.hadoop.hbase.rest.client.Cluster;
034import org.apache.hadoop.hbase.rest.client.Response;
035import org.apache.hadoop.hbase.rest.model.NamespacesModel;
036import org.apache.hadoop.hbase.rest.model.TestNamespacesModel;
037import org.apache.hadoop.hbase.testclassification.MediumTests;
038import org.apache.hadoop.hbase.testclassification.RestTests;
039import org.apache.hadoop.hbase.util.Bytes;
040import org.junit.AfterClass;
041import org.junit.BeforeClass;
042import org.junit.ClassRule;
043import org.junit.Test;
044import org.junit.experimental.categories.Category;
045
046@Category({ RestTests.class, MediumTests.class })
047public class TestNamespacesResource {
048  @ClassRule
049  public static final HBaseClassTestRule CLASS_RULE =
050    HBaseClassTestRule.forClass(TestNamespacesResource.class);
051
052  private static String NAMESPACE1 = "TestNamespacesInstanceResource1";
053  private static String NAMESPACE2 = "TestNamespacesInstanceResource2";
054
055  private static final HBaseTestingUtility TEST_UTIL = new HBaseTestingUtility();
056  private static final HBaseRESTTestingUtility REST_TEST_UTIL = new HBaseRESTTestingUtility();
057  private static Client client;
058  private static JAXBContext context;
059  private static Configuration conf;
060  private static TestNamespacesModel testNamespacesModel;
061
062  @BeforeClass
063  public static void setUpBeforeClass() throws Exception {
064    conf = TEST_UTIL.getConfiguration();
065    TEST_UTIL.startMiniCluster();
066    REST_TEST_UTIL.startServletContainer(conf);
067    client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort()));
068    testNamespacesModel = new TestNamespacesModel();
069    context = JAXBContext.newInstance(NamespacesModel.class);
070  }
071
072  @AfterClass
073  public static void tearDownAfterClass() throws Exception {
074    REST_TEST_UTIL.shutdownServletContainer();
075    TEST_UTIL.shutdownMiniCluster();
076  }
077
078  private static NamespacesModel fromXML(byte[] content) throws JAXBException {
079    return (NamespacesModel) context.createUnmarshaller()
080      .unmarshal(new ByteArrayInputStream(content));
081  }
082
083  private boolean doesNamespaceExist(Admin admin, String namespaceName) throws IOException {
084    NamespaceDescriptor[] nd = admin.listNamespaceDescriptors();
085    for (NamespaceDescriptor namespaceDescriptor : nd) {
086      if (namespaceDescriptor.getName().equals(namespaceName)) {
087        return true;
088      }
089    }
090    return false;
091  }
092
093  private void createNamespaceViaAdmin(Admin admin, String name) throws IOException {
094    NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(name);
095    NamespaceDescriptor nsd = builder.build();
096    admin.createNamespace(nsd);
097  }
098
099  @Test
100  public void testNamespaceListXMLandJSON() throws IOException, JAXBException {
101    String namespacePath = "/namespaces/";
102    NamespacesModel model;
103    Response response;
104
105    // Check that namespace does not yet exist via non-REST call.
106    Admin admin = TEST_UTIL.getAdmin();
107    assertFalse(doesNamespaceExist(admin, NAMESPACE1));
108    model = testNamespacesModel.buildTestModel();
109    testNamespacesModel.checkModel(model);
110
111    // Check that REST GET finds only default namespaces via XML and JSON responses.
112    response = client.get(namespacePath, Constants.MIMETYPE_XML);
113    assertEquals(200, response.getCode());
114    model = fromXML(response.getBody());
115    testNamespacesModel.checkModel(model, "hbase", "default");
116    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
117    assertEquals(200, response.getCode());
118    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
119    testNamespacesModel.checkModel(model, "hbase", "default");
120
121    // Create namespace and check that REST GET finds one additional namespace.
122    createNamespaceViaAdmin(admin, NAMESPACE1);
123    response = client.get(namespacePath, Constants.MIMETYPE_XML);
124    assertEquals(200, response.getCode());
125    model = fromXML(response.getBody());
126    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
127    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
128    assertEquals(200, response.getCode());
129    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
130    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
131
132    // Create another namespace and check that REST GET finds one additional namespace.
133    createNamespaceViaAdmin(admin, NAMESPACE2);
134    response = client.get(namespacePath, Constants.MIMETYPE_XML);
135    assertEquals(200, response.getCode());
136    model = fromXML(response.getBody());
137    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
138    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
139    assertEquals(200, response.getCode());
140    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
141    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
142
143    // Delete namespace and check that REST still finds correct namespaces.
144    admin.deleteNamespace(NAMESPACE1);
145    response = client.get(namespacePath, Constants.MIMETYPE_XML);
146    assertEquals(200, response.getCode());
147    model = fromXML(response.getBody());
148    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
149    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
150    assertEquals(200, response.getCode());
151    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
152    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
153
154    admin.deleteNamespace(NAMESPACE2);
155  }
156
157  @Test
158  public void testNamespaceListPBandDefault() throws IOException {
159    String schemaPath = "/namespaces/";
160    NamespacesModel model;
161    Response response;
162
163    // Check that namespace does not yet exist via non-REST call.
164    Admin admin = TEST_UTIL.getAdmin();
165    assertFalse(doesNamespaceExist(admin, NAMESPACE1));
166    model = testNamespacesModel.buildTestModel();
167    testNamespacesModel.checkModel(model);
168
169    // Check that REST GET finds only default namespaces via PB and default Accept header.
170    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
171    assertEquals(200, response.getCode());
172    model.getObjectFromMessage(response.getBody());
173    testNamespacesModel.checkModel(model, "hbase", "default");
174    response = client.get(schemaPath);
175    assertEquals(200, response.getCode());
176
177    // Create namespace and check that REST GET finds one additional namespace.
178    createNamespaceViaAdmin(admin, NAMESPACE1);
179    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
180    assertEquals(200, response.getCode());
181    model.getObjectFromMessage(response.getBody());
182    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
183    response = client.get(schemaPath);
184    assertEquals(200, response.getCode());
185
186    // Create another namespace and check that REST GET finds one additional namespace.
187    createNamespaceViaAdmin(admin, NAMESPACE2);
188    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
189    assertEquals(200, response.getCode());
190    model.getObjectFromMessage(response.getBody());
191    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
192    response = client.get(schemaPath);
193    assertEquals(200, response.getCode());
194
195    // Delete namespace and check that REST GET still finds correct namespaces.
196    admin.deleteNamespace(NAMESPACE1);
197    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
198    assertEquals(200, response.getCode());
199    model.getObjectFromMessage(response.getBody());
200    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
201    response = client.get(schemaPath);
202    assertEquals(200, response.getCode());
203
204    admin.deleteNamespace(NAMESPACE2);
205  }
206}