Skip to content

Commit 33f9b6a

Browse files
authored
samples: added cleanup option (GoogleCloudPlatform#3993)
Fixes GoogleCloudPlatform#3836 - [X] Please **merge** this PR for me once it is approved.
1 parent 4783d46 commit 33f9b6a

File tree

2 files changed

+154
-1
lines changed

2 files changed

+154
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
/*
2+
* Copyright 2020 Google Inc.
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 com.example.cloud.iot.endtoend;
18+
19+
import static com.example.cloud.iot.endtoend.CloudiotPubsubExampleServer.APP_NAME;
20+
21+
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
22+
import com.google.api.client.http.HttpRequestInitializer;
23+
import com.google.api.client.json.JsonFactory;
24+
import com.google.api.client.json.jackson2.JacksonFactory;
25+
import com.google.api.services.cloudiot.v1.CloudIot;
26+
import com.google.api.services.cloudiot.v1.CloudIotScopes;
27+
import com.google.api.services.cloudiot.v1.model.Device;
28+
import com.google.api.services.cloudiot.v1.model.DeviceRegistry;
29+
import com.google.auth.http.HttpCredentialsAdapter;
30+
import com.google.auth.oauth2.GoogleCredentials;
31+
import java.io.IOException;
32+
import java.security.GeneralSecurityException;
33+
import java.util.List;
34+
35+
public class CleanUpHelper {
36+
protected static List<DeviceRegistry> getRegisteries(String project, String cloudRegion)
37+
throws IOException, GeneralSecurityException {
38+
GoogleCredentials credential =
39+
GoogleCredentials.getApplicationDefault().createScoped(CloudIotScopes.all());
40+
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
41+
HttpRequestInitializer init = new HttpCredentialsAdapter(credential);
42+
final CloudIot service =
43+
new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init)
44+
.setApplicationName(APP_NAME)
45+
.build();
46+
final String projectPath = String.format("projects/%s/locations/%s", project, cloudRegion);
47+
48+
List<DeviceRegistry> registries =
49+
service
50+
.projects()
51+
.locations()
52+
.registries()
53+
.list(projectPath)
54+
.execute()
55+
.getDeviceRegistries();
56+
return registries;
57+
}
58+
59+
/**
60+
* clearRegistry
61+
*
62+
* <ul>
63+
* <li>Registries can't be deleted if they contain devices,
64+
* <li>Gateways (a type of device) can't be deleted if they have bound devices
65+
* <li>Devices can't be deleted if bound to gateways...
66+
* </ul>
67+
*
68+
* <p>To completely remove a registry, you must unbind all devices from gateways, then remove all
69+
* devices in a registry before removing the registry. As pseudocode: <code>
70+
* ForAll gateways
71+
* ForAll devicesBoundToGateway
72+
* unbindDeviceFromGateway
73+
* ForAll devices
74+
* Delete device by ID
75+
* Delete registry
76+
* </code>
77+
*/
78+
protected static void clearRegistry(String cloudRegion, String projectId, String registryName)
79+
throws GeneralSecurityException, IOException {
80+
GoogleCredentials credential =
81+
GoogleCredentials.getApplicationDefault().createScoped(CloudIotScopes.all());
82+
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
83+
HttpRequestInitializer init = new HttpCredentialsAdapter(credential);
84+
final CloudIot service =
85+
new CloudIot.Builder(GoogleNetHttpTransport.newTrustedTransport(), jsonFactory, init)
86+
.setApplicationName(APP_NAME)
87+
.build();
88+
final String registryPath =
89+
String.format(
90+
"projects/%s/locations/%s/registries/%s", projectId, cloudRegion, registryName);
91+
92+
CloudIot.Projects.Locations.Registries regAlias = service.projects().locations().registries();
93+
CloudIot.Projects.Locations.Registries.Devices devAlias = regAlias.devices();
94+
95+
// Remove all devices from the regsitry
96+
List<Device> devices = devAlias.list(registryPath).execute().getDevices();
97+
98+
if (devices != null) {
99+
System.out.println("Found " + devices.size() + " devices");
100+
for (Device d : devices) {
101+
String deviceId = d.getId();
102+
String devicePath = String.format("%s/devices/%s", registryPath, deviceId);
103+
service.projects().locations().registries().devices().delete(devicePath).execute();
104+
}
105+
}
106+
107+
// Delete the registry
108+
service.projects().locations().registries().delete(registryPath).execute();
109+
}
110+
}

