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