Skip to content

Commit c16bb4c

Browse files
feat(compute): add compute disk create with snapshot schedule (GoogleCloudPlatform#9788)
* Implemented compute_disk_create_with_snapshot_schedule sample, created test * Fixed code * Fixed code * Fixed test * Fixed code * Fixed code as requested in the comments * Fixed lint issue * Fixed lint issue * Deleted redundant code
1 parent f328675 commit c16bb4c

File tree

3 files changed

+139
-11
lines changed

3 files changed

+139
-11
lines changed
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
* Copyright 2024 Google LLC
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package compute.disks;
18+
19+
// [START compute_disk_create_with_snapshot_schedule]
20+
import com.google.cloud.compute.v1.Disk;
21+
import com.google.cloud.compute.v1.DisksClient;
22+
import com.google.cloud.compute.v1.Operation;
23+
import com.google.cloud.compute.v1.Operation.Status;
24+
import java.io.IOException;
25+
import java.util.List;
26+
import java.util.concurrent.ExecutionException;
27+
import java.util.concurrent.TimeUnit;
28+
import java.util.concurrent.TimeoutException;
29+
30+
public class CreateDiskWithSnapshotSchedule {
31+
public static void main(String[] args)
32+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
33+
// TODO(developer): Replace these variables before running the sample.
34+
// Project ID or project number of the Cloud project you want to use.
35+
String projectId = "YOUR_PROJECT_ID";
36+
// Name of the zone in which you want to create the disk.
37+
String zone = "us-central1-a";
38+
// Name of the disk you want to create.
39+
String diskName = "YOUR_DISK_NAME";
40+
// Name of the schedule you want to link to the disk.
41+
String snapshotScheduleName = "YOUR_SCHEDULE_NAME";
42+
43+
createDiskWithSnapshotSchedule(projectId, zone, diskName, snapshotScheduleName);
44+
}
45+
46+
// Creates disk with linked snapshot schedule.
47+
public static Status createDiskWithSnapshotSchedule(
48+
String projectId, String zone, String diskName, String snapshotScheduleName)
49+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
50+
// Initialize client that will be used to send requests. This client only needs to be created
51+
// once, and can be reused for multiple requests.
52+
try (DisksClient disksClient = DisksClient.create()) {
53+
String region = zone.substring(0, zone.lastIndexOf('-'));
54+
// Get the resource policy to link to the disk
55+
String resourcePolicyLink = String.format("projects/%s/regions/%s/resourcePolicies/%s",
56+
projectId, region, snapshotScheduleName);
57+
58+
Disk disk = Disk.newBuilder()
59+
.setName(diskName)
60+
.setZone(zone)
61+
.addAllResourcePolicies(List.of(resourcePolicyLink))
62+
.build();
63+
64+
Operation response = disksClient.insertAsync(projectId, zone, disk).get(3, TimeUnit.MINUTES);
65+
66+
if (response.hasError()) {
67+
throw new Error("Disk creation failed! " + response.getError());
68+
}
69+
return response.getStatus();
70+
}
71+
}
72+
}
73+
// [END compute_disk_create_with_snapshot_schedule]

compute/cloud-client/src/test/java/compute/Util.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import com.google.cloud.compute.v1.RegionInstanceTemplatesClient;
3131
import com.google.cloud.compute.v1.Reservation;
3232
import com.google.cloud.compute.v1.ReservationsClient;
33+
import com.google.cloud.compute.v1.ResourcePoliciesClient;
34+
import com.google.cloud.compute.v1.ResourcePolicy;
3335
import com.google.cloud.compute.v1.Snapshot;
3436
import com.google.cloud.compute.v1.SnapshotsClient;
3537
import com.google.cloud.compute.v1.StoragePool;
@@ -39,7 +41,9 @@
3941
import compute.disks.DeleteSnapshot;
4042
import compute.disks.RegionalDelete;
4143
import compute.reservation.DeleteReservation;
44+
import compute.snapshotschedule.DeleteSnapshotSchedule;
4245
import java.io.IOException;
46+
import java.lang.Error;
4347
import java.nio.charset.StandardCharsets;
4448
import java.security.SecureRandom;
4549
import java.time.Instant;
@@ -283,6 +287,21 @@ public static void deleteStoragePool(String project, String zone, String storage
283287
}
284288
}
285289

