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.security.access; 019 020import static org.junit.jupiter.api.Assertions.assertThrows; 021import static org.mockito.Mockito.mock; 022 023import java.util.List; 024import java.util.Map; 025import java.util.Set; 026import org.apache.hadoop.hbase.NamespaceDescriptor; 027import org.apache.hadoop.hbase.TableName; 028import org.apache.hadoop.hbase.WriteAttemptedOnReadOnlyClusterException; 029import org.apache.hadoop.hbase.client.BalanceRequest; 030import org.apache.hadoop.hbase.client.Mutation; 031import org.apache.hadoop.hbase.client.RegionInfo; 032import org.apache.hadoop.hbase.client.SnapshotDescription; 033import org.apache.hadoop.hbase.client.TableDescriptor; 034import org.apache.hadoop.hbase.coprocessor.MasterCoprocessorEnvironment; 035import org.apache.hadoop.hbase.coprocessor.ObserverContext; 036import org.apache.hadoop.hbase.net.Address; 037import org.apache.hadoop.hbase.quotas.GlobalQuotaSettings; 038import org.apache.hadoop.hbase.replication.ReplicationPeerConfig; 039import org.apache.hadoop.hbase.replication.SyncReplicationState; 040import org.apache.hadoop.hbase.testclassification.SecurityTests; 041import org.apache.hadoop.hbase.testclassification.SmallTests; 042import org.apache.hadoop.hbase.util.Bytes; 043import org.junit.jupiter.api.AfterEach; 044import org.junit.jupiter.api.BeforeEach; 045import org.junit.jupiter.api.Tag; 046import org.junit.jupiter.api.Test; 047 048// Tests methods of Master Observer which are implemented in ReadOnlyController, 049// by mocking the coprocessor environment and dependencies 050 051@Tag(SecurityTests.TAG) 052@Tag(SmallTests.TAG) 053public class TestReadOnlyControllerMasterObserver { 054 055 MasterReadOnlyController MasterReadOnlyController; 056 057 // Master Coprocessor mocking variables 058 ObserverContext<MasterCoprocessorEnvironment> c, ctx; 059 TableDescriptor desc; 060 RegionInfo[] regions; 061 TableName tableName; 062 TableDescriptor currentDescriptor, newDescriptor; 063 String dstSFT; 064 byte[] family; 065 byte[] splitRow; 066 byte[] splitKey; 067 List<Mutation> metaEntries; 068 RegionInfo[] regionsToMerge; 069 SnapshotDescription snapshot; 070 TableDescriptor tableDescriptor; 071 NamespaceDescriptor ns; 072 NamespaceDescriptor currentNsDescriptor, newNsDescriptor; 073 String namespace; 074 String userName; 075 GlobalQuotaSettings quotas; 076 String regionServer; 077 Set<Address> servers; 078 Set<TableName> tables; 079 String targetGroup; 080 String name; 081 String groupName; 082 BalanceRequest request; 083 String oldName, newName; 084 Map<String, String> configuration; 085 String peerId; 086 ReplicationPeerConfig peerConfig; 087 SyncReplicationState state; 088 UserPermission userPermission; 089 boolean mergeExistingPermissions; 090 091 @BeforeEach 092 public void setup() throws Exception { 093 MasterReadOnlyController = new MasterReadOnlyController(); 094 095 // mocking variables initialization 096 c = mock(ObserverContext.class); 097 // ctx is created to make naming variable in sync with the Observer interface 098 // methods where 'ctx' is used as the ObserverContext variable name instead of 'c'. 099 // otherwise both are one and the same 100 ctx = c; 101 desc = mock(TableDescriptor.class); 102 regions = new RegionInfo[] {}; 103 tableName = TableName.valueOf("testTable"); 104 currentDescriptor = mock(TableDescriptor.class); 105 newDescriptor = mock(TableDescriptor.class); 106 dstSFT = "dstSFT"; 107 family = Bytes.toBytes("testFamily"); 108 splitRow = Bytes.toBytes("splitRow"); 109 splitKey = Bytes.toBytes("splitKey"); 110 metaEntries = List.of(); 111 regionsToMerge = new RegionInfo[] {}; 112 snapshot = mock(SnapshotDescription.class); 113 tableDescriptor = mock(TableDescriptor.class); 114 ns = mock(NamespaceDescriptor.class); 115 currentNsDescriptor = mock(NamespaceDescriptor.class); 116 newNsDescriptor = mock(NamespaceDescriptor.class); 117 namespace = "testNamespace"; 118 userName = "testUser"; 119 quotas = mock(GlobalQuotaSettings.class); 120 regionServer = "testRegionServer"; 121 servers = Set.of(); 122 tables = Set.of(); 123 targetGroup = "targetGroup"; 124 name = "testRSGroup"; 125 groupName = "testGroupName"; 126 request = BalanceRequest.newBuilder().build(); 127 oldName = "oldRSGroupName"; 128 newName = "newRSGroupName"; 129 configuration = Map.of(); 130 peerId = "testPeerId"; 131 peerConfig = mock(ReplicationPeerConfig.class); 132 state = SyncReplicationState.NONE; 133 userPermission = mock(UserPermission.class); 134 mergeExistingPermissions = false; 135 136 // Linking the mocks: 137 } 138 139 @AfterEach 140 public void tearDown() throws Exception { 141 142 } 143 144 @Test 145 public void testPreCreateTableRegionsInfosReadOnlyException() { 146 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 147 MasterReadOnlyController.preCreateTableRegionsInfos(ctx, desc); 148 }); 149 } 150 151 @Test 152 public void testPreCreateTableReadOnlyException() { 153 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 154 MasterReadOnlyController.preCreateTable(ctx, desc, regions); 155 }); 156 } 157 158 @Test 159 public void testPreCreateTableActionReadOnlyException() { 160 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 161 MasterReadOnlyController.preCreateTableAction(ctx, desc, regions); 162 }); 163 } 164 165 @Test 166 public void testPreDeleteTableReadOnlyException() { 167 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 168 MasterReadOnlyController.preDeleteTable(ctx, tableName); 169 }); 170 } 171 172 @Test 173 public void testPreDeleteTableActionReadOnlyException() { 174 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 175 MasterReadOnlyController.preDeleteTableAction(ctx, tableName); 176 }); 177 } 178 179 @Test 180 public void testPreTruncateTableReadOnlyException() { 181 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 182 MasterReadOnlyController.preTruncateTable(ctx, tableName); 183 }); 184 } 185 186 @Test 187 public void testPreTruncateTableActionReadOnlyException() { 188 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 189 MasterReadOnlyController.preTruncateTableAction(ctx, tableName); 190 }); 191 } 192 193 @Test 194 public void testPreModifyTableReadOnlyException() { 195 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 196 MasterReadOnlyController.preModifyTable(ctx, tableName, currentDescriptor, newDescriptor); 197 }); 198 } 199 200 @Test 201 public void testPreModifyTableStoreFileTrackerReadOnlyException() { 202 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 203 MasterReadOnlyController.preModifyTableStoreFileTracker(ctx, tableName, dstSFT); 204 }); 205 } 206 207 @Test 208 public void testPreModifyColumnFamilyStoreFileTrackerReadOnlyException() { 209 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 210 MasterReadOnlyController.preModifyColumnFamilyStoreFileTracker(ctx, tableName, family, 211 dstSFT); 212 }); 213 } 214 215 @Test 216 public void testPreModifyTableActionReadOnlyException() { 217 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 218 MasterReadOnlyController.preModifyTableAction(ctx, tableName, currentDescriptor, 219 newDescriptor); 220 }); 221 } 222 223 @Test 224 public void testPreSplitRegionReadOnlyException() { 225 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 226 MasterReadOnlyController.preSplitRegion(c, tableName, splitRow); 227 }); 228 } 229 230 @Test 231 public void testPreSplitRegionActionReadOnlyException() { 232 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 233 MasterReadOnlyController.preSplitRegionAction(c, tableName, splitRow); 234 }); 235 } 236 237 @Test 238 public void testPreSplitRegionBeforeMETAActionReadOnlyException() { 239 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 240 MasterReadOnlyController.preSplitRegionBeforeMETAAction(ctx, splitKey, metaEntries); 241 }); 242 } 243 244 @Test 245 public void testPreSplitRegionAfterMETAActionReadOnlyException() { 246 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 247 MasterReadOnlyController.preSplitRegionAfterMETAAction(ctx); 248 }); 249 } 250 251 @Test 252 public void testPreMergeRegionsActionReadOnlyException() { 253 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 254 MasterReadOnlyController.preMergeRegionsAction(ctx, regionsToMerge); 255 }); 256 } 257 258 @Test 259 public void testPreMergeRegionsCommitActionReadOnlyException() { 260 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 261 MasterReadOnlyController.preMergeRegionsCommitAction(ctx, regionsToMerge, metaEntries); 262 }); 263 } 264 265 @Test 266 public void testPreSnapshotReadOnlyException() { 267 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 268 MasterReadOnlyController.preSnapshot(ctx, snapshot, tableDescriptor); 269 }); 270 } 271 272 @Test 273 public void testPreCloneSnapshotReadOnlyException() { 274 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 275 MasterReadOnlyController.preCloneSnapshot(ctx, snapshot, tableDescriptor); 276 }); 277 } 278 279 @Test 280 public void testPreRestoreSnapshotReadOnlyException() { 281 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 282 MasterReadOnlyController.preRestoreSnapshot(ctx, snapshot, tableDescriptor); 283 }); 284 } 285 286 @Test 287 public void testPreDeleteSnapshotReadOnlyException() { 288 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 289 MasterReadOnlyController.preDeleteSnapshot(ctx, snapshot); 290 }); 291 } 292 293 @Test 294 public void testPreCreateNamespaceReadOnlyException() { 295 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 296 MasterReadOnlyController.preCreateNamespace(ctx, ns); 297 }); 298 } 299 300 @Test 301 public void testPreModifyNamespaceReadOnlyException() { 302 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 303 MasterReadOnlyController.preModifyNamespace(ctx, currentNsDescriptor, newNsDescriptor); 304 }); 305 } 306 307 @Test 308 public void testPreDeleteNamespaceReadOnlyException() { 309 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 310 MasterReadOnlyController.preDeleteNamespace(ctx, namespace); 311 }); 312 } 313 314 @Test 315 public void testPreMasterStoreFlushReadOnlyException() { 316 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 317 MasterReadOnlyController.preMasterStoreFlush(ctx); 318 }); 319 } 320 321 @Test 322 public void testPreSetUserQuotaReadOnlyException() { 323 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 324 MasterReadOnlyController.preSetUserQuota(ctx, userName, quotas); 325 }); 326 } 327 328 @Test 329 public void testPreSetUserQuotaOnTableReadOnlyException() { 330 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 331 MasterReadOnlyController.preSetUserQuota(ctx, userName, tableName, quotas); 332 }); 333 } 334 335 @Test 336 public void testPreSetUserQuotaOnNamespaceReadOnlyException() { 337 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 338 MasterReadOnlyController.preSetUserQuota(ctx, userName, namespace, quotas); 339 }); 340 } 341 342 @Test 343 public void testPreSetTableQuotaReadOnlyException() { 344 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 345 MasterReadOnlyController.preSetTableQuota(ctx, tableName, quotas); 346 }); 347 } 348 349 @Test 350 public void testPreSetNamespaceQuotaReadOnlyException() { 351 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 352 MasterReadOnlyController.preSetNamespaceQuota(ctx, namespace, quotas); 353 }); 354 } 355 356 @Test 357 public void testPreSetRegionServerQuotaReadOnlyException() { 358 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 359 MasterReadOnlyController.preSetRegionServerQuota(ctx, regionServer, quotas); 360 }); 361 } 362 363 @Test 364 public void testPreMergeRegionsReadOnlyException() { 365 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 366 MasterReadOnlyController.preMergeRegions(ctx, regionsToMerge); 367 }); 368 } 369 370 @Test 371 public void testPreMoveServersAndTablesReadOnlyException() { 372 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 373 MasterReadOnlyController.preMoveServersAndTables(ctx, servers, tables, targetGroup); 374 }); 375 } 376 377 @Test 378 public void testPreMoveServersReadOnlyException() { 379 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 380 MasterReadOnlyController.preMoveServers(ctx, servers, targetGroup); 381 }); 382 } 383 384 @Test 385 public void testPreMoveTablesReadOnlyException() { 386 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 387 MasterReadOnlyController.preMoveTables(ctx, tables, targetGroup); 388 }); 389 } 390 391 @Test 392 public void testPreAddRSGroupReadOnlyException() { 393 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 394 MasterReadOnlyController.preAddRSGroup(ctx, name); 395 }); 396 } 397 398 @Test 399 public void testPreRemoveRSGroupReadOnlyException() { 400 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 401 MasterReadOnlyController.preRemoveRSGroup(ctx, name); 402 }); 403 } 404 405 @Test 406 public void testPreBalanceRSGroupReadOnlyException() { 407 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 408 MasterReadOnlyController.preBalanceRSGroup(ctx, groupName, request); 409 }); 410 } 411 412 @Test 413 public void testPreRemoveServersReadOnlyException() { 414 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 415 MasterReadOnlyController.preRemoveServers(ctx, servers); 416 }); 417 } 418 419 @Test 420 public void testPreRenameRSGroupReadOnlyException() { 421 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 422 MasterReadOnlyController.preRenameRSGroup(ctx, oldName, newName); 423 }); 424 } 425 426 @Test 427 public void testPreUpdateRSGroupConfigReadOnlyException() { 428 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 429 MasterReadOnlyController.preUpdateRSGroupConfig(ctx, groupName, configuration); 430 }); 431 } 432 433 @Test 434 public void testPreAddReplicationPeerReadOnlyException() { 435 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 436 MasterReadOnlyController.preAddReplicationPeer(ctx, peerId, peerConfig); 437 }); 438 } 439 440 @Test 441 public void testPreRemoveReplicationPeerReadOnlyException() { 442 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 443 MasterReadOnlyController.preRemoveReplicationPeer(ctx, peerId); 444 }); 445 } 446 447 @Test 448 public void testPreEnableReplicationPeerReadOnlyException() { 449 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 450 MasterReadOnlyController.preEnableReplicationPeer(ctx, peerId); 451 }); 452 } 453 454 @Test 455 public void testPreDisableReplicationPeerReadOnlyException() { 456 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 457 MasterReadOnlyController.preDisableReplicationPeer(ctx, peerId); 458 }); 459 } 460 461 @Test 462 public void testPreUpdateReplicationPeerConfigReadOnlyException() { 463 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 464 MasterReadOnlyController.preUpdateReplicationPeerConfig(ctx, peerId, peerConfig); 465 }); 466 } 467 468 @Test 469 public void testPreTransitReplicationPeerSyncReplicationStateReadOnlyException() { 470 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 471 MasterReadOnlyController.preTransitReplicationPeerSyncReplicationState(ctx, peerId, state); 472 }); 473 } 474 475 @Test 476 public void testPreGrantReadOnlyException() { 477 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 478 MasterReadOnlyController.preGrant(ctx, userPermission, mergeExistingPermissions); 479 }); 480 } 481 482 @Test 483 public void testPreRevokeReadOnlyException() { 484 assertThrows(WriteAttemptedOnReadOnlyClusterException.class, () -> { 485 MasterReadOnlyController.preRevoke(ctx, userPermission); 486 }); 487 } 488}