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.thrift2; 019 020import static java.nio.ByteBuffer.wrap; 021import static org.junit.jupiter.api.Assertions.assertEquals; 022import static org.junit.jupiter.api.Assertions.assertFalse; 023import static org.junit.jupiter.api.Assertions.assertTrue; 024 025import java.io.IOException; 026import java.nio.ByteBuffer; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.List; 030import org.apache.hadoop.conf.Configuration; 031import org.apache.hadoop.hbase.DoNotRetryIOException; 032import org.apache.hadoop.hbase.HBaseTestingUtil; 033import org.apache.hadoop.hbase.TableName; 034import org.apache.hadoop.hbase.client.Admin; 035import org.apache.hadoop.hbase.client.ColumnFamilyDescriptor; 036import org.apache.hadoop.hbase.client.ColumnFamilyDescriptorBuilder; 037import org.apache.hadoop.hbase.client.TableDescriptor; 038import org.apache.hadoop.hbase.client.TableDescriptorBuilder; 039import org.apache.hadoop.hbase.security.UserProvider; 040import org.apache.hadoop.hbase.testclassification.ClientTests; 041import org.apache.hadoop.hbase.testclassification.MediumTests; 042import org.apache.hadoop.hbase.thrift2.generated.TAppend; 043import org.apache.hadoop.hbase.thrift2.generated.TColumnIncrement; 044import org.apache.hadoop.hbase.thrift2.generated.TColumnValue; 045import org.apache.hadoop.hbase.thrift2.generated.TCompareOperator; 046import org.apache.hadoop.hbase.thrift2.generated.TDelete; 047import org.apache.hadoop.hbase.thrift2.generated.TGet; 048import org.apache.hadoop.hbase.thrift2.generated.TIOError; 049import org.apache.hadoop.hbase.thrift2.generated.TIncrement; 050import org.apache.hadoop.hbase.thrift2.generated.TMutation; 051import org.apache.hadoop.hbase.thrift2.generated.TPut; 052import org.apache.hadoop.hbase.thrift2.generated.TRowMutations; 053import org.apache.hadoop.hbase.thrift2.generated.TScan; 054import org.apache.hadoop.hbase.util.Bytes; 055import org.junit.jupiter.api.AfterAll; 056import org.junit.jupiter.api.BeforeAll; 057import org.junit.jupiter.api.BeforeEach; 058import org.junit.jupiter.api.Tag; 059import org.junit.jupiter.api.Test; 060 061import org.apache.hbase.thirdparty.org.apache.thrift.TException; 062 063@Tag(ClientTests.TAG) 064@Tag(MediumTests.TAG) 065public class TestThriftHBaseServiceHandlerWithReadOnly { 066 067 private static final HBaseTestingUtil UTIL = new HBaseTestingUtil(); 068 069 // Static names for tables, columns, rows, and values 070 private static byte[] tableAname = Bytes.toBytes("tableA"); 071 private static byte[] familyAname = Bytes.toBytes("familyA"); 072 private static byte[] familyBname = Bytes.toBytes("familyB"); 073 private static byte[] qualifierAname = Bytes.toBytes("qualifierA"); 074 private static byte[] qualifierBname = Bytes.toBytes("qualifierB"); 075 private static byte[] valueAname = Bytes.toBytes("valueA"); 076 private static byte[] valueBname = Bytes.toBytes("valueB"); 077 private static ColumnFamilyDescriptor[] families = new ColumnFamilyDescriptor[] { 078 ColumnFamilyDescriptorBuilder.newBuilder(familyAname).setMaxVersions(3).build(), 079 ColumnFamilyDescriptorBuilder.newBuilder(familyBname).setMaxVersions(2).build() }; 080 081 @BeforeAll 082 public static void beforeClass() throws Exception { 083 UTIL.getConfiguration().setBoolean("hbase.thrift.readonly", true); 084 UTIL.getConfiguration().set("hbase.client.retries.number", "3"); 085 UTIL.startMiniCluster(); 086 Admin admin = UTIL.getAdmin(); 087 TableDescriptor tableDescriptor = TableDescriptorBuilder 088 .newBuilder(TableName.valueOf(tableAname)).setColumnFamilies(Arrays.asList(families)).build(); 089 admin.createTable(tableDescriptor); 090 admin.close(); 091 } 092 093 @AfterAll 094 public static void afterClass() throws Exception { 095 UTIL.shutdownMiniCluster(); 096 } 097 098 @BeforeEach 099 public void setup() throws Exception { 100 101 } 102 103 private ThriftHBaseServiceHandler createHandler() throws TException { 104 try { 105 Configuration conf = UTIL.getConfiguration(); 106 return new ThriftHBaseServiceHandler(conf, UserProvider.instantiate(conf)); 107 } catch (IOException ie) { 108 throw new TException(ie); 109 } 110 } 111 112 @Test 113 public void testExistsWithReadOnly() throws TException { 114 115 ThriftHBaseServiceHandler handler = createHandler(); 116 byte[] rowName = Bytes.toBytes("testExists"); 117 ByteBuffer table = wrap(tableAname); 118 TGet get = new TGet(wrap(rowName)); 119 120 boolean exceptionCaught = false; 121 try { 122 handler.exists(table, get); 123 } catch (TIOError e) { 124 exceptionCaught = true; 125 } finally { 126 assertFalse(exceptionCaught); 127 } 128 } 129 130 @Test 131 public void testExistsAllWithReadOnly() throws TException { 132 ThriftHBaseServiceHandler handler = createHandler(); 133 byte[] rowName1 = Bytes.toBytes("testExistsAll1"); 134 byte[] rowName2 = Bytes.toBytes("testExistsAll2"); 135 ByteBuffer table = wrap(tableAname); 136 137 List<TGet> gets = new ArrayList<>(); 138 gets.add(new TGet(wrap(rowName1))); 139 gets.add(new TGet(wrap(rowName2))); 140 141 boolean exceptionCaught = false; 142 try { 143 handler.existsAll(table, gets); 144 } catch (TIOError e) { 145 exceptionCaught = true; 146 } finally { 147 assertFalse(exceptionCaught); 148 } 149 } 150 151 @Test 152 public void testGetWithReadOnly() throws Exception { 153 ThriftHBaseServiceHandler handler = createHandler(); 154 byte[] rowName = Bytes.toBytes("testGet"); 155 ByteBuffer table = wrap(tableAname); 156 157 TGet get = new TGet(wrap(rowName)); 158 159 boolean exceptionCaught = false; 160 try { 161 handler.get(table, get); 162 } catch (TIOError e) { 163 exceptionCaught = true; 164 } finally { 165 assertFalse(exceptionCaught); 166 } 167 } 168 169 @Test 170 public void testGetMultipleWithReadOnly() throws Exception { 171 ThriftHBaseServiceHandler handler = createHandler(); 172 ByteBuffer table = wrap(tableAname); 173 byte[] rowName1 = Bytes.toBytes("testGetMultiple1"); 174 byte[] rowName2 = Bytes.toBytes("testGetMultiple2"); 175 176 List<TGet> gets = new ArrayList<>(2); 177 gets.add(new TGet(wrap(rowName1))); 178 gets.add(new TGet(wrap(rowName2))); 179 180 boolean exceptionCaught = false; 181 try { 182 handler.getMultiple(table, gets); 183 } catch (TIOError e) { 184 exceptionCaught = true; 185 } finally { 186 assertFalse(exceptionCaught); 187 } 188 } 189 190 @Test 191 public void testPutWithReadOnly() throws Exception { 192 ThriftHBaseServiceHandler handler = createHandler(); 193 ByteBuffer table = wrap(tableAname); 194 byte[] rowName = Bytes.toBytes("testPut"); 195 196 List<TColumnValue> columnValues = new ArrayList<>(2); 197 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 198 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 199 TPut put = new TPut(wrap(rowName), columnValues); 200 201 boolean exceptionCaught = false; 202 try { 203 handler.put(table, put); 204 } catch (TIOError e) { 205 exceptionCaught = true; 206 assertTrue(e.getCause() instanceof DoNotRetryIOException); 207 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 208 } finally { 209 assertTrue(exceptionCaught); 210 } 211 } 212 213 @Test 214 public void testCheckAndPutWithReadOnly() throws Exception { 215 ThriftHBaseServiceHandler handler = createHandler(); 216 byte[] rowName = Bytes.toBytes("testCheckAndPut"); 217 ByteBuffer table = wrap(tableAname); 218 219 List<TColumnValue> columnValuesA = new ArrayList<>(1); 220 TColumnValue columnValueA = 221 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 222 columnValuesA.add(columnValueA); 223 TPut putA = new TPut(wrap(rowName), columnValuesA); 224 putA.setColumnValues(columnValuesA); 225 226 List<TColumnValue> columnValuesB = new ArrayList<>(1); 227 TColumnValue columnValueB = 228 new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname)); 229 columnValuesB.add(columnValueB); 230 TPut putB = new TPut(wrap(rowName), columnValuesB); 231 putB.setColumnValues(columnValuesB); 232 233 boolean exceptionCaught = false; 234 try { 235 handler.checkAndPut(table, wrap(rowName), wrap(familyAname), wrap(qualifierAname), 236 wrap(valueAname), putB); 237 } catch (TIOError e) { 238 exceptionCaught = true; 239 assertTrue(e.getCause() instanceof DoNotRetryIOException); 240 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 241 } finally { 242 assertTrue(exceptionCaught); 243 } 244 } 245 246 @Test 247 public void testPutMultipleWithReadOnly() throws Exception { 248 ThriftHBaseServiceHandler handler = createHandler(); 249 ByteBuffer table = wrap(tableAname); 250 byte[] rowName1 = Bytes.toBytes("testPutMultiple1"); 251 byte[] rowName2 = Bytes.toBytes("testPutMultiple2"); 252 253 List<TColumnValue> columnValues = new ArrayList<>(2); 254 columnValues.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname))); 255 columnValues.add(new TColumnValue(wrap(familyBname), wrap(qualifierBname), wrap(valueBname))); 256 List<TPut> puts = new ArrayList<>(2); 257 puts.add(new TPut(wrap(rowName1), columnValues)); 258 puts.add(new TPut(wrap(rowName2), columnValues)); 259 260 boolean exceptionCaught = false; 261 try { 262 handler.putMultiple(table, puts); 263 } catch (TIOError e) { 264 exceptionCaught = true; 265 assertTrue(e.getCause() instanceof DoNotRetryIOException); 266 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 267 } finally { 268 assertTrue(exceptionCaught); 269 } 270 } 271 272 @Test 273 public void testDeleteWithReadOnly() throws Exception { 274 ThriftHBaseServiceHandler handler = createHandler(); 275 byte[] rowName = Bytes.toBytes("testDelete"); 276 ByteBuffer table = wrap(tableAname); 277 278 TDelete delete = new TDelete(wrap(rowName)); 279 280 boolean exceptionCaught = false; 281 try { 282 handler.deleteSingle(table, delete); 283 } catch (TIOError e) { 284 exceptionCaught = true; 285 assertTrue(e.getCause() instanceof DoNotRetryIOException); 286 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 287 } finally { 288 assertTrue(exceptionCaught); 289 } 290 } 291 292 @Test 293 public void testDeleteMultipleWithReadOnly() throws Exception { 294 ThriftHBaseServiceHandler handler = createHandler(); 295 ByteBuffer table = wrap(tableAname); 296 byte[] rowName1 = Bytes.toBytes("testDeleteMultiple1"); 297 byte[] rowName2 = Bytes.toBytes("testDeleteMultiple2"); 298 299 List<TDelete> deletes = new ArrayList<>(2); 300 deletes.add(new TDelete(wrap(rowName1))); 301 deletes.add(new TDelete(wrap(rowName2))); 302 303 boolean exceptionCaught = false; 304 try { 305 handler.deleteMultiple(table, deletes); 306 } catch (TIOError e) { 307 exceptionCaught = true; 308 assertTrue(e.getCause() instanceof DoNotRetryIOException); 309 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 310 } finally { 311 assertTrue(exceptionCaught); 312 } 313 } 314 315 @Test 316 public void testCheckAndMutateWithReadOnly() throws Exception { 317 ThriftHBaseServiceHandler handler = createHandler(); 318 ByteBuffer table = wrap(tableAname); 319 ByteBuffer row = wrap(Bytes.toBytes("row")); 320 ByteBuffer family = wrap(familyAname); 321 ByteBuffer qualifier = wrap(qualifierAname); 322 ByteBuffer value = wrap(valueAname); 323 324 List<TColumnValue> columnValuesB = new ArrayList<>(1); 325 TColumnValue columnValueB = new TColumnValue(family, wrap(qualifierBname), wrap(valueBname)); 326 columnValuesB.add(columnValueB); 327 TPut putB = new TPut(row, columnValuesB); 328 putB.setColumnValues(columnValuesB); 329 330 TRowMutations tRowMutations = 331 new TRowMutations(row, Arrays.<TMutation> asList(TMutation.put(putB))); 332 333 boolean exceptionCaught = false; 334 try { 335 handler.checkAndMutate(table, row, family, qualifier, TCompareOperator.EQUAL, value, 336 tRowMutations); 337 } catch (TIOError e) { 338 exceptionCaught = true; 339 assertTrue(e.getCause() instanceof DoNotRetryIOException); 340 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 341 } finally { 342 assertTrue(exceptionCaught); 343 } 344 } 345 346 @Test 347 public void testCheckAndDeleteWithReadOnly() throws Exception { 348 ThriftHBaseServiceHandler handler = createHandler(); 349 byte[] rowName = Bytes.toBytes("testCheckAndDelete"); 350 ByteBuffer table = wrap(tableAname); 351 352 TDelete delete = new TDelete(wrap(rowName)); 353 354 boolean exceptionCaught = false; 355 try { 356 handler.checkAndDelete(table, wrap(rowName), wrap(familyAname), wrap(qualifierAname), 357 wrap(valueAname), delete); 358 } catch (TIOError e) { 359 exceptionCaught = true; 360 assertTrue(e.getCause() instanceof DoNotRetryIOException); 361 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 362 } finally { 363 assertTrue(exceptionCaught); 364 } 365 } 366 367 @Test 368 public void testIncrementWithReadOnly() throws Exception { 369 ThriftHBaseServiceHandler handler = createHandler(); 370 byte[] rowName = Bytes.toBytes("testIncrement"); 371 ByteBuffer table = wrap(tableAname); 372 373 List<TColumnIncrement> incrementColumns = new ArrayList<>(1); 374 incrementColumns.add(new TColumnIncrement(wrap(familyAname), wrap(qualifierAname))); 375 TIncrement increment = new TIncrement(wrap(rowName), incrementColumns); 376 377 boolean exceptionCaught = false; 378 try { 379 handler.increment(table, increment); 380 } catch (TIOError e) { 381 exceptionCaught = true; 382 assertTrue(e.getCause() instanceof DoNotRetryIOException); 383 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 384 } finally { 385 assertTrue(exceptionCaught); 386 } 387 } 388 389 @Test 390 public void testAppendWithReadOnly() throws Exception { 391 ThriftHBaseServiceHandler handler = createHandler(); 392 byte[] rowName = Bytes.toBytes("testAppend"); 393 ByteBuffer table = wrap(tableAname); 394 byte[] v1 = Bytes.toBytes("42"); 395 396 List<TColumnValue> appendColumns = new ArrayList<>(1); 397 appendColumns.add(new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(v1))); 398 TAppend append = new TAppend(wrap(rowName), appendColumns); 399 400 boolean exceptionCaught = false; 401 try { 402 handler.append(table, append); 403 } catch (TIOError e) { 404 exceptionCaught = true; 405 assertTrue(e.getCause() instanceof DoNotRetryIOException); 406 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 407 } finally { 408 assertTrue(exceptionCaught); 409 } 410 } 411 412 @Test 413 public void testMutateRowWithReadOnly() throws Exception { 414 ThriftHBaseServiceHandler handler = createHandler(); 415 byte[] rowName = Bytes.toBytes("testMutateRow"); 416 ByteBuffer table = wrap(tableAname); 417 418 List<TColumnValue> columnValuesA = new ArrayList<>(1); 419 TColumnValue columnValueA = 420 new TColumnValue(wrap(familyAname), wrap(qualifierAname), wrap(valueAname)); 421 columnValuesA.add(columnValueA); 422 TPut putA = new TPut(wrap(rowName), columnValuesA); 423 putA.setColumnValues(columnValuesA); 424 425 TDelete delete = new TDelete(wrap(rowName)); 426 427 List<TMutation> mutations = new ArrayList<>(2); 428 TMutation mutationA = TMutation.put(putA); 429 mutations.add(mutationA); 430 TMutation mutationB = TMutation.deleteSingle(delete); 431 mutations.add(mutationB); 432 TRowMutations tRowMutations = new TRowMutations(wrap(rowName), mutations); 433 434 boolean exceptionCaught = false; 435 try { 436 handler.mutateRow(table, tRowMutations); 437 } catch (TIOError e) { 438 exceptionCaught = true; 439 assertTrue(e.getCause() instanceof DoNotRetryIOException); 440 assertEquals("Thrift Server is in Read-only mode.", e.getMessage()); 441 } finally { 442 assertTrue(exceptionCaught); 443 } 444 } 445 446 @Test 447 public void testScanWithReadOnly() throws Exception { 448 ThriftHBaseServiceHandler handler = createHandler(); 449 ByteBuffer table = wrap(tableAname); 450 451 TScan scan = new TScan(); 452 boolean exceptionCaught = false; 453 try { 454 int scanId = handler.openScanner(table, scan); 455 handler.getScannerRows(scanId, 10); 456 handler.closeScanner(scanId); 457 } catch (TIOError e) { 458 exceptionCaught = true; 459 } finally { 460 assertFalse(exceptionCaught); 461 } 462 } 463}