290+
// Delete snapshot schedule which starts with the given prefixToDelete and
291+
// has creation timestamp >24 hours.
292+
public static void cleanUpExistingSnapshotSchedule(
293+
String prefixToDelete, String projectId, String region)
294+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
295+
try (ResourcePoliciesClient resourcePoliciesClient = ResourcePoliciesClient.create()) {
296+
for (ResourcePolicy resource : resourcePoliciesClient.list(projectId, region).iterateAll()) {
297+
if (containPrefixToDeleteAndZone(resource, prefixToDelete, region)
298+
&& isCreatedBeforeThresholdTime(resource.getCreationTimestamp())) {
299+
DeleteSnapshotSchedule.deleteSnapshotSchedule(projectId, region, resource.getName());
300+
}
301+
}
302+
}
303+
}
304+
286305
public static boolean containPrefixToDeleteAndZone(
287306
Object resource, String prefixToDelete, String zone) {
288307
boolean containPrefixAndZone = false;
@@ -308,6 +327,11 @@ public static boolean containPrefixToDeleteAndZone(
308327
containPrefixAndZone = ((StoragePool) resource).getName().contains(prefixToDelete)
309328
&& ((StoragePool) resource).getZone().contains(zone);
310329
}
330+
if (resource instanceof ResourcePolicy) {
331+
containPrefixAndZone = ((ResourcePolicy) resource).getName().contains(prefixToDelete)
332+
&& ((ResourcePolicy) resource).getRegion()
333+
.contains(zone.substring(0, zone.lastIndexOf('-')));
334+
}
311335
} catch (NullPointerException e) {
312336
System.out.println("Resource not found, skipping deletion:");
313337
}

compute/cloud-client/src/test/java/compute/disks/DisksIT.java

Lines changed: 42 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import static com.google.common.truth.Truth.assertThat;
2020
import static com.google.common.truth.Truth.assertWithMessage;
2121
import static org.junit.Assert.assertEquals;
22+
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
2223

2324
import com.google.cloud.compute.v1.AttachedDisk;
2425
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
@@ -37,6 +38,8 @@
3738
import com.google.cloud.compute.v1.SnapshotsClient;
3839
import compute.DeleteInstance;
3940
import compute.Util;
41+
import compute.snapshotschedule.CreateSnapshotSchedule;
42+
import compute.snapshotschedule.DeleteSnapshotSchedule;
4043
import java.io.ByteArrayOutputStream;
4144
import java.io.IOException;
4245
import java.io.PrintStream;
@@ -81,7 +84,8 @@ public class DisksIT {
8184
private static String SECONDARY_DISK;
8285
private static final long DISK_SIZE = 10L;
8386
private static String SECONDARY_CUSTOM_DISK;
84-
87+
private static String DISK_WITH_SNAPSHOT_SCHEDULE;
88+
private static String SNAPSHOT_SCHEDULE;
8589
private ByteArrayOutputStream stdOut;
8690

8791
// Check if the required environment variables are set.
@@ -113,6 +117,8 @@ public static void setup()
113117
SECONDARY_REGIONAL_DISK = "gcloud-test-disk-secondary-regional-" + uuid;
114118
SECONDARY_DISK = "gcloud-test-disk-secondary-" + uuid;
115119
SECONDARY_CUSTOM_DISK = "gcloud-test-disk-custom-" + uuid;
120+
DISK_WITH_SNAPSHOT_SCHEDULE = "gcloud-test-disk-shapshot-" + uuid;
121+
SNAPSHOT_SCHEDULE = "gcloud-test-snapshot-schedule-" + uuid;
116122

117123
// Cleanup existing stale resources.
118124
Util.cleanUpExistingInstances("test-disks", PROJECT_ID, ZONE);
@@ -122,6 +128,7 @@ public static void setup()
122128
"gcloud-test-disk-secondary-regional-", PROJECT_ID, "us-central1");
123129
Util.cleanUpExistingRegionalDisks("gcloud-test-disk-", PROJECT_ID, REGION);
124130
Util.cleanUpExistingSnapshots("gcloud-test-snapshot-", PROJECT_ID);
131+
Util.cleanUpExistingSnapshotSchedule("gcloud-test-snapshot-schedule-", PROJECT_ID, REGION);
125132

126133
// Create disk from image.
127134
Image debianImage = null;
@@ -154,7 +161,8 @@ public static void setup()
154161
TimeUnit.SECONDS.sleep(10);
155162
SetDiskAutodelete.setDiskAutodelete(PROJECT_ID, ZONE, INSTANCE_NAME, DISK_NAME, true);
156163
assertThat(stdOut.toString()).contains("Disk autodelete field updated.");
157-
164+
CreateSnapshotSchedule.createSnapshotSchedule(PROJECT_ID, REGION, SNAPSHOT_SCHEDULE,
165+
"description", 10, "US");
158166
// Create zonal and regional blank disks for testing attach and resize.
159167
createZonalDisk();
160168
createRegionalDisk();
@@ -191,6 +199,8 @@ public static void cleanUp()
191199
RegionalDelete.deleteRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK);
192200
DeleteDisk.deleteDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK);
193201
DeleteDisk.deleteDisk(PROJECT_ID, "us-central1-c", SECONDARY_CUSTOM_DISK);
202+
DeleteDisk.deleteDisk(PROJECT_ID, ZONE, DISK_WITH_SNAPSHOT_SCHEDULE);
203+
DeleteSnapshotSchedule.deleteSnapshotSchedule(PROJECT_ID, REGION, SNAPSHOT_SCHEDULE);
194204

