Skip to content

Commit 3ce6598

Browse files
Added compute_instance_not_consume_reservation sample and test.
1 parent 3b56aae commit 3ce6598

File tree

6 files changed

+249
-76
lines changed

6 files changed

+249
-76
lines changed
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
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.reservation;
18+
19+
// [START compute_instance_not_consume_reservation]
20+
21+
import static com.google.cloud.compute.v1.ReservationAffinity.ConsumeReservationType.NO_RESERVATION;
22+
23+
import com.google.cloud.compute.v1.AttachedDisk;
24+
import com.google.cloud.compute.v1.AttachedDiskInitializeParams;
25+
import com.google.cloud.compute.v1.Instance;
26+
import com.google.cloud.compute.v1.InstancesClient;
27+
import com.google.cloud.compute.v1.NetworkInterface;
28+
import com.google.cloud.compute.v1.Operation;
29+
import com.google.cloud.compute.v1.ReservationAffinity;
30+
import java.io.IOException;
31+
import java.util.concurrent.ExecutionException;
32+
import java.util.concurrent.TimeUnit;
33+
import java.util.concurrent.TimeoutException;
34+
35+
public class CreateInstanceNotConsumeReservation {
36+
public static void main(String[] args)
37+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
38+
// TODO(developer): Replace these variables before running the sample.
39+
// Project ID or project number of the Cloud project you want to use.
40+
String projectId = "YOUR_PROJECT_ID";
41+
// Name of the zone in which you want to create the reservation.
42+
String zone = "us-central1-a";
43+
// Name of the VM instance you want to query.
44+
String instanceName = "YOUR_INSTANCE_NAME";
45+
// Machine type of the instances in the reservation.
46+
String machineType = "n2-standard-32";
47+
48+
createInstanceNotConsumeReservation(projectId, zone, instanceName, machineType);
49+
}
50+
51+
// Create a virtual machine that explicitly doesn't consume reservations
52+
public static void createInstanceNotConsumeReservation(
53+
String projectId, String zone, String instanceName, String machineType)
54+
throws IOException, InterruptedException, ExecutionException, TimeoutException {
55+
// Below are sample values that can be replaced.
56+
// sourceImage: path to the operating system image to mount.
57+
// * For details about images you can mount, see https://cloud.google.com/compute/docs/images
58+
// Network interface to associate with the instance.
59+
String sourceImage = String
60+
.format("projects/debian-cloud/global/images/family/%s", "debian-11");
61+
String network = "global/networks/default"; // Example network
62+
63+
// Initialize client that will be used to send requests. This client only needs to be created
64+
// once, and can be reused for multiple requests.
65+
try (InstancesClient instancesClient = InstancesClient.create()) {
66+
67+
// Create the attached disk object
68+
AttachedDisk attachedDisk =
69+
AttachedDisk.newBuilder()
70+
.setBoot(true)
71+
.setAutoDelete(true)
72+
.setInitializeParams(
73+
AttachedDiskInitializeParams.newBuilder()
74+
.setSourceImage(sourceImage)
75+
.build())
76+
.build();
77+
78+
// Create the network interface object
79+
NetworkInterface networkInterface =
80+
NetworkInterface.newBuilder().setName(network).build();
81+
82+
// Set reservation affinity to "none"
83+
ReservationAffinity reservationAffinity =
84+
ReservationAffinity.newBuilder()
85+
.setConsumeReservationType(NO_RESERVATION.toString())
86+
.build();
87+
88+
// Create the instance object
89+
Instance instance =
90+
Instance.newBuilder()
91+
.setName(instanceName)
92+
.setMachineType("zones/" + zone + "/machineTypes/" + machineType)
93+
.addDisks(attachedDisk)
94+
.addNetworkInterfaces(networkInterface)
95+
.setReservationAffinity(reservationAffinity)
96+
.build();
97+
98+
// Wait for the operation to complete.
99+
Operation response = instancesClient.insertAsync(
100+
projectId, zone, instance).get(3, TimeUnit.MINUTES);
101+
102+
if (response.hasError()) {
103+
System.out.println("Instance creation failed ! ! " + response);
104+
return;
105+
}
106+
System.out.println("Operation Status: " + response.getStatus());
107+
}
108+
}
109+
}
110+
// [END compute_instance_not_consume_reservation]

compute/cloud-client/src/main/java/compute/reservation/CreateReservation.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616

1717
package compute.reservation;
1818