iot/api-client/end-to-end-example/src/test/java/com/example/cloud/iot/endtoend/CloudiotPubsubExampleServerTest.java

+44-1
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,14 @@
1616

1717
package com.example.cloud.iot.endtoend;
1818

19+
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
20+
import com.google.api.services.cloudiot.v1.model.DeviceRegistry;
1921
import java.io.ByteArrayOutputStream;
2022
import java.io.IOException;
2123
import java.io.PrintStream;
2224
import java.security.GeneralSecurityException;
25+
import java.util.ArrayList;
26+
import java.util.List;
2327
import org.json.JSONException;
2428
import org.json.JSONObject;
2529
import org.junit.After;
@@ -63,8 +67,19 @@ public void testConfigTurnOn() throws GeneralSecurityException, IOException, JSO
6367
int maxTemp = 11;
6468
JSONObject data = new JSONObject();
6569

70+
try {
71+
CloudiotPubsubExampleServer.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID);
72+
} catch (GoogleJsonResponseException ex) {
73+
if (!ex.isSuccessStatusCode()) {
74+
System.out.println("Cleaning up registry: " + REGISTRY_ID);
75+
// Clean up the 80% of old registries
76+
deleteUnusedOldRegistries(PROJECT_ID, CLOUD_REGION);
77+
// retry since the creation failed.
78+
CloudiotPubsubExampleServer.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID);
79+
}
80+
}
81+
6682
// Set up
67-
CloudiotPubsubExampleServer.createRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID, TOPIC_ID);
6883
CloudiotPubsubExampleServer.createDevice(PROJECT_ID, CLOUD_REGION, REGISTRY_ID, DEVICE_ID);
6984

7085
data.put("temperature", maxTemp);
@@ -80,6 +95,34 @@ public void testConfigTurnOn() throws GeneralSecurityException, IOException, JSO
8095
CloudiotPubsubExampleServer.deleteRegistry(CLOUD_REGION, PROJECT_ID, REGISTRY_ID);
8196
}
8297

98+
private void deleteUnusedOldRegistries(String projectId, String region)
99+
throws IOException, GeneralSecurityException {
100+
// Clean 50 oldest registries with testing prefix in the project.
101+
System.out.println("The maximum number of registries is about to exceed.");
102+
System.out.println("Deleting the oldest 50 registries with IoT Test prefix");
103+
104+
// Gather all the registries into temp list
105+
List<DeviceRegistry> registries = CleanUpHelper.getRegisteries(PROJECT_ID, CLOUD_REGION);
106+
107+
// Filter all registries with prefix.
108+
// since the list is already sorted by currentMillis suffix,
109+
// first 50 will be the oldest.
110+
List<DeviceRegistry> filteredRegistries = new ArrayList<>();
111+
112+
for (int i = 0; i < registries.size(); i++) {
113+
DeviceRegistry registry = registries.get(i);
114+
if (registry.getName().contains("test-registry-")
115+
|| registry.getName().contains("java-reg-")) {
116+
filteredRegistries.add(registry);
117+
}
118+
}
119+
120+
// Delete the 50 oldest registries
121+
for (DeviceRegistry registry : filteredRegistries) {
122+
CleanUpHelper.clearRegistry(CLOUD_REGION, PROJECT_ID, registry.getId());
123+
}
124+
}
125+
83126
@Test
84127
public void testConfigOff() throws GeneralSecurityException, IOException, JSONException {
85128
int minTemp = -1;

0 commit comments

Comments
 (0)