2121import static io .grpc .Status .Code .NOT_FOUND ;
2222import static org .junit .Assert .fail ;
2323
24- import com .google .api .core .ApiFuture ;
25- import com .google .api .core .ApiFutures ;
24+ import com .google .api .gax .batching .Batcher ;
2625import com .google .api .gax .rpc .ApiException ;
2726import com .google .cloud .Policy ;
2827import com .google .cloud .bigtable .admin .v2 .BigtableInstanceAdminClient ;
3837import com .google .cloud .bigtable .admin .v2 .models .Table ;
3938import com .google .cloud .bigtable .admin .v2 .models .UpdateBackupRequest ;
4039import com .google .cloud .bigtable .data .v2 .BigtableDataClient ;
41- import com .google .cloud .bigtable .data .v2 .models .RowMutation ;
42- import com .google .cloud .bigtable .test_helpers .env .AbstractTestEnv ;
40+ import com .google .cloud .bigtable .data .v2 .models .RowMutationEntry ;
4341import com .google .cloud .bigtable .test_helpers .env .EmulatorEnv ;
4442import com .google .cloud .bigtable .test_helpers .env .TestEnvRule ;
45- import com .google .common .collect . Lists ;
43+ import com .google .common .base . Stopwatch ;
4644import com .google .protobuf .ByteString ;
4745import io .grpc .StatusRuntimeException ;
4846import java .io .IOException ;
5250import java .util .concurrent .TimeUnit ;
5351import java .util .concurrent .TimeoutException ;
5452import java .util .logging .Logger ;
55- import org .junit .*;
53+ import org .junit .AfterClass ;
54+ import org .junit .BeforeClass ;
55+ import org .junit .ClassRule ;
56+ import org .junit .Test ;
5657import org .junit .runner .RunWith ;
5758import org .junit .runners .JUnit4 ;
5859import org .threeten .bp .Duration ;
5960import org .threeten .bp .Instant ;
6061
6162@ RunWith (JUnit4 .class )
6263public class BigtableBackupIT {
63- @ ClassRule public static TestEnvRule testEnvRule = new TestEnvRule ();
64+ @ ClassRule public static final TestEnvRule testEnvRule = new TestEnvRule ();
6465
6566 private static final Logger LOGGER = Logger .getLogger (BigtableBackupIT .class .getName ());
6667
6768 private static final int [] BACKOFF_DURATION = {2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 , 1024 };
6869
69- private static final String TEST_TABLE_SUFFIX = "test-table-for-backup-it" ;
70- private static final String TEST_BACKUP_SUFFIX = "test-backup-for-backup-it" ;
71-
7270 private static BigtableTableAdminClient tableAdmin ;
7371 private static BigtableInstanceAdminClient instanceAdmin ;
7472 private static BigtableDataClient dataClient ;
7573
76- private static String targetInstance ;
7774 private static String targetCluster ;
7875 private static Table testTable ;
79- private static String prefix ;
8076
8177 @ BeforeClass
82- public static void createClient ()
83- throws IOException , InterruptedException , ExecutionException , TimeoutException {
78+ public static void setUpClass () throws InterruptedException {
8479 assume ()
8580 .withMessage ("BigtableInstanceAdminClient is not supported on Emulator" )
8681 .that (testEnvRule .env ())
8782 .isNotInstanceOf (EmulatorEnv .class );
8883
84+ tableAdmin = testEnvRule .env ().getTableAdminClient ();
8985 instanceAdmin = testEnvRule .env ().getInstanceAdminClient ();
86+ dataClient = testEnvRule .env ().getDataClient ();
9087
91- targetCluster = AbstractTestEnv .TEST_CLUSTER_PREFIX + Instant .now ().getEpochSecond ();
92- targetInstance =
93- AbstractTestEnv .TEST_INSTANCE_PREFIX + "backup-" + Instant .now ().getEpochSecond ();
94-
95- instanceAdmin .createInstance (
96- CreateInstanceRequest .of (targetInstance )
97- .addCluster (targetCluster , testEnvRule .env ().getPrimaryZone (), 3 , StorageType .SSD )
98- .setDisplayName ("backups-test-instance" )
99- .addLabel ("state" , "readytodelete" )
100- .setType (Type .PRODUCTION ));
101-
102- // Setup a prefix to avoid collisions between concurrent test runs
103- prefix = String .format ("020%d" , System .currentTimeMillis ());
104-
105- tableAdmin = testEnvRule .env ().getTableAdminClientForInstance (targetInstance );
106- dataClient = testEnvRule .env ().getDataClientForInstance (targetInstance );
107-
88+ targetCluster = testEnvRule .env ().getPrimaryClusterId ();
10889 testTable = createAndPopulateTestTable (tableAdmin , dataClient );
10990 }
11091
11192 @ AfterClass
112- public static void closeClient () {
93+ public static void tearDownClass () {
11394 if (testTable != null ) {
11495 try {
11596 tableAdmin .deleteTable (testTable .getId ());
11697 } catch (Exception e ) {
11798 // Ignore.
11899 }
119100 }
120-
121- if (targetInstance != null ) {
122- instanceAdmin .deleteInstance (targetInstance );
123- }
124-
125- if (tableAdmin != null ) {
126- tableAdmin .close ();
127- }
128-
129- if (dataClient != null ) {
130- dataClient .close ();
131- }
132- }
133-
134- @ Before
135- public void setup () {
136- if (tableAdmin == null ) {
137- throw new AssumptionViolatedException (
138- "Required properties are not set, skipping integration tests." );
139- }
140101 }
141102
142103 @ Test
143- public void createAndGetBackupTest () throws InterruptedException {
144- Instant expireTime = Instant .now ().plus (Duration .ofDays (15 ));
145- String backupId = generateId (TEST_BACKUP_SUFFIX );
104+ public void createAndGetBackupTest () {
105+ String backupId = testEnvRule .env ().newPrefix ();
106+ Instant expireTime = Instant .now ().plus (Duration .ofHours (6 ));
107+
146108 CreateBackupRequest request =
147109 CreateBackupRequest .of (targetCluster , backupId )
148110 .setSourceTableId (testTable .getId ())
@@ -185,9 +147,9 @@ public void createAndGetBackupTest() throws InterruptedException {
185147 }
186148
187149 @ Test
188- public void listBackupTest () throws InterruptedException {
189- String backupId1 = generateId ( "list-1-" + TEST_BACKUP_SUFFIX );
190- String backupId2 = generateId ( "list-2-" + TEST_BACKUP_SUFFIX );
150+ public void listBackupTest () {
151+ String backupId1 = testEnvRule . env (). newPrefix ( );
152+ String backupId2 = testEnvRule . env (). newPrefix ( );
191153
192154 try {
193155 tableAdmin .createBackup (createBackupRequest (backupId1 ));
@@ -206,8 +168,8 @@ public void listBackupTest() throws InterruptedException {
206168 }
207169
208170 @ Test
209- public void updateBackupTest () throws InterruptedException {
210- String backupId = generateId ( "update-" + TEST_BACKUP_SUFFIX );
171+ public void updateBackupTest () {
172+ String backupId = testEnvRule . env (). newPrefix ( );
211173 tableAdmin .createBackup (createBackupRequest (backupId ));
212174
213175 Instant expireTime = Instant .now ().plus (Duration .ofDays (20 ));
@@ -223,7 +185,7 @@ public void updateBackupTest() throws InterruptedException {
223185
224186 @ Test
225187 public void deleteBackupTest () throws InterruptedException {
226- String backupId = generateId ( "delete-" + TEST_BACKUP_SUFFIX );
188+ String backupId = testEnvRule . env (). newPrefix ( );
227189
228190 tableAdmin .createBackup (createBackupRequest (backupId ));
229191 tableAdmin .deleteBackup (targetCluster , backupId );
@@ -248,8 +210,8 @@ public void deleteBackupTest() throws InterruptedException {
248210
249211 @ Test
250212 public void restoreTableTest () throws InterruptedException , ExecutionException {
251- String backupId = generateId ( "restore-" + TEST_BACKUP_SUFFIX );
252- String restoredTableId = generateId ( "restored-table" ) ;
213+ String backupId = testEnvRule . env (). newPrefix ( );
214+ String restoredTableId = testEnvRule . env (). newPrefix () + "-restore" ;
253215 tableAdmin .createBackup (createBackupRequest (backupId ));
254216
255217 // Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
@@ -282,62 +244,65 @@ public void restoreTableTest() throws InterruptedException, ExecutionException {
282244 @ Test
283245 public void crossInstanceRestoreTest ()
284246 throws InterruptedException , IOException , ExecutionException , TimeoutException {
285- String backupId = generateId ("cross-" + TEST_BACKUP_SUFFIX );
286- String restoredTableId = generateId ("restored-table-2" );
287-
288- // Set up a new instance to test cross-instance restore. The source backup is stored in this
289- // instance.
290- String sourceInstance =
291- AbstractTestEnv .TEST_INSTANCE_PREFIX + "backup-" + Instant .now ().getEpochSecond ();
292- String sourceCluster = AbstractTestEnv .TEST_CLUSTER_PREFIX + Instant .now ().getEpochSecond ();
247+ String backupId = testEnvRule .env ().newPrefix ();
248+ String restoredTableId = testEnvRule .env ().newPrefix ();
249+
250+ // Create the backup
251+ tableAdmin .createBackup (
252+ CreateBackupRequest .of (targetCluster , backupId )
253+ .setSourceTableId (testTable .getId ())
254+ .setExpireTime (Instant .now ().plus (Duration .ofHours (6 ))));
255+
256+ Stopwatch stopwatch = Stopwatch .createStarted ();
257+
258+ // Set up a new instance to test cross-instance restore. The backup will be restored here
259+ String targetInstance = testEnvRule .env ().newPrefix ();
293260 instanceAdmin .createInstance (
294- CreateInstanceRequest .of (sourceInstance )
295- .addCluster (sourceCluster , testEnvRule .env ().getSecondaryZone (), 3 , StorageType .SSD )
296- .setDisplayName ("backups-source -test-instance" )
261+ CreateInstanceRequest .of (targetInstance )
262+ .addCluster (targetInstance , testEnvRule .env ().getSecondaryZone (), 1 , StorageType .SSD )
263+ .setDisplayName ("backups-dest -test-instance" )
297264 .addLabel ("state" , "readytodelete" )
298265 .setType (Type .PRODUCTION ));
299- BigtableTableAdminClient sourceTableAdmin =
300- testEnvRule .env ().getTableAdminClientForInstance (sourceInstance );
301- Table sourceTable =
302- createAndPopulateTestTable (
303- sourceTableAdmin , testEnvRule .env ().getDataClientForInstance (sourceInstance ));
304- sourceTableAdmin .createBackup (
305- CreateBackupRequest .of (sourceCluster , backupId )
306- .setSourceTableId (sourceTable .getId ())
307- .setExpireTime (Instant .now ().plus (Duration .ofHours (6 ))));
308266
309- // Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
310- // table operation.
311- Thread .sleep (120 * 1000 );
267+ try (BigtableTableAdminClient destTableAdmin =
268+ testEnvRule .env ().getTableAdminClientForInstance (targetInstance )) {
312269
313- try {
314- RestoreTableRequest req =
315- RestoreTableRequest .of (sourceInstance , sourceCluster , backupId )
316- .setTableId (restoredTableId );
317- RestoredTableResult result = tableAdmin .restoreTable (req );
318- assertWithMessage ("Incorrect restored table id" )
319- .that (result .getTable ().getId ())
320- .isEqualTo (restoredTableId );
321- assertWithMessage ("Incorrect instance id" )
322- .that (result .getTable ().getInstanceId ())
323- .isEqualTo (targetInstance );
324-
325- // The assertion might be missing if the test is running against a HDD cluster or an
326- // optimization is not necessary.
327- assertWithMessage ("Empty OptimizeRestoredTable token" )
328- .that (result .getOptimizeRestoredTableOperationToken ())
329- .isNotNull ();
330- tableAdmin .awaitOptimizeRestoredTable (result .getOptimizeRestoredTableOperationToken ());
331- tableAdmin .getTable (restoredTableId );
332- } finally {
333- sourceTableAdmin .deleteBackup (sourceCluster , backupId );
334- instanceAdmin .deleteInstance (sourceInstance );
270+ // Wait 2 minutes so that the RestoreTable API will trigger an optimize restored
271+ // table operation.
272+ Thread .sleep (
273+ Duration .ofMinutes (2 )
274+ .minus (Duration .ofMillis (stopwatch .elapsed (TimeUnit .MILLISECONDS )))
275+ .toMillis ());
276+
277+ try {
278+ RestoreTableRequest req =
279+ RestoreTableRequest .of (testEnvRule .env ().getInstanceId (), targetCluster , backupId )
280+ .setTableId (restoredTableId );
281+ RestoredTableResult result = destTableAdmin .restoreTable (req );
282+ assertWithMessage ("Incorrect restored table id" )
283+ .that (result .getTable ().getId ())
284+ .isEqualTo (restoredTableId );
285+ assertWithMessage ("Incorrect instance id" )
286+ .that (result .getTable ().getInstanceId ())
287+ .isEqualTo (targetInstance );
288+
289+ // The assertion might be missing if the test is running against a HDD cluster or an
290+ // optimization is not necessary.
291+ assertWithMessage ("Empty OptimizeRestoredTable token" )
292+ .that (result .getOptimizeRestoredTableOperationToken ())
293+ .isNotNull ();
294+ destTableAdmin .awaitOptimizeRestoredTable (result .getOptimizeRestoredTableOperationToken ());
295+ destTableAdmin .getTable (restoredTableId );
296+ } finally {
297+ tableAdmin .deleteBackup (targetCluster , backupId );
298+ instanceAdmin .deleteInstance (targetInstance );
299+ }
335300 }
336301 }
337302
338303 @ Test
339- public void backupIamTest () throws InterruptedException {
340- String backupId = generateId ( "iam-" + TEST_BACKUP_SUFFIX );
304+ public void backupIamTest () {
305+ String backupId = testEnvRule . env (). newPrefix ( );
341306
342307 try {
343308 tableAdmin .createBackup (createBackupRequest (backupId ));
@@ -373,31 +338,24 @@ private CreateBackupRequest createBackupRequest(String backupId) {
373338 .setExpireTime (Instant .now ().plus (Duration .ofDays (15 )));
374339 }
375340
376- private static String generateId (String name ) {
377- return prefix + "-" + name ;
378- }
379-
380341 private static Table createAndPopulateTestTable (
381342 BigtableTableAdminClient tableAdmin , BigtableDataClient dataClient )
382- throws InterruptedException , ExecutionException , TimeoutException {
383- Table testTable =
384- tableAdmin .createTable (
385- CreateTableRequest .of (generateId (TEST_TABLE_SUFFIX )).addFamily ("cf1" ));
343+ throws InterruptedException {
344+ String tableId = testEnvRule .env ().newPrefix ();
345+ Table testTable = tableAdmin .createTable (CreateTableRequest .of (tableId ).addFamily ("cf1" ));
386346
387347 // Populate test data.
388348 byte [] rowBytes = new byte [1024 ];
389349 Random random = new Random ();
390350 random .nextBytes (rowBytes );
391351
392- List <ApiFuture <?>> futures = Lists .newArrayList ();
393- for (int i = 0 ; i < 10 ; i ++) {
394- ApiFuture <Void > future =
395- dataClient .mutateRowAsync (
396- RowMutation .create (testTable .getId (), "test-row-" + i )
397- .setCell ("cf1" , ByteString .EMPTY , ByteString .copyFrom (rowBytes )));
398- futures .add (future );
352+ try (Batcher <RowMutationEntry , Void > batcher = dataClient .newBulkMutationBatcher (tableId )) {
353+ for (int i = 0 ; i < 10 ; i ++) {
354+ batcher .add (
355+ RowMutationEntry .create ("test-row-" + i )
356+ .setCell ("cf1" , ByteString .EMPTY , ByteString .copyFrom (rowBytes )));
357+ }
399358 }
400- ApiFutures .allAsList (futures ).get (3 , TimeUnit .MINUTES );
401359 return testTable ;
402360 }
403361}
0 commit comments