Skip to content

Commit 1e247e8

Browse files
author
Ajay Kannan
committed
---
yaml --- r: 6635 b: refs/heads/tswast-patch-1 c: 4fdd477 h: refs/heads/master i: 6633: f55a606 6631: 10daa51
1 parent 197f4f0 commit 1e247e8

3 files changed

Lines changed: 61 additions & 45 deletions

File tree

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,5 +57,5 @@ refs/tags/v0.18.0: 9d193c4c4b9d1c6f21515dd8e50836b9194ec9bb
5757
refs/tags/v0.19.0: e67b56e4d8dad5f9a7b38c9b2107c23c828f2ed5
5858
refs/tags/v0.20.0: 839f7fb7156535146aa1cb2c5aadd8d375d854e8
5959
refs/tags/v0.20.1: 370471f437f1f4f68a11e068df5cd6bf39edb1fa
60-
refs/heads/tswast-patch-1: 19aa650e3a452f312c106e06ba247afb05cae29b
60+
refs/heads/tswast-patch-1: 4fdd477e02fbedfc4faa620096b67064f3287597
6161
refs/heads/pubsub-streaming-pull: 19262b752ee874eb2ca3b950eb2aef44d5a5267b

branches/tswast-patch-1/gcloud-java-resourcemanager/src/main/java/com/google/gcloud/resourcemanager/testing/LocalResourceManagerHelper.java

Lines changed: 55 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.Random;
3535
import java.util.Set;
3636
import java.util.concurrent.ConcurrentHashMap;
37+
import java.util.logging.Level;
3738
import java.util.logging.Logger;
3839
import java.util.zip.GZIPInputStream;
3940