19+
// [START compute_reservation_create]
20+
1921
import com.google.cloud.compute.v1.AcceleratorConfig;
2022
import com.google.cloud.compute.v1.AllocationSpecificSKUAllocationAllocatedInstancePropertiesReservedDisk;
2123
import com.google.cloud.compute.v1.AllocationSpecificSKUAllocationReservedInstanceProperties;
@@ -28,7 +30,6 @@
2830
import java.util.concurrent.TimeUnit;
2931
import java.util.concurrent.TimeoutException;
3032

31-
// [START compute_reservation_create]
3233
public class CreateReservation {
3334

3435
public static void main(String[] args)

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static void setUp()
102102
Util.cleanUpExistingInstances("my-new-test-instance", PROJECT_ID, ZONE);
103103
Util.cleanUpExistingInstances("encrypted-test-instance", PROJECT_ID, ZONE);
104104
Util.cleanUpExistingInstances("test-instance-with-ssd", PROJECT_ID, ZONE);
105-
Util.cleanUpExistingInstanceTemplates("test-inst-temp-regional", PROJECT_ID);
105+
Util.cleanUpExistingRegionalInstanceTemplates("test-inst-temp-regional", PROJECT_ID, ZONE);
106106

107107
compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME);
108108
compute.CreateInstance.createInstance(PROJECT_ID, ZONE, MACHINE_NAME_LIST_INSTANCE);

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

Lines changed: 99 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -16,22 +16,21 @@
1616

1717
package compute;
1818

