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 =
057    new HBaseRESTTestingUtility();
058  private static Client client;
059  private static JAXBContext context;
060  private static Configuration conf;
061  private static TestNamespacesModel testNamespacesModel;
062
063  @BeforeClass
064  public static void setUpBeforeClass() throws Exception {
065    conf = TEST_UTIL.getConfiguration();
066    TEST_UTIL.startMiniCluster();
067    REST_TEST_UTIL.startServletContainer(conf);
068    client = new Client(new Cluster().add("localhost", REST_TEST_UTIL.getServletPort()));
069    testNamespacesModel = new TestNamespacesModel();
070    context = JAXBContext.newInstance(NamespacesModel.class);
071  }
072
073  @AfterClass
074  public static void tearDownAfterClass() throws Exception {
075    REST_TEST_UTIL.shutdownServletContainer();
076    TEST_UTIL.shutdownMiniCluster();
077  }
078
079  private static NamespacesModel fromXML(byte[] content) throws JAXBException {
080    return (NamespacesModel) context.createUnmarshaller()
081      .unmarshal(new ByteArrayInputStream(content));
082  }
083
084  private boolean doesNamespaceExist(Admin admin, String namespaceName) throws IOException {
085    NamespaceDescriptor[] nd = admin.listNamespaceDescriptors();
086    for (NamespaceDescriptor namespaceDescriptor : nd) {
087      if (namespaceDescriptor.getName().equals(namespaceName)) {
088        return true;
089      }
090    }
091    return false;
092  }
093
094  private void createNamespaceViaAdmin(Admin admin, String name) throws IOException {
095    NamespaceDescriptor.Builder builder = NamespaceDescriptor.create(name);
096    NamespaceDescriptor nsd = builder.build();
097    admin.createNamespace(nsd);
098  }
099
100  @Test
101  public void testNamespaceListXMLandJSON() throws IOException, JAXBException {
102    String namespacePath = "/namespaces/";
103    NamespacesModel model;
104    Response response;
105
106    // Check that namespace does not yet exist via non-REST call.
107    Admin admin = TEST_UTIL.getAdmin();
108    assertFalse(doesNamespaceExist(admin, NAMESPACE1));
109    model = testNamespacesModel.buildTestModel();
110    testNamespacesModel.checkModel(model);
111
112    // Check that REST GET finds only default namespaces via XML and JSON responses.
113    response = client.get(namespacePath, Constants.MIMETYPE_XML);
114    assertEquals(200, response.getCode());
115    model = fromXML(response.getBody());
116    testNamespacesModel.checkModel(model, "hbase", "default");
117    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
118    assertEquals(200, response.getCode());
119    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
120    testNamespacesModel.checkModel(model, "hbase", "default");
121
122    // Create namespace and check that REST GET finds one additional namespace.
123    createNamespaceViaAdmin(admin, NAMESPACE1);
124    response = client.get(namespacePath, Constants.MIMETYPE_XML);
125    assertEquals(200, response.getCode());
126    model = fromXML(response.getBody());
127    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
128    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
129    assertEquals(200, response.getCode());
130    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
131    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
132
133    // Create another namespace and check that REST GET finds one additional namespace.
134    createNamespaceViaAdmin(admin, NAMESPACE2);
135    response = client.get(namespacePath, Constants.MIMETYPE_XML);
136    assertEquals(200, response.getCode());
137    model = fromXML(response.getBody());
138    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
139    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
140    assertEquals(200, response.getCode());
141    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
142    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
143
144    // Delete namespace and check that REST still finds correct namespaces.
145    admin.deleteNamespace(NAMESPACE1);
146    response = client.get(namespacePath, Constants.MIMETYPE_XML);
147    assertEquals(200, response.getCode());
148    model = fromXML(response.getBody());
149    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
150    response = client.get(namespacePath, Constants.MIMETYPE_JSON);
151    assertEquals(200, response.getCode());
152    model = testNamespacesModel.fromJSON(Bytes.toString(response.getBody()));
153    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
154
155    admin.deleteNamespace(NAMESPACE2);
156  }
157
158  @Test
159  public void testNamespaceListPBandDefault() throws IOException {
160    String schemaPath = "/namespaces/";
161    NamespacesModel model;
162    Response response;
163
164    // Check that namespace does not yet exist via non-REST call.
165    Admin admin = TEST_UTIL.getAdmin();
166    assertFalse(doesNamespaceExist(admin, NAMESPACE1));
167    model = testNamespacesModel.buildTestModel();
168    testNamespacesModel.checkModel(model);
169
170    // Check that REST GET finds only default namespaces via PB and default Accept header.
171    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
172    assertEquals(200, response.getCode());
173    model.getObjectFromMessage(response.getBody());
174    testNamespacesModel.checkModel(model, "hbase", "default");
175    response = client.get(schemaPath);
176    assertEquals(200, response.getCode());
177
178    // Create namespace and check that REST GET finds one additional namespace.
179    createNamespaceViaAdmin(admin, NAMESPACE1);
180    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
181    assertEquals(200, response.getCode());
182    model.getObjectFromMessage(response.getBody());
183    testNamespacesModel.checkModel(model, NAMESPACE1, "hbase", "default");
184    response = client.get(schemaPath);
185    assertEquals(200, response.getCode());
186
187    // Create another namespace and check that REST GET finds one additional namespace.
188    createNamespaceViaAdmin(admin, NAMESPACE2);
189    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
190    assertEquals(200, response.getCode());
191    model.getObjectFromMessage(response.getBody());
192    testNamespacesModel.checkModel(model, NAMESPACE1, NAMESPACE2, "hbase", "default");
193    response = client.get(schemaPath);
194    assertEquals(200, response.getCode());
195
196    // Delete namespace and check that REST GET still finds correct namespaces.
197    admin.deleteNamespace(NAMESPACE1);
198    response = client.get(schemaPath, Constants.MIMETYPE_PROTOBUF);
199    assertEquals(200, response.getCode());
200    model.getObjectFromMessage(response.getBody());
201    testNamespacesModel.checkModel(model, NAMESPACE2, "hbase", "default");
202    response = client.get(schemaPath);
203    assertEquals(200, response.getCode());
204
205    admin.deleteNamespace(NAMESPACE2);
206  }
207}