diff --git a/compute/cloud-client/src/main/java/compute/CreateInstanceWithRegionalDiskFromSnapshot.java b/compute/cloud-client/src/main/java/compute/CreateInstanceWithRegionalDiskFromSnapshot.java new file mode 100644 index 00000000000..e879a7e2d1a --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/CreateInstanceWithRegionalDiskFromSnapshot.java @@ -0,0 +1,109 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package compute; + +// [START compute_instance_create_replicated_boot_disk] +import com.google.cloud.compute.v1.AttachedDisk; +import com.google.cloud.compute.v1.AttachedDiskInitializeParams; +import com.google.cloud.compute.v1.Instance; +import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.NetworkInterface; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class CreateInstanceWithRegionalDiskFromSnapshot { + + public static void main(String[] args) throws IOException, ExecutionException, + InterruptedException, TimeoutException { + // TODO(developer): Replace these variables before running the sample + // Project ID or project number of the Cloud project you want to use. + String projectId = "YOUR_PROJECT_ID"; + // Name of the zone in which you want to create the instance. + String zone = "us-central1-a"; + // Name of the instance you want to create. + String instanceName = "YOUR_INSTANCE_NAME"; + // Name for the replicated disk. + String diskName = "YOUR_REPLICATED_DISK_NAME"; + String region = zone.substring(0, zone.length() - 2); + // Type of the disk. + String diskType = String.format( + "projects/%s/regions/%s/diskTypes/pd-standard", projectId, region); + // The full path and name of the snapshot that you want to use as the source for the new disk. + String snapshotLink = String.format("projects/%s/global/snapshots/%s", projectId, + "SNAPSHOT_NAME"); + // An iterable collection of zone names in which you want to keep + // the new disks' replicas. One of the replica zones of the clone must match + // the zone of the source disk. + List replicaZones = new ArrayList<>(); + + createInstanceWithRegionalDiskFromSnapshot(projectId, zone, instanceName, diskName, diskType, + snapshotLink, replicaZones); + } + + // Creates a new VM instance with regional disk from a snapshot and specifies replica zones. + public static Status createInstanceWithRegionalDiskFromSnapshot( + String projectId, String zone, String instanceName, String diskName, + String diskType, String snapshotLink, List replicaZones) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (InstancesClient instancesClient = InstancesClient.create()) { + AttachedDiskInitializeParams initializeParams = AttachedDiskInitializeParams.newBuilder() + .setSourceSnapshot(snapshotLink) + .setDiskType(diskType) + .setDiskName(diskName) + .addAllReplicaZones(replicaZones) + .build(); + + // Boot disk configuration + AttachedDisk bootDisk = AttachedDisk.newBuilder() + .setBoot(true) + .setAutoDelete(true) // Optional: Delete disk when instance is deleted. + .setType(AttachedDisk.Type.PERSISTENT.toString()) + .setInitializeParams(initializeParams) + .build(); + + // Network interface configuration (using the default network) + NetworkInterface networkInterface = NetworkInterface.newBuilder() + .setNetwork("global/networks/default") + .build(); + + // Create the instance resource + Instance instanceResource = Instance.newBuilder() + .setName(instanceName) + .setMachineType(String.format("zones/%s/machineTypes/n1-standard-1", zone)) + .addDisks(bootDisk) + .addNetworkInterfaces(networkInterface) + .build(); + + Operation response = instancesClient.insertAsync(projectId, zone, instanceResource).get(3, + TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error creating instance! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_instance_create_replicated_boot_disk] \ No newline at end of file diff --git a/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopRegionalDiskReplicationConsistencyGroup.java b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopRegionalDiskReplicationConsistencyGroup.java new file mode 100644 index 00000000000..6e293eef0cf --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopRegionalDiskReplicationConsistencyGroup.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package compute.disks.consistencygroup; + +// [START compute_consistency_group_regional_stop_replication] +import com.google.cloud.compute.v1.DisksStopGroupAsyncReplicationResource; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.RegionDisksClient; +import com.google.cloud.compute.v1.StopGroupAsyncReplicationRegionDiskRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class StopRegionalDiskReplicationConsistencyGroup { + + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project that contains the disk. + String project = "YOUR_PROJECT_ID"; + // Region of the disk. + String region = "us-central1"; + // Name of the consistency group. + String consistencyGroupName = "CONSISTENCY_GROUP"; + + stopRegionalDiskReplicationConsistencyGroup(project, region, consistencyGroupName); + } + + // Stops replication of a consistency group for a project in a given region. + public static Status stopRegionalDiskReplicationConsistencyGroup( + String project, String region, String consistencyGroupName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String resourcePolicy = String.format("projects/%s/regions/%s/resourcePolicies/%s", + project, region, consistencyGroupName); + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (RegionDisksClient disksClient = RegionDisksClient.create()) { + StopGroupAsyncReplicationRegionDiskRequest request = + StopGroupAsyncReplicationRegionDiskRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setDisksStopGroupAsyncReplicationResourceResource( + DisksStopGroupAsyncReplicationResource.newBuilder() + .setResourcePolicy(resourcePolicy).build()) + .build(); + Operation response = disksClient.stopGroupAsyncReplicationAsync(request) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error stopping disk replication! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_consistency_group_regional_stop_replication] diff --git a/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopZonalDiskReplicationConsistencyGroup.java b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopZonalDiskReplicationConsistencyGroup.java new file mode 100644 index 00000000000..38c31e1850d --- /dev/null +++ b/compute/cloud-client/src/main/java/compute/disks/consistencygroup/StopZonalDiskReplicationConsistencyGroup.java @@ -0,0 +1,73 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package compute.disks.consistencygroup; + +// [START compute_consistency_group_stop_replication] +import com.google.cloud.compute.v1.DisksClient; +import com.google.cloud.compute.v1.DisksStopGroupAsyncReplicationResource; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; +import com.google.cloud.compute.v1.StopGroupAsyncReplicationDiskRequest; +import java.io.IOException; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +public class StopZonalDiskReplicationConsistencyGroup { + public static void main(String[] args) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Cloud project that contains the disk. + String project = "YOUR_PROJECT_ID"; + // Zone of the disk. + String zone = "us-central1-a"; + // Name of the consistency group. + String consistencyGroupName = "CONSISTENCY_GROUP"; + + stopZonalDiskReplicationConsistencyGroup(project, zone, consistencyGroupName); + } + + // Stops replication of a consistency group for a project in a given zone. + public static Status stopZonalDiskReplicationConsistencyGroup( + String project, String zone, String consistencyGroupName) + throws IOException, InterruptedException, ExecutionException, TimeoutException { + String region = zone.substring(0, zone.lastIndexOf('-')); + + String resourcePolicy = String.format("projects/%s/regions/%s/resourcePolicies/%s", + project, region, consistencyGroupName); + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (DisksClient disksClient = DisksClient.create()) { + StopGroupAsyncReplicationDiskRequest request = + StopGroupAsyncReplicationDiskRequest.newBuilder() + .setProject(project) + .setZone(zone) + .setDisksStopGroupAsyncReplicationResourceResource( + DisksStopGroupAsyncReplicationResource.newBuilder() + .setResourcePolicy(resourcePolicy).build()) + .build(); + Operation response = disksClient.stopGroupAsyncReplicationAsync(request) + .get(3, TimeUnit.MINUTES); + + if (response.hasError()) { + throw new Error("Error stopping disk replication! " + response.getError()); + } + return response.getStatus(); + } + } +} +// [END compute_consistency_group_stop_replication] diff --git a/compute/cloud-client/src/main/java/compute/reservation/CreateSharedReservation.java b/compute/cloud-client/src/main/java/compute/reservation/CreateSharedReservation.java index 53052ee4d25..624965554a9 100644 --- a/compute/cloud-client/src/main/java/compute/reservation/CreateSharedReservation.java +++ b/compute/cloud-client/src/main/java/compute/reservation/CreateSharedReservation.java @@ -18,7 +18,9 @@ // [START compute_reservation_create_shared] import com.google.cloud.compute.v1.AllocationSpecificSKUReservation; +import com.google.cloud.compute.v1.InsertReservationRequest; import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.Operation.Status; import com.google.cloud.compute.v1.Reservation; import com.google.cloud.compute.v1.ReservationsClient; import com.google.cloud.compute.v1.ShareSettings; @@ -29,12 +31,6 @@ import java.util.concurrent.TimeoutException; public class CreateSharedReservation { - private final ReservationsClient reservationsClient; - - // Constructor to inject the ReservationsClient - public CreateSharedReservation(ReservationsClient reservationsClient) { - this.reservationsClient = reservationsClient; - } public static void main(String[] args) throws IOException, ExecutionException, InterruptedException, TimeoutException { @@ -48,62 +44,66 @@ public static void main(String[] args) // For more information visit this page: // https://cloud.google.com/compute/docs/instances/reservations-shared#shared_reservation_constraint String projectId = "YOUR_PROJECT_ID"; - // Zone in which the reservation resides. + // Zone in which to reserve resources. String zone = "us-central1-a"; // Name of the reservation to be created. String reservationName = "YOUR_RESERVATION_NAME"; // The URI of the global instance template to be used for creating the reservation. String instanceTemplateUri = String.format( - "projects/%s/global/instanceTemplates/YOUR_INSTANCE_TEMPLATE_NAME", projectId); + "projects/%s/global/instanceTemplates/%s", projectId, "YOUR_INSTANCE_TEMPLATE_NAME"); // Number of instances for which capacity needs to be reserved. int vmCount = 3; - // In your main method, create ReservationsClient - ReservationsClient client = ReservationsClient.create(); - // Create an instance of your class, passing in the client - CreateSharedReservation creator = new CreateSharedReservation(client); - creator.createSharedReservation(projectId, zone, reservationName, instanceTemplateUri, vmCount); + createSharedReservation(projectId, zone, reservationName, instanceTemplateUri, vmCount); } // Creates a shared reservation with the given name in the given zone. - public void createSharedReservation( - String projectId, String zone, - String reservationName, String instanceTemplateUri, int vmCount) - throws ExecutionException, InterruptedException, TimeoutException { + public static Status createSharedReservation( + String projectId, String zone, + String reservationName, String instanceTemplateUri, int vmCount) + throws ExecutionException, InterruptedException, TimeoutException, IOException { + + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (ReservationsClient reservationsClient = ReservationsClient.create()) { + ShareSettings shareSettings = ShareSettings.newBuilder() + .setShareType(String.valueOf(ShareSettings.ShareType.SPECIFIC_PROJECTS)) + // The IDs of projects that can consume this reservation. You can include up to + // 100 consumer projects. These projects must be in the same organization as + // the owner project. Don't include the owner project. + // By default, it is already allowed to consume the reservation. + .putProjectMap("CONSUMER_PROJECT_1", ShareSettingsProjectConfig.newBuilder().build()) + .putProjectMap("CONSUMER_PROJECT_2", ShareSettingsProjectConfig.newBuilder().build()) + .build(); - ShareSettings shareSettings = ShareSettings.newBuilder() - .setShareType(String.valueOf(ShareSettings.ShareType.SPECIFIC_PROJECTS)) - // The IDs of projects that can consume this reservation. You can include up to 100 - // consumer projects. These projects must be in the same organization as - // the owner project. Don't include the owner project. By default, it is already allowed - // to consume the reservation. - .putProjectMap("CONSUMER_PROJECT_ID_1", ShareSettingsProjectConfig.newBuilder().build()) - .putProjectMap("CONSUMER_PROJECT_ID_2", ShareSettingsProjectConfig.newBuilder().build()) - .build(); + Reservation reservationResource = + Reservation.newBuilder() + .setName(reservationName) + .setZone(zone) + .setSpecificReservationRequired(true) + .setShareSettings(shareSettings) + .setSpecificReservation( + AllocationSpecificSKUReservation.newBuilder() + .setCount(vmCount) + .setSourceInstanceTemplate(instanceTemplateUri) + .build()) + .build(); - // Create the reservation. - Reservation reservation = - Reservation.newBuilder() - .setName(reservationName) - .setZone(zone) - .setSpecificReservationRequired(true) - .setShareSettings(shareSettings) - .setSpecificReservation( - AllocationSpecificSKUReservation.newBuilder() - .setCount(vmCount) - .setSourceInstanceTemplate(instanceTemplateUri) - .build()) - .build(); + InsertReservationRequest request = + InsertReservationRequest.newBuilder() + .setProject(projectId) + .setZone(zone) + .setReservationResource(reservationResource) + .build(); - // Wait for the create reservation operation to complete. - Operation response = - this.reservationsClient.insertAsync(projectId, zone, reservation).get(3, TimeUnit.MINUTES); + Operation response = reservationsClient.insertAsync(request) + .get(3, TimeUnit.MINUTES); - if (response.hasError()) { - System.out.println("Reservation creation failed!" + response); - return; + if (response.hasError()) { + throw new Error("Reservation creation failed!!" + response); + } + return response.getStatus(); } - System.out.println("Reservation created. Operation Status: " + response.getStatus()); } } // [END compute_reservation_create_shared] diff --git a/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java b/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java index 625464b11a9..90ea8bfa729 100644 --- a/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java +++ b/compute/cloud-client/src/test/java/compute/InstanceOperationsIT.java @@ -20,27 +20,34 @@ import static com.google.common.truth.Truth.assertWithMessage; import static compute.Util.getZone; +import com.google.cloud.compute.v1.CreateSnapshotRegionDiskRequest; import com.google.cloud.compute.v1.Disk; import com.google.cloud.compute.v1.Instance; import com.google.cloud.compute.v1.Instance.Status; import com.google.cloud.compute.v1.InstancesClient; +import com.google.cloud.compute.v1.Operation; +import com.google.cloud.compute.v1.RegionDisksClient; +import com.google.cloud.compute.v1.Snapshot; import compute.disks.CloneEncryptedDisk; import compute.disks.CreateEncryptedDisk; import compute.disks.DeleteDisk; +import compute.disks.DeleteSnapshot; +import compute.disks.RegionalCreateFromSource; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; import java.util.UUID; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; import org.junit.Assert; import org.junit.jupiter.api.AfterAll; -import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeAll; -import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; import org.junit.runner.RunWith; @@ -52,13 +59,21 @@ public class InstanceOperationsIT { private static final String PROJECT_ID = System.getenv("GOOGLE_CLOUD_PROJECT"); private static final String ZONE = getZone(); + private static final String REGION = ZONE.substring(0, ZONE.length() - 2); private static String MACHINE_NAME; private static String MACHINE_NAME_ENCRYPTED; private static String DISK_NAME; private static String ENCRYPTED_DISK_NAME; private static String RAW_KEY; - - private ByteArrayOutputStream stdOut; + private static String INSTANCE_NAME; + private static final String DISK_TYPE = String.format("regions/%s/diskTypes/pd-standard", REGION); + private static String REPLICATED_DISK_NAME; + private static String SNAPSHOT_NAME; + private static final String DISK_SNAPSHOT_LINK = + String.format("projects/%s/global/snapshots/%s", PROJECT_ID, SNAPSHOT_NAME); + private static final List REPLICA_ZONES = Arrays.asList( + String.format("projects/%s/zones/%s-a", PROJECT_ID, REGION), + String.format("projects/%s/zones/%s-b", PROJECT_ID, REGION)); // Check if the required environment variables are set. public static void requireEnvVar(String envVarName) { @@ -72,47 +87,42 @@ public static void setUp() requireEnvVar("GOOGLE_APPLICATION_CREDENTIALS"); requireEnvVar("GOOGLE_CLOUD_PROJECT"); - final PrintStream out = System.out; - ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); - System.setOut(new PrintStream(stdOut)); - MACHINE_NAME = "test-instance-operation-" + UUID.randomUUID(); MACHINE_NAME_ENCRYPTED = "test-instance-encrypted-" + UUID.randomUUID(); DISK_NAME = "test-clone-disk-enc-" + UUID.randomUUID(); ENCRYPTED_DISK_NAME = "test-disk-enc-" + UUID.randomUUID(); RAW_KEY = Util.getBase64EncodedKey(); - - // Cleanup existing stale resources. - Util.cleanUpExistingInstances("test-instance-", PROJECT_ID, ZONE); - Util.cleanUpExistingDisks("test-clone-disk-enc-", PROJECT_ID, ZONE); - Util.cleanUpExistingDisks("test-disk-enc-", PROJECT_ID, ZONE); + INSTANCE_NAME = "test-instance-" + UUID.randomUUID(); + REPLICATED_DISK_NAME = "test-disk-replicated-" + UUID.randomUUID(); + SNAPSHOT_NAME = "test-snapshot-" + UUID.randomUUID().toString().split("-")[0]; compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME); compute.CreateEncryptedInstance .createEncryptedInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED, RAW_KEY); + RegionalCreateFromSource.createRegionalDisk(PROJECT_ID, REGION, REPLICA_ZONES, + REPLICATED_DISK_NAME, DISK_TYPE, 200, Optional.empty(), Optional.empty()); + createDiskSnapshot(PROJECT_ID, REGION, REPLICATED_DISK_NAME, SNAPSHOT_NAME); TimeUnit.SECONDS.sleep(30); - - stdOut.close(); - System.setOut(out); } - @AfterAll public static void cleanup() throws IOException, InterruptedException, ExecutionException, TimeoutException { - final PrintStream out = System.out; - ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); - System.setOut(new PrintStream(stdOut)); + // Cleanup existing stale resources. + Util.cleanUpExistingInstances("test-instance-", PROJECT_ID, ZONE); + Util.cleanUpExistingDisks("test-clone-disk-enc-", PROJECT_ID, ZONE); + Util.cleanUpExistingDisks("test-disk-enc-", PROJECT_ID, ZONE); + Util.cleanUpExistingRegionalDisks("test-disk-replicated-", PROJECT_ID, REGION); + Util.cleanUpExistingSnapshots("test-snapshot-", PROJECT_ID); // Delete all instances created for testing. compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED); compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, MACHINE_NAME); + compute.DeleteInstance.deleteInstance(PROJECT_ID, ZONE, INSTANCE_NAME); DeleteDisk.deleteDisk(PROJECT_ID, ZONE, DISK_NAME); DeleteDisk.deleteDisk(PROJECT_ID, ZONE, ENCRYPTED_DISK_NAME); - - stdOut.close(); - System.setOut(out); + DeleteSnapshot.deleteSnapshot(PROJECT_ID, SNAPSHOT_NAME); } private static Instance getInstance(String machineName) throws IOException { @@ -121,16 +131,28 @@ private static Instance getInstance(String machineName) throws IOException { } } - @BeforeEach - public void beforeEach() { - stdOut = new ByteArrayOutputStream(); - System.setOut(new PrintStream(stdOut)); - } - - @AfterEach - public void afterEach() { - stdOut = null; - System.setOut(null); + public static void createDiskSnapshot(String project, String region, String diskName, + String snapshotName) + throws IOException, ExecutionException, InterruptedException, TimeoutException { + try (RegionDisksClient disksClient = RegionDisksClient.create()) { + + CreateSnapshotRegionDiskRequest createSnapshotDiskRequest = + CreateSnapshotRegionDiskRequest.newBuilder() + .setProject(project) + .setRegion(region) + .setDisk(diskName) + .setSnapshotResource(Snapshot.newBuilder() + .setName(snapshotName) + .build()) + .build(); + + Operation operation = disksClient.createSnapshotAsync(createSnapshotDiskRequest) + .get(3, TimeUnit.MINUTES); + + if (operation.hasError()) { + throw new Error("Failed to create the snapshot"); + } + } } @Test @@ -204,14 +226,17 @@ public void testEncryptedInstanceOperations() @Test public void testCloneEncryptedDisk() throws IOException, ExecutionException, InterruptedException, TimeoutException { - Assert.assertEquals(Util.getInstanceStatus(PROJECT_ID, ZONE, MACHINE_NAME_ENCRYPTED), - "RUNNING"); + ByteArrayOutputStream stdOut = new ByteArrayOutputStream(); + System.setOut(new PrintStream(stdOut)); + Instance instance = getInstance(MACHINE_NAME_ENCRYPTED); String diskType = String.format("zones/%s/diskTypes/pd-standard", ZONE); CloneEncryptedDisk.createDiskFromCustomerEncryptedKey(PROJECT_ID, ZONE, DISK_NAME, diskType, 10, instance.getDisks(0).getSource(), RAW_KEY.getBytes( StandardCharsets.UTF_8)); assertThat(stdOut.toString()).contains("Disk cloned with customer encryption key."); + + stdOut.close(); } @Test @@ -228,4 +253,15 @@ public void testCreateEncryptedDisk() Assert.assertNotNull(encryptedDisk.getDiskEncryptionKey()); Assert.assertNotNull(encryptedDisk.getDiskEncryptionKey().getSha256()); } + + @Test + public void testCreateInstanceWithRegionalDiskFromSnapshot() + throws IOException, ExecutionException, InterruptedException, TimeoutException { + Operation.Status status = CreateInstanceWithRegionalDiskFromSnapshot + .createInstanceWithRegionalDiskFromSnapshot( + PROJECT_ID, ZONE, INSTANCE_NAME, REPLICATED_DISK_NAME, + DISK_TYPE, DISK_SNAPSHOT_LINK, REPLICA_ZONES); + + assertThat(status).isEqualTo(Operation.Status.DONE); + } } diff --git a/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java b/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java index 75716d474df..e7038724d45 100644 --- a/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java +++ b/compute/cloud-client/src/test/java/compute/disks/ConsistencyGroupIT.java @@ -36,12 +36,16 @@ import com.google.cloud.compute.v1.RegionDisksClient; import com.google.cloud.compute.v1.RemoveResourcePoliciesRegionDiskRequest; import com.google.cloud.compute.v1.ResourcePoliciesClient; +import com.google.cloud.compute.v1.StopGroupAsyncReplicationDiskRequest; +import com.google.cloud.compute.v1.StopGroupAsyncReplicationRegionDiskRequest; import compute.disks.consistencygroup.AddDiskToConsistencyGroup; import compute.disks.consistencygroup.CreateConsistencyGroup; import compute.disks.consistencygroup.DeleteConsistencyGroup; import compute.disks.consistencygroup.ListRegionalDisksInConsistencyGroup; import compute.disks.consistencygroup.ListZonalDisksInConsistencyGroup; import compute.disks.consistencygroup.RemoveDiskFromConsistencyGroup; +import compute.disks.consistencygroup.StopRegionalDiskReplicationConsistencyGroup; +import compute.disks.consistencygroup.StopZonalDiskReplicationConsistencyGroup; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Timeout; @@ -54,6 +58,7 @@ public class ConsistencyGroupIT { private static final String PROJECT_ID = "project-id"; private static final String REGION = "asia-east1"; + private static final String ZONE = "asia-east1-c"; private static final String CONSISTENCY_GROUP_NAME = "consistency-group"; private static final String DISK_NAME = "disk-for-consistency"; @@ -193,4 +198,54 @@ public void testListZonalDisksInConsistencyGroup() throws Exception { verify(mockResponse, times(1)).iterateAll(); } } + + @Test + public void testStopRegionalDiskReplicationConsistencyGroup() throws Exception { + try (MockedStatic mockedRegionDisksClient = + mockStatic(RegionDisksClient.class)) { + Operation operation = mock(Operation.class); + RegionDisksClient mockClient = mock(RegionDisksClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedRegionDisksClient.when(RegionDisksClient::create).thenReturn(mockClient); + when(mockClient.stopGroupAsyncReplicationAsync( + any(StopGroupAsyncReplicationRegionDiskRequest.class))).thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status status = StopRegionalDiskReplicationConsistencyGroup + .stopRegionalDiskReplicationConsistencyGroup( + PROJECT_ID, REGION, CONSISTENCY_GROUP_NAME); + + verify(mockClient, times(1)).stopGroupAsyncReplicationAsync( + any(StopGroupAsyncReplicationRegionDiskRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + } + } + + @Test + public void testStopZonalDiskReplicationConsistencyGroup() throws Exception { + try (MockedStatic mockedDisksClient = + mockStatic(DisksClient.class)) { + Operation operation = mock(Operation.class); + DisksClient mockClient = mock(DisksClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + + mockedDisksClient.when(DisksClient::create).thenReturn(mockClient); + when(mockClient.stopGroupAsyncReplicationAsync( + any(StopGroupAsyncReplicationDiskRequest.class))).thenReturn(mockFuture); + when(mockFuture.get(anyLong(), any(TimeUnit.class))).thenReturn(operation); + when(operation.getStatus()).thenReturn(Status.DONE); + + Status status = StopZonalDiskReplicationConsistencyGroup + .stopZonalDiskReplicationConsistencyGroup( + PROJECT_ID, ZONE, CONSISTENCY_GROUP_NAME); + + verify(mockClient, times(1)).stopGroupAsyncReplicationAsync( + any(StopGroupAsyncReplicationDiskRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + } + } } \ No newline at end of file diff --git a/compute/cloud-client/src/test/java/compute/reservation/ReservationIT.java b/compute/cloud-client/src/test/java/compute/reservation/ReservationIT.java index ab9575f067a..e94d2fee8b3 100644 --- a/compute/cloud-client/src/test/java/compute/reservation/ReservationIT.java +++ b/compute/cloud-client/src/test/java/compute/reservation/ReservationIT.java @@ -18,21 +18,23 @@ import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertWithMessage; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.mockStatic; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; import com.google.api.gax.longrunning.OperationFuture; import com.google.api.gax.rpc.NotFoundException; -import com.google.cloud.compute.v1.AllocationSpecificSKUReservation; +import com.google.cloud.compute.v1.InsertReservationRequest; import com.google.cloud.compute.v1.Operation; import com.google.cloud.compute.v1.Operation.Status; import com.google.cloud.compute.v1.Reservation; import com.google.cloud.compute.v1.ReservationsClient; -import com.google.cloud.compute.v1.ShareSettings; -import com.google.cloud.compute.v1.ShareSettingsProjectConfig; import compute.CreateInstanceTemplate; import compute.CreateRegionalInstanceTemplate; import compute.DeleteInstanceTemplate; @@ -53,6 +55,7 @@ import org.junit.jupiter.api.Timeout; import org.junit.runner.RunWith; import org.junit.runners.JUnit4; +import org.mockito.MockedStatic; @RunWith(JUnit4.class) @Timeout(value = 6, unit = TimeUnit.MINUTES) @@ -184,50 +187,26 @@ public void testCreateReservationWithRegionInstanceTemplate() @Test public void testCreateSharedReservation() - throws ExecutionException, InterruptedException, TimeoutException { - // Mock the ReservationsClient - ReservationsClient mockReservationsClient = mock(ReservationsClient.class); - - // This test require projects in the test environment to share reservation with, - // therefore the operation should be mocked. If you want to make a real test, - // please set the CONSUMER_PROJECT_ID_1 and CONSUMER_PROJECT_ID_2 accordingly. - // Make sure that base project has proper permissions to share reservations. - // See: https://cloud.google.com/compute/docs/instances/reservations-shared#shared_reservation_constraint - ShareSettings shareSettings = ShareSettings.newBuilder() - .setShareType(String.valueOf(ShareSettings.ShareType.SPECIFIC_PROJECTS)) - .putProjectMap("CONSUMER_PROJECT_ID_1", ShareSettingsProjectConfig.newBuilder().build()) - .putProjectMap("CONSUMER_PROJECT_ID_2", ShareSettingsProjectConfig.newBuilder().build()) - .build(); - - Reservation reservation = - Reservation.newBuilder() - .setName(RESERVATION_NAME_SHARED) - .setZone(ZONE) - .setSpecificReservationRequired(true) - .setShareSettings(shareSettings) - .setSpecificReservation( - AllocationSpecificSKUReservation.newBuilder() - .setCount(NUMBER_OF_VMS) - .setSourceInstanceTemplate(INSTANCE_TEMPLATE_SHARED_RESERV_URI) - .build()) - .build(); - - OperationFuture mockFuture = mock(OperationFuture.class); - when(mockReservationsClient.insertAsync(PROJECT_ID, ZONE, reservation)) - .thenReturn(mockFuture); - Operation mockOperation = mock(Operation.class); - when(mockFuture.get(3, TimeUnit.MINUTES)).thenReturn(mockOperation); - when(mockOperation.hasError()).thenReturn(false); - when(mockOperation.getStatus()).thenReturn(Status.DONE); - - // Create an instance, passing in the mock client - CreateSharedReservation creator = new CreateSharedReservation(mockReservationsClient); - - creator.createSharedReservation(PROJECT_ID, ZONE, - RESERVATION_NAME_SHARED, INSTANCE_TEMPLATE_SHARED_RESERV_URI, NUMBER_OF_VMS); - - verify(mockReservationsClient, times(1)) - .insertAsync(PROJECT_ID, ZONE, reservation); - assertThat(stdOut.toString()).contains("Reservation created. Operation Status: DONE"); + throws ExecutionException, InterruptedException, TimeoutException, IOException { + try (MockedStatic mockReservationsClient = + mockStatic(ReservationsClient.class)) { + ReservationsClient mockClient = mock(ReservationsClient.class); + OperationFuture mockFuture = mock(OperationFuture.class); + Operation mockOperation = mock(Operation.class); + + mockReservationsClient.when(ReservationsClient::create).thenReturn(mockClient); + when(mockClient.insertAsync(any(InsertReservationRequest.class))) + .thenReturn(mockFuture); + when(mockFuture.get(3, TimeUnit.MINUTES)).thenReturn(mockOperation); + when(mockOperation.getStatus()).thenReturn(Status.DONE); + + Status status = CreateSharedReservation.createSharedReservation(PROJECT_ID, ZONE, + RESERVATION_NAME_SHARED, INSTANCE_TEMPLATE_SHARED_RESERV_URI, NUMBER_OF_VMS); + + verify(mockClient, times(1)).insertAsync(any(InsertReservationRequest.class)); + verify(mockFuture, times(1)).get(anyLong(), any(TimeUnit.class)); + assertEquals(Status.DONE, status); + + } } } \ No newline at end of file diff --git a/secretmanager/src/main/java/secretmanager/CreateSecret.java b/secretmanager/src/main/java/secretmanager/CreateSecret.java index a5f6f79439b..0a025daf088 100644 --- a/secretmanager/src/main/java/secretmanager/CreateSecret.java +++ b/secretmanager/src/main/java/secretmanager/CreateSecret.java @@ -21,6 +21,7 @@ import com.google.cloud.secretmanager.v1.Replication; import com.google.cloud.secretmanager.v1.Secret; import com.google.cloud.secretmanager.v1.SecretManagerServiceClient; +import com.google.protobuf.Duration; import java.io.IOException; public class CreateSecret { @@ -41,6 +42,12 @@ public static void createSecret(String projectId, String secretId) throws IOExce // Build the parent name from the project. ProjectName projectName = ProjectName.of(projectId); + // Optionally set a TTL for the secret. This demonstrates how to configure + // a secret to be automatically deleted after a certain period. The TTL is + // specified in seconds (e.g., 900 for 15 minutes). This can be useful + // for managing sensitive data and reducing storage costs. + Duration ttl = Duration.newBuilder().setSeconds(900).build(); + // Build the secret to create. Secret secret = Secret.newBuilder() @@ -48,6 +55,7 @@ public static void createSecret(String projectId, String secretId) throws IOExce Replication.newBuilder() .setAutomatic(Replication.Automatic.newBuilder().build()) .build()) + .setTtl(ttl) .build(); // Create the secret. diff --git a/tpu/src/main/java/tpu/ListQueuedResources.java b/tpu/src/main/java/tpu/ListQueuedResources.java new file mode 100644 index 00000000000..1d38c988892 --- /dev/null +++ b/tpu/src/main/java/tpu/ListQueuedResources.java @@ -0,0 +1,55 @@ +/* + * Copyright 2024 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package tpu; + +//[START tpu_queued_resources_list] +import com.google.cloud.tpu.v2alpha1.ListQueuedResourcesRequest; +import com.google.cloud.tpu.v2alpha1.QueuedResource; +import com.google.cloud.tpu.v2alpha1.TpuClient; +import com.google.cloud.tpu.v2alpha1.TpuClient.ListQueuedResourcesPage; +import java.io.IOException; + +public class ListQueuedResources { + public static void main(String[] args) throws IOException { + // TODO(developer): Replace these variables before running the sample. + // Project ID or project number of the Google Cloud project. + String projectId = "YOUR_PROJECT_ID"; + // The zone in which the TPU was created. + String zone = "us-central1-a"; + + listQueuedResources(projectId, zone); + } + + // List Queued Resources. + public static ListQueuedResourcesPage listQueuedResources( + String projectId, String zone) throws IOException { + String parent = String.format("projects/%s/locations/%s", projectId, zone); + // Initialize client that will be used to send requests. This client only needs to be created + // once, and can be reused for multiple requests. + try (TpuClient tpuClient = TpuClient.create()) { + ListQueuedResourcesRequest request = + ListQueuedResourcesRequest.newBuilder().setParent(parent).build(); + ListQueuedResourcesPage response = tpuClient.listQueuedResources(request).getPage(); + + for (QueuedResource queuedResource : response.iterateAll()) { + System.out.println(queuedResource.getName()); + } + return response; + } + } +} +//[END tpu_queued_resources_list] diff --git a/tpu/src/test/java/tpu/QueuedResourceIT.java b/tpu/src/test/java/tpu/QueuedResourceIT.java index 7d164105f25..0cb6bafcd4d 100644 --- a/tpu/src/test/java/tpu/QueuedResourceIT.java +++ b/tpu/src/test/java/tpu/QueuedResourceIT.java @@ -16,6 +16,7 @@ package tpu; +import static com.google.common.truth.Truth.assertThat; import static org.junit.Assert.assertEquals; import static org.mockito.ArgumentMatchers.anyLong; import static org.mockito.Mockito.any; @@ -29,10 +30,15 @@ import com.google.cloud.tpu.v2alpha1.CreateQueuedResourceRequest; import com.google.cloud.tpu.v2alpha1.DeleteQueuedResourceRequest; import com.google.cloud.tpu.v2alpha1.GetQueuedResourceRequest; +import com.google.cloud.tpu.v2alpha1.ListQueuedResourcesRequest; import com.google.cloud.tpu.v2alpha1.QueuedResource; import com.google.cloud.tpu.v2alpha1.TpuClient; +import com.google.cloud.tpu.v2alpha1.TpuClient.ListQueuedResourcesPage; +import com.google.cloud.tpu.v2alpha1.TpuClient.ListQueuedResourcesPagedResponse; import com.google.cloud.tpu.v2alpha1.TpuSettings; import java.io.IOException; +import java.util.Arrays; +import java.util.List; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.Test; @@ -120,6 +126,33 @@ public void testGetQueuedResource() throws IOException { } } + @Test + public void testListTpuVm() throws IOException { + try (MockedStatic mockedTpuClient = mockStatic(TpuClient.class)) { + QueuedResource queuedResource1 = mock(QueuedResource.class); + QueuedResource queuedResource2 = mock(QueuedResource.class); + List mockListQueuedResources = + Arrays.asList(queuedResource1, queuedResource2); + + TpuClient mockClient = mock(TpuClient.class); + mockedTpuClient.when(TpuClient::create).thenReturn(mockClient); + ListQueuedResourcesPagedResponse mockListQueuedResourcesResponse = + mock(ListQueuedResourcesPagedResponse.class); + when(mockClient.listQueuedResources(any(ListQueuedResourcesRequest.class))) + .thenReturn(mockListQueuedResourcesResponse); + ListQueuedResourcesPage mockQueuedResourcesPage = + mock(ListQueuedResourcesPage.class); + when(mockListQueuedResourcesResponse.getPage()).thenReturn(mockQueuedResourcesPage); + when(mockQueuedResourcesPage.getValues()).thenReturn(mockListQueuedResources); + + ListQueuedResourcesPage returnedList = + ListQueuedResources.listQueuedResources(PROJECT_ID, ZONE); + + assertThat(returnedList.getValues()).isEqualTo(mockListQueuedResources); + verify(mockClient, times(1)).listQueuedResources(any(ListQueuedResourcesRequest.class)); + } + } + @Test public void testDeleteForceQueuedResource() throws IOException, InterruptedException, ExecutionException {