19-
import com.google.api.gax.rpc.NotFoundException;
20-
import com.google.cloud.compute.v1.AggregatedListInstancesRequest;
2119
import com.google.cloud.compute.v1.Disk;
2220
import com.google.cloud.compute.v1.DisksClient;
2321
import com.google.cloud.compute.v1.Instance;
24-
import com.google.cloud.compute.v1.Instance.Status;
2522
import com.google.cloud.compute.v1.InstanceTemplate;
2623
import com.google.cloud.compute.v1.InstanceTemplatesClient;
2724
import com.google.cloud.compute.v1.InstanceTemplatesClient.ListPagedResponse;
2825
import com.google.cloud.compute.v1.InstancesClient;
29-
import com.google.cloud.compute.v1.InstancesClient.AggregatedListPagedResponse;
30-
import com.google.cloud.compute.v1.InstancesScopedList;
31-
import com.google.cloud.compute.v1.ListInstanceTemplatesRequest;
26+
import com.google.cloud.compute.v1.ListRegionInstanceTemplatesRequest;
3227
import com.google.cloud.compute.v1.RegionDisksClient;
28+
import com.google.cloud.compute.v1.RegionInstanceTemplatesClient;
3329
import com.google.cloud.compute.v1.Reservation;
3430
import com.google.cloud.compute.v1.ReservationsClient;
31+
import com.google.cloud.compute.v1.Snapshot;
32+
import com.google.cloud.compute.v1.StoragePool;
33+
import compute.deleteprotection.SetDeleteProtection;
3534
import compute.reservation.DeleteReservation;
3635
import java.io.IOException;
3736
import java.nio.charset.StandardCharsets;
@@ -40,7 +39,6 @@
4039
import java.time.OffsetDateTime;
4140
import java.time.temporal.ChronoUnit;
4241
import java.util.Base64;
43-
import java.util.Map;
4442
import java.util.Random;
4543
import java.util.concurrent.ExecutionException;
4644
import java.util.concurrent.TimeoutException;
@@ -52,7 +50,7 @@ public abstract class Util {
5250
// resources
5351
// and delete the listed resources based on the timestamp.
5452

55-
private static final int DELETION_THRESHOLD_TIME_HOURS = 24;
53+
private static final int DELETION_THRESHOLD_TIME_HOURS = 30;
5654
// comma separate list of zone names
5755
private static final String TEST_ZONES_NAME = "JAVA_DOCS_COMPUTE_TEST_ZONES";
5856
private static final String DEFAULT_ZONES = "us-central1-a,us-west1-a,asia-south1-a";
@@ -61,70 +59,67 @@ public abstract class Util {
6159
// has creation timestamp >24 hours.
6260
public static void cleanUpExistingInstanceTemplates(String prefixToDelete, String projectId)
6361
throws IOException, ExecutionException, InterruptedException, TimeoutException {
64-
for (InstanceTemplate template : listFilteredInstanceTemplates(projectId, prefixToDelete)
65-
.iterateAll()) {
66-
if (!template.hasCreationTimestamp()) {
67-
continue;
62+
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
63+
ListPagedResponse templates = instanceTemplatesClient.list(projectId);
64+
for (InstanceTemplate instanceTemplate : templates.iterateAll()) {
65+
if (containPrefixToDelete(instanceTemplate, prefixToDelete)
66+
&& isCreatedBeforeThresholdTime(instanceTemplate.getCreationTimestamp())
67+
&& instanceTemplate.isInitialized()) {
68+
DeleteInstanceTemplate.deleteInstanceTemplate(projectId, instanceTemplate.getName());
69+
}
6870
}
69-
if (template.getName().contains(prefixToDelete)
70-
&& isCreatedBeforeThresholdTime(template.getCreationTimestamp())
71-
&& template.isInitialized()) {
72-
DeleteInstanceTemplate.deleteInstanceTemplate(projectId, template.getName());
71+
}
72+
}
73+
74+
// Delete regional instance templates which starts with the given prefixToDelete and
75+
// has creation timestamp >24 hours.
76+
public static void cleanUpExistingRegionalInstanceTemplates(
77+
String prefixToDelete, String projectId, String zone)
78+
throws IOException, ExecutionException, InterruptedException, TimeoutException {
79+
try (RegionInstanceTemplatesClient instanceTemplatesClient =
80+
RegionInstanceTemplatesClient.create()) {
81+
String region = zone.substring(0, zone.lastIndexOf('-'));
82+
ListRegionInstanceTemplatesRequest request =
83+
ListRegionInstanceTemplatesRequest.newBuilder()
84+
.setProject(projectId)
85+
.setRegion(region)
86+
.build();
87+
88+
for (InstanceTemplate instanceTemplate :
89+
instanceTemplatesClient.list(request).iterateAll()) {
90+
if (containPrefixToDeleteAndZone(instanceTemplate, prefixToDelete, zone)
91+
&& isCreatedBeforeThresholdTime(instanceTemplate.getCreationTimestamp())
92+
&& instanceTemplate.isInitialized()) {
93+
DeleteRegionalInstanceTemplate.deleteRegionalInstanceTemplate(
94+
projectId, region, instanceTemplate.getName());
95+
}
7396
}
7497
}
7598
}
7699

77100
// Delete instances which starts with the given prefixToDelete and
78101
// has creation timestamp >24 hours.
79102
public static void cleanUpExistingInstances(String prefixToDelete, String projectId,
80-
String instanceZone)
103+
String instanceZone)
81104
throws IOException, ExecutionException, InterruptedException, TimeoutException {
82-
for (Map.Entry<String, InstancesScopedList> instanceGroup : listFilteredInstances(
83-
projectId, prefixToDelete).iterateAll()) {
84-
for (Instance instance : instanceGroup.getValue().getInstancesList()) {
85-
if (!instance.hasCreationTimestamp()) {
86-
continue;
105+
try (InstancesClient instancesClient = InstancesClient.create()) {
106+
for (Instance instance : instancesClient.list(projectId, instanceZone).iterateAll()) {
107+
if (instance.getDeletionProtection()
108+
&& isCreatedBeforeThresholdTime(instance.getCreationTimestamp())) {
109+
SetDeleteProtection.setDeleteProtection(
110+
projectId, instanceZone, instance.getName(), false);
87111
}
88-
if (instance.getName().contains(prefixToDelete)
89-
&& isCreatedBeforeThresholdTime(instance.getCreationTimestamp())
90-
&& instance.getStatus().equalsIgnoreCase(Status.RUNNING.toString())) {
112+
if (containPrefixToDeleteAndZone(instance, prefixToDelete, instanceZone)
113+
&& isCreatedBeforeThresholdTime(instance.getCreationTimestamp())) {
91114
DeleteInstance.deleteInstance(projectId, instanceZone, instance.getName());
92115
}
93116
}
94117
}
95118
}
96119

97-
public static AggregatedListPagedResponse listFilteredInstances(
98-
String project, String instanceNamePrefix) throws IOException {
99-
try (InstancesClient instancesClient = InstancesClient.create()) {
100-
101-
AggregatedListInstancesRequest aggregatedListInstancesRequest = AggregatedListInstancesRequest
102-
.newBuilder()
103-
.setProject(project)
104-
.setFilter(String.format("name:%s", instanceNamePrefix))
105-
.build();
106-
107-
return instancesClient
108-
.aggregatedList(aggregatedListInstancesRequest);
109-
}
110-
}
111-
112-
public static ListPagedResponse listFilteredInstanceTemplates(
113-
String projectId, String instanceTemplatePrefix) throws IOException {
114-
try (InstanceTemplatesClient instanceTemplatesClient = InstanceTemplatesClient.create()) {
115-
ListInstanceTemplatesRequest listInstanceTemplatesRequest =
116-
ListInstanceTemplatesRequest.newBuilder()
117-
.setProject(projectId)
118-
.setFilter(String.format("name:%s", instanceTemplatePrefix))
119-
.build();
120-
121-
return instanceTemplatesClient.list(listInstanceTemplatesRequest);
122-
}
123-
}
124-
125120
public static boolean isCreatedBeforeThresholdTime(String timestamp) {
126121
return OffsetDateTime.parse(timestamp).toInstant()
127-
.isBefore(Instant.now().minus(DELETION_THRESHOLD_TIME_HOURS, ChronoUnit.HOURS));
122+
.isBefore(Instant.now().minus(DELETION_THRESHOLD_TIME_HOURS, ChronoUnit.MINUTES));
128123
}
129124

130125
public static String getBase64EncodedKey() {
@@ -185,25 +180,65 @@ public static String getEnvVar(String envVarName, String defaultValue) {
185180
return val;
186181
}
187182

188-
// Delete reservations which starts with the given prefixToDelete and
183+
// Delete reservation which starts with the given prefixToDelete and
189184
// has creation timestamp >24 hours.
190185
public static void cleanUpExistingReservations(
191186
String prefixToDelete, String projectId, String zone)
192187
throws IOException, ExecutionException, InterruptedException, TimeoutException {
193188
try (ReservationsClient reservationsClient = ReservationsClient.create()) {
194189
for (Reservation reservation : reservationsClient.list(projectId, zone).iterateAll()) {
195-
if (!reservationsClient.list(projectId, zone).iterateAll().iterator().hasNext()) {
196-
break;
197-
}
198-
if (reservation.getName().contains(prefixToDelete)
190+
if (containPrefixToDeleteAndZone(reservation, prefixToDelete, zone)
199191
&& isCreatedBeforeThresholdTime(reservation.getCreationTimestamp())) {
200-
try {
201-
DeleteReservation.deleteReservation(projectId, zone, reservation.getName());
202-
} catch (NotFoundException e) {
203-
System.err.println("Reservation not found, skipping deletion:" + reservation.getName());
204-
}
192+
DeleteReservation.deleteReservation(projectId, zone, reservation.getName());
205193
}
206194
}
207195
}
208196
}
197+
198+
public static boolean containPrefixToDeleteAndZone(
199+
Object resource, String prefixToDelete, String zone) {
200+
boolean containPrefixAndZone = false;
201+
try {
202+
if (resource instanceof Instance) {
203+
containPrefixAndZone = ((Instance) resource).getName().contains(prefixToDelete)
204+
&& ((Instance) resource).getZone().contains(zone);
205+
}
206+
if (resource instanceof InstanceTemplate) {
207+
containPrefixAndZone = ((InstanceTemplate) resource).getName().contains(prefixToDelete)
208+
&& ((InstanceTemplate) resource).getRegion()
209+
.contains(zone.substring(0, zone.lastIndexOf('-')));
210+
}
211+
if (resource instanceof Reservation) {
212+
containPrefixAndZone = ((Reservation) resource).getName().contains(prefixToDelete)
213+
&& ((Reservation) resource).getZone().contains(zone);
214+
}
215+
if (resource instanceof Disk) {
216+
containPrefixAndZone = ((Disk) resource).getName().contains(prefixToDelete)
217+
&& ((Disk) resource).getZone().contains(zone);
218+
}
219+
if (resource instanceof StoragePool) {
220+
containPrefixAndZone = ((StoragePool) resource).getName().contains(prefixToDelete)
221+
&& ((StoragePool) resource).getZone().contains(zone);
222+
}
223+
} catch (NullPointerException e) {
224+
System.err.println("Resource not found, skipping deletion:");
225+
}
226+
return containPrefixAndZone;
227+
}
228+
229+
public static boolean containPrefixToDelete(
230+
Object resource, String prefixToDelete) {
231+
boolean containPrefixToDelete = false;
232+
try {
233+
if (resource instanceof InstanceTemplate) {
234+
containPrefixToDelete = ((InstanceTemplate) resource).getName().contains(prefixToDelete);
235+
}
236+
if (resource instanceof Snapshot) {
237+
containPrefixToDelete = ((Snapshot) resource).getName().contains(prefixToDelete);
238+
}
239+
} catch (NullPointerException e) {
240+
System.err.println("Resource not found, skipping deletion:");
241+
}
242+
return containPrefixToDelete;
243+
}
209244
}

0 commit comments

Comments
 (0)