@@ -51,6 +52,19 @@ public class LocalResourceManagerHelper {
5152
private static final Random PROJECT_NUMBER_GENERATOR = new Random();
5253
private static final String VERSION = "v1beta1";
5354
private static final String CONTEXT = "/" + VERSION + "/projects";
55+
private static final URI BASE_CONTEXT;
56+
private static final Set<String> SUPPORTED_COMPRESSION_ENCODINGS =
57+
ImmutableSet.of("gzip", "x-gzip");
58+
59+
static {
60+
try {
61+
BASE_CONTEXT = new URI(CONTEXT);
62+
} catch (URISyntaxException e) {
63+
log.log(Level.WARNING, "URI.", e);
64+
throw new RuntimeException(
65+
"Could not initialize LocalResourceManagerHelper due to URISyntaxException.", e);
66+
}
67+
}
5468

5569
// see https://cloud.google.com/resource-manager/reference/rest/v1beta1/projects
5670
private static final Set<Character> PERMISSIBLE_PROJECT_NAME_PUNCTUATION =
@@ -60,7 +74,7 @@ public class LocalResourceManagerHelper {
6074
private final ConcurrentHashMap<String, Project> projects = new ConcurrentHashMap<>();
6175
private final int port;
6276

63-
static class Response {
77+
private static class Response {
6478
private final int code;
6579
private final String body;
6680

@@ -78,7 +92,7 @@ String body() {
7892
}
7993
}
8094

81-
enum Error {
95+
private enum Error {
8296
ALREADY_EXISTS(409, "global", "alreadyExists", "ALREADY_EXISTS"),
8397
PERMISSION_DENIED(403, "global", "forbidden", "PERMISSION_DENIED"),
8498
// change failed precondition error code to 412 when #440 is fixed
@@ -126,37 +140,27 @@ private class RequestHandler implements HttpHandler {
126140
@Override
127141
public void handle(HttpExchange exchange) {
128142
// see https://cloud.google.com/resource-manager/reference/rest/
129-
Response response = null;
130-
URI baseContext = null;
131-
try {
132-
baseContext = new URI(CONTEXT);
133-
} catch (URISyntaxException e) {
134-
writeResponse(
135-
exchange,
136-
Error.INTERNAL_ERROR.response(
137-
"URI syntax exception when constructing URI from the path '" + CONTEXT + "'"));
138-
return;
139-
}
140-
String path = baseContext.relativize(exchange.getRequestURI()).getPath();
143+
Response response;
144+
String path = BASE_CONTEXT.relativize(exchange.getRequestURI()).getPath();
141145
String requestMethod = exchange.getRequestMethod();
142146
try {
143147
switch (requestMethod) {
144148
case "POST":
145-
if (path.contains(":undelete")) {
146-
response = undelete(projectIdFromURI(path));
149+
if (path.endsWith(":undelete")) {
150+
response = undelete(projectIdFromUri(path));
147151
} else {
148152
String requestBody =
149153
decodeContent(exchange.getRequestHeaders(), exchange.getRequestBody());
150154
response = create(jsonFactory.fromString(requestBody, Project.class));
151155
}
152156
break;
153157
case "DELETE":
154-
response = delete(projectIdFromURI(path));
158+
response = delete(projectIdFromUri(path));
155159
break;
156160
case "GET":
157161
if (!path.isEmpty()) {
158162
response =
159-
get(projectIdFromURI(path), parseFields(exchange.getRequestURI().getQuery()));
163+
get(projectIdFromUri(path), parseFields(exchange.getRequestURI().getQuery()));
160164
} else {
161165
response = list(parseListOptions(exchange.getRequestURI().getQuery()));
162166
}
@@ -165,10 +169,12 @@ public void handle(HttpExchange exchange) {
165169
String requestBody =
166170
decodeContent(exchange.getRequestHeaders(), exchange.getRequestBody());
167171
response =
168-
replace(projectIdFromURI(path), jsonFactory.fromString(requestBody, Project.class));
172+
replace(projectIdFromUri(path), jsonFactory.fromString(requestBody, Project.class));
169173
break;
170174
default:
171-
response = Error.BAD_REQUEST.response("The server could not understand the request.");
175+
response = Error.BAD_REQUEST.response(
176+
"The server could not understand the following request URI: " + requestMethod + " "
177+
+ path);
172178
}
173179
} catch (IOException e) {
174180
response = Error.BAD_REQUEST.response(e.getMessage());
@@ -185,7 +191,7 @@ private static void writeResponse(HttpExchange exchange, Response response) {
185191
outputStream.write(response.body().getBytes(StandardCharsets.UTF_8));
186192
outputStream.close();
187193
} catch (IOException e) {
188-
log.info("IOException encountered when sending response.");
194+
log.log(Level.WARNING, "IOException encountered when sending response.", e);
189195
}
190196
}
191197

@@ -194,10 +200,12 @@ private static String decodeContent(Headers headers, InputStream inputStream) th
194200
InputStream input = inputStream;
195201
try {
196202
if (contentEncoding != null && !contentEncoding.isEmpty()) {
197-
if (contentEncoding.get(0).equals("gzip") || contentEncoding.get(0).equals("x-gzip")) {
203+
String encoding = contentEncoding.get(0);
204+
if (SUPPORTED_COMPRESSION_ENCODINGS.contains(encoding)) {
198205
input = new GZIPInputStream(inputStream);
199-
} else if (!contentEncoding.equals("identity")) {
200-
throw new IOException("The request has an unsupported HTTP content encoding.");
206+
} else if (!encoding.equals("identity")) {
207+
throw new IOException(
208+
"The request has the following unsupported HTTP content encoding: " + encoding);
201209
}
202210
}
203211
return new String(ByteStreams.toByteArray(input), StandardCharsets.UTF_8);
@@ -206,7 +214,7 @@ private static String decodeContent(Headers headers, InputStream inputStream) th
206214
}
207215
}
208216

209-
private static String projectIdFromURI(String path) throws IOException {
217+
private static String projectIdFromUri(String path) throws IOException {
210218
if (path.isEmpty()) {
211219
throw new IOException("The URI path '" + path + "' doesn't have a project ID.");
212220
}
@@ -286,7 +294,7 @@ private static final boolean isValidIdOrLabel(String value, int minLength, int m
286294
return false;
287295
}
288296
}
289-
if (value.length() > 0 && (!Character.isLetter(value.charAt(0)) || value.endsWith("-"))) {
297+
if (!value.isEmpty() && (!Character.isLetter(value.charAt(0)) || value.endsWith("-"))) {
290298
return false;
291299
}
292300
return value.length() >= minLength && value.length() <= maxLength;
@@ -316,7 +324,9 @@ Response create(Project project) {
316324
Response delete(String projectId) {
317325
Project project = projects.get(projectId);
318326
if (project == null) {
319-
// when possible, change this to 404 (#440)
327+
// Currently the service returns 403 Permission Denied when trying to delete a project that
328+
// doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
329+
// 404 Not Found error when the service fixes this (#440).
320330
return Error.PERMISSION_DENIED.response(
321331
"Error when deleting " + projectId + " because the project was not found.");
322332
}
@@ -331,7 +341,9 @@ Response delete(String projectId) {
331341

332342
Response get(String projectId, String[] fields) {
333343
if (!projects.containsKey(projectId)) {
334-
// when possible, change this to 404 (#440)
344+
// Currently the service returns 403 Permission Denied when trying to get a project that
345+
// doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
346+
// 404 Not Found error when the service fixes this (#440).
335347
return Error.PERMISSION_DENIED.response("Project " + projectId + " not found.");
336348
}
337349
Project project = projects.get(projectId);
@@ -385,16 +397,17 @@ private static boolean includeProject(Project project, String[] filters) {
385397
}
386398
for (String filter : filters) {
387399
String[] filterEntry = filter.toLowerCase().split(":");
388-
if ("id".equals(filterEntry[0])) {
400+
String filterType = filterEntry[0];
401+
if ("id".equals(filterType)) {
389402
if (!satisfiesFilter(project.getProjectId(), filterEntry[1])) {
390403
return false;
391404
}
392-
} else if ("name".equals(filterEntry[0])) {
405+
} else if ("name".equals(filterType)) {
393406
if (!satisfiesFilter(project.getName(), filterEntry[1])) {
394407
return false;
395408
}
396-
} else if (filterEntry[0].startsWith("labels")) {
397-
String labelKey = filterEntry[0].split("\\.")[1];
409+
} else if (filterType.startsWith("labels.")) {
410+
String labelKey = filterType.substring("labels.".length());
398411
if (project.getLabels() != null) {
399412
String labelValue = project.getLabels().get(labelKey);
400413
if (!satisfiesFilter(labelValue, filterEntry[1])) {
@@ -410,7 +423,7 @@ private static boolean satisfiesFilter(String projectValue, String filterValue)
410423
if (projectValue == null) {
411424
return false;
412425
}
413-
return "*".equals(filterValue) ? true : filterValue.equals(projectValue.toLowerCase());
426+
return "*".equals(filterValue) || filterValue.equals(projectValue.toLowerCase());
414427
}
415428

416429
private static Project extractFields(Project fullProject, String[] fields) {
@@ -449,7 +462,9 @@ private static Project extractFields(Project fullProject, String[] fields) {
449462
Response replace(String projectId, Project project) {
450463
Project originalProject = projects.get(projectId);
451464
if (originalProject == null) {
452-
// when possible, change this to 404 (#440)
465+
// Currently the service returns 403 Permission Denied when trying to replace a project that
466+
// doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
467+
// 404 Not Found error when the service fixes this (#440).
453468
return Error.PERMISSION_DENIED.response(
454469
"Error when replacing " + projectId + " because the project was not found.");
455470
} else if (!originalProject.getLifecycleState().equals("ACTIVE")) {
@@ -474,7 +489,9 @@ Response undelete(String projectId) {
474489
Project project = projects.get(projectId);
475490
Response response;
476491
if (project == null) {
477-
// when possible, change this to 404 (#440)
492+
// Currently the service returns 403 Permission Denied when trying to undelete a project that
493+
// doesn't exist. Here we mimic this behavior, but this line should be changed to throw a
494+
// 404 Not Found error when the service fixes this (#440).
478495
response = Error.PERMISSION_DENIED.response(
479496
"Error when undeleting " + projectId + " because the project was not found.");
480497
} else if (!project.getLifecycleState().equals("DELETE_REQUESTED")) {
@@ -488,9 +505,8 @@ Response undelete(String projectId) {
488505
}
489506

490507
private LocalResourceManagerHelper() {
491-
InetSocketAddress addr = new InetSocketAddress(0);
492508
try {
493-
server = HttpServer.create(addr, 0);
509+
server = HttpServer.create(new InetSocketAddress(0), 0);
494510
port = server.getAddress().getPort();
495511
server.createContext(CONTEXT, new RequestHandler());
496512
} catch (IOException e) {
@@ -550,9 +566,9 @@ public boolean changeLifecycleState(String projectId, String lifecycleState) {
550566
* <p>This method can be used to fully remove a project (to mimic when the server completely
551567
* deletes a project).
552568
*
553-
* @return true if the project was successfully deleted, false otherwise.
569+
* @return true if the project was successfully deleted, false if the project didn't exist.
554570
*/
555571
public boolean removeProject(String projectId) {
556-
return projects.remove(checkNotNull(projectId)) != null ? true : false;
572+
return projects.remove(checkNotNull(projectId)) != null;
557573
}
558574
}

branches/tswast-patch-1/gcloud-java-resourcemanager/src/test/java/com/google/gcloud/resourcemanager/LocalResourceManagerHelperTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,9 @@ private static com.google.api.services.cloudresourcemanager.model.Project copyFr
6868
}
6969

7070
private void clearProjects() {
71-
Iterator<com.google.api.services.cloudresourcemanager.model.Project> it =
72-
rpc.list(EMPTY_RPC_OPTIONS).y().iterator();
73-
while (it.hasNext()) {
74-
RESOURCE_MANAGER_HELPER.removeProject(it.next().getProjectId());
71+
for (com.google.api.services.cloudresourcemanager.model.Project project :
72+
rpc.list(EMPTY_RPC_OPTIONS).y()) {
73+
RESOURCE_MANAGER_HELPER.removeProject(project.getProjectId());
7574
}
7675
}
7776

@@ -196,7 +195,8 @@ public void testIsInvalidProjectLabels() {
196195
for (int i = 0; i < 257; i++) {
197196
tooManyLabels.put("k" + Integer.toString(i), "v" + Integer.toString(i));
198197
}
199-
expectInvalidArgumentException(project, invalidLabelMessageSubstring);
198+
project.setLabels(tooManyLabels);
199+
expectInvalidArgumentException(project, "exceeds the limit of 256 labels");
200200
project.setLabels(ImmutableMap.of("k-1", ""));
201201
rpc.create(project);
202202
assertNotNull(rpc.get(project.getProjectId(), EMPTY_RPC_OPTIONS));

0 commit comments

Comments
 (0)