195205
stdOut.close();
196206
System.setOut(out);
@@ -325,24 +335,28 @@ public void testCreateReplicatedDisk()
325335
throws IOException, ExecutionException, InterruptedException, TimeoutException {
326336
Status status = CreateReplicatedDisk.createReplicatedDisk(PROJECT_ID, REGION,
327337
replicaZones, REGIONAL_REPLICATED_DISK, 100, DISK_TYPE);
328-
Disk disk = Util.getRegionalDisk(PROJECT_ID, REGION, REGIONAL_REPLICATED_DISK);
329338

330339
assertThat(status).isEqualTo(Status.DONE);
331-
assertEquals(REGIONAL_REPLICATED_DISK, disk.getName());
340+
assertDoesNotThrow(() -> {
341+
Disk disk = Util.getRegionalDisk(PROJECT_ID, REGION, REGIONAL_REPLICATED_DISK);
342+
assertEquals(REGIONAL_REPLICATED_DISK, disk.getName());
343+
});
332344
}
333345

334346
@Test
335347
public void testCreateDiskSecondaryRegional()
336348
throws IOException, ExecutionException, InterruptedException, TimeoutException {
337-
String diskType = String.format(
349+
String diskType = String.format(
338350
"projects/%s/regions/%s/diskTypes/pd-balanced", PROJECT_ID, REGION);
339351
Status status = CreateDiskSecondaryRegional.createDiskSecondaryRegional(
340352
PROJECT_ID, PROJECT_ID, REGIONAL_BLANK_DISK, SECONDARY_REGIONAL_DISK,
341353
REGION, "us-central1", DISK_SIZE, diskType);
342-
Disk disk = Util.getRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK);
343354

344355
assertThat(status).isEqualTo(Status.DONE);
345-
assertEquals(SECONDARY_REGIONAL_DISK, disk.getName());
356+
assertDoesNotThrow(() -> {
357+
Disk disk = Util.getRegionalDisk(PROJECT_ID, "us-central1", SECONDARY_REGIONAL_DISK);
358+
assertEquals(SECONDARY_REGIONAL_DISK, disk.getName());
359+
});
346360
}
347361

348362
@Test
@@ -353,10 +367,12 @@ public void testCreateDiskSecondaryZonal()
353367
Status status = CreateDiskSecondaryZonal.createDiskSecondaryZonal(
354368
PROJECT_ID, PROJECT_ID, EMPTY_DISK_NAME, SECONDARY_DISK, ZONE,
355369
"us-central1-c", DISK_SIZE, diskType);
356-
Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK);
357370

358371
assertThat(status).isEqualTo(Status.DONE);
359-
assertEquals(SECONDARY_DISK, disk.getName());
372+
assertDoesNotThrow(() -> {
373+
Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_DISK);
374+
assertEquals(SECONDARY_DISK, disk.getName());
375+
});
360376
}
361377

362378
@Test
@@ -367,9 +383,24 @@ public void testCreateSecondaryCustomDisk()
367383
Status status = CreateSecondaryCustomDisk.createSecondaryCustomDisk(
368384
PROJECT_ID, PROJECT_ID, EMPTY_DISK_NAME, SECONDARY_CUSTOM_DISK, ZONE,
369385
"us-central1-c", DISK_SIZE, diskType);
370-
Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_CUSTOM_DISK);
371386

372387
assertThat(status).isEqualTo(Status.DONE);
373-
assertEquals(SECONDARY_CUSTOM_DISK, disk.getName());
388+
assertDoesNotThrow(() -> {
389+
Disk disk = Util.getDisk(PROJECT_ID, "us-central1-c", SECONDARY_CUSTOM_DISK);
390+
assertEquals(SECONDARY_CUSTOM_DISK, disk.getName());
391+
});
392+
}
393+
394+
@Test
395+
void testCreateDiskWithSnapshotSchedule()
396+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
397+
Status status = CreateDiskWithSnapshotSchedule.createDiskWithSnapshotSchedule(
398+
PROJECT_ID, ZONE, DISK_WITH_SNAPSHOT_SCHEDULE, SNAPSHOT_SCHEDULE);
399+
400+
assertThat(status).isEqualTo(Status.DONE);
401+
assertDoesNotThrow(() -> {
402+
Disk disk = Util.getDisk(PROJECT_ID, ZONE, DISK_WITH_SNAPSHOT_SCHEDULE);
403+
assertEquals(DISK_WITH_SNAPSHOT_SCHEDULE, disk.getName());
404+
});
374405
}
375406
}

0 commit comments

Comments
 (0)