Skip to content

Commit a4f6db9

Browse files
committed
Merge pull request #728 from mziccard/compute
Add support for Compute's operations
2 parents 4e16b54 + cc29929 commit a4f6db9

19 files changed

Lines changed: 3596 additions & 175 deletions

gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java

Lines changed: 270 additions & 60 deletions
Large diffs are not rendered by default.

gcloud-java-compute/src/main/java/com/google/gcloud/compute/ComputeImpl.java

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,25 @@
3535

3636
final class ComputeImpl extends BaseService<ComputeOptions> implements Compute {
3737

38+
private static class GlobalOperationPageFetcher implements NextPageFetcher<Operation> {
39+
40+
private static final long serialVersionUID = -2488912172182315364L;
41+
private final Map<ComputeRpc.Option, ?> requestOptions;
42+
private final ComputeOptions serviceOptions;
43+
44+
GlobalOperationPageFetcher(ComputeOptions serviceOptions, String cursor,
45+
Map<ComputeRpc.Option, ?> optionMap) {
46+
this.requestOptions =
47+
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
48+
this.serviceOptions = serviceOptions;
49+
}
50+
51+
@Override
52+
public Page<Operation> nextPage() {
53+
return listGlobalOperations(serviceOptions, requestOptions);
54+
}
55+
}
56+
3857
private static class DiskTypePageFetcher implements NextPageFetcher<DiskType> {
3958

4059
private static final long serialVersionUID = -5253916264932522976L;
@@ -153,6 +172,48 @@ public Page<Zone> nextPage() {
153172
}
154173
}
155174

175+
private static class RegionOperationPageFetcher implements NextPageFetcher<Operation> {
176+
177+
private static final long serialVersionUID = 4111705358926164078L;
178+
private final Map<ComputeRpc.Option, ?> requestOptions;
179+
private final ComputeOptions serviceOptions;
180+
private final String region;
181+
182+
RegionOperationPageFetcher(String region, ComputeOptions serviceOptions, String cursor,
183+
Map<ComputeRpc.Option, ?> optionMap) {
184+
this.requestOptions =
185+
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
186+
this.serviceOptions = serviceOptions;
187+
this.region = region;
188+
}
189+
190+
@Override
191+
public Page<Operation> nextPage() {
192+
return listRegionOperations(region, serviceOptions, requestOptions);
193+
}
194+
}
195+
196+
private static class ZoneOperationPageFetcher implements NextPageFetcher<Operation> {
197+
198+
private static final long serialVersionUID = -9012504536518197793L;
199+
private final Map<ComputeRpc.Option, ?> requestOptions;
200+
private final ComputeOptions serviceOptions;
201+
private final String zone;
202+
203+
ZoneOperationPageFetcher(String zone, ComputeOptions serviceOptions, String cursor,
204+
Map<ComputeRpc.Option, ?> optionMap) {
205+
this.requestOptions =
206+
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
207+
this.serviceOptions = serviceOptions;
208+
this.zone = zone;
209+
}
210+
211+
@Override
212+
public Page<Operation> nextPage() {
213+
return listZoneOperations(zone, serviceOptions, requestOptions);
214+
}
215+
}
216+
156217
private final ComputeRpc computeRpc;
157218

158219
ComputeImpl(ComputeOptions options) {
@@ -464,6 +525,165 @@ public com.google.api.services.compute.model.License call() {
464525
}
465526
}
466527

528+
@Override
529+
public Operation get(final OperationId operationId, OperationOption... options) {
530+
final Map<ComputeRpc.Option, ?> optionsMap = optionMap(options);
531+
try {
532+
com.google.api.services.compute.model.Operation answer =
533+
runWithRetries(new Callable<com.google.api.services.compute.model.Operation>() {
534+
@Override
535+
public com.google.api.services.compute.model.Operation call() {
536+
switch (operationId.type()) {
537+
case REGION:
538+
RegionOperationId regionOperationId = (RegionOperationId) operationId;
539+
return computeRpc.getRegionOperation(regionOperationId.region(),
540+
regionOperationId.operation(), optionsMap);
541+
case ZONE:
542+
ZoneOperationId zoneOperationId = (ZoneOperationId) operationId;
543+
return computeRpc.getZoneOperation(zoneOperationId.zone(),
544+
zoneOperationId.operation(), optionsMap);
545+
case GLOBAL:
546+
return computeRpc.getGlobalOperation(operationId.operation(), optionsMap);
547+
default:
548+
throw new IllegalArgumentException("Unexpected operation identity type");
549+
}
550+
}
551+
}, options().retryParams(), EXCEPTION_HANDLER);
552+
return answer == null ? null : Operation.fromPb(this, answer);
553+
} catch (RetryHelper.RetryHelperException e) {
554+
throw ComputeException.translateAndThrow(e);
555+
}
556+
}
557+
558+
@Override
559+
public Page<Operation> listGlobalOperations(OperationListOption... options) {
560+
return listGlobalOperations(options(), optionMap(options));
561+
}
562+
563+
private static Page<Operation> listGlobalOperations(final ComputeOptions serviceOptions,
564+
final Map<ComputeRpc.Option, ?> optionsMap) {
565+
try {
566+
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
567+
runWithRetries(new Callable<ComputeRpc.Tuple<String,
568+
Iterable<com.google.api.services.compute.model.Operation>>>() {
569+
@Override
570+
public ComputeRpc.Tuple<String,
571+
Iterable<com.google.api.services.compute.model.Operation>> call() {
572+
return serviceOptions.rpc().listGlobalOperations(optionsMap);
573+
}
574+
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
575+
String cursor = result.x();
576+
Iterable<Operation> operations = Iterables.transform(
577+
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
578+
: result.y(),
579+
new Function<com.google.api.services.compute.model.Operation, Operation>() {
580+
@Override
581+
public Operation apply(com.google.api.services.compute.model.Operation operation) {
582+
return Operation.fromPb(serviceOptions.service(), operation);
583+
}
584+
});
585+
return new PageImpl<>(new GlobalOperationPageFetcher(serviceOptions, cursor, optionsMap),
586+
cursor, operations);
587+
} catch (RetryHelper.RetryHelperException e) {
588+
throw ComputeException.translateAndThrow(e);
589+
}
590+
}
591+
592+
@Override
593+
public Page<Operation> listRegionOperations(String region, OperationListOption... options) {
594+
return listRegionOperations(region, options(), optionMap(options));
595+
}
596+
597+
private static Page<Operation> listRegionOperations(final String region,
598+
final ComputeOptions serviceOptions, final Map<ComputeRpc.Option, ?> optionsMap) {
599+
try {
600+
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
601+
runWithRetries(new Callable<ComputeRpc.Tuple<String,
602+
Iterable<com.google.api.services.compute.model.Operation>>>() {
603+
@Override
604+
public ComputeRpc.Tuple<String,
605+
Iterable<com.google.api.services.compute.model.Operation>> call() {
606+
return serviceOptions.rpc().listRegionOperations(region, optionsMap);
607+
}
608+
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
609+
String cursor = result.x();
610+
Iterable<Operation> operations = Iterables.transform(
611+
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
612+
: result.y(),
613+
new Function<com.google.api.services.compute.model.Operation, Operation>() {
614+
@Override
615+
public Operation apply(com.google.api.services.compute.model.Operation operation) {
616+
return Operation.fromPb(serviceOptions.service(), operation);
617+
}
618+
});
619+
return new PageImpl<>(new RegionOperationPageFetcher(region, serviceOptions, cursor,
620+
optionsMap), cursor, operations);
621+
} catch (RetryHelper.RetryHelperException e) {
622+
throw ComputeException.translateAndThrow(e);
623+
}
624+
}
625+
626+
@Override
627+
public Page<Operation> listZoneOperations(String zone, OperationListOption... options) {
628+
return listZoneOperations(zone, options(), optionMap(options));
629+
}
630+
631+
private static Page<Operation> listZoneOperations(final String zone,
632+
final ComputeOptions serviceOptions, final Map<ComputeRpc.Option, ?> optionsMap) {
633+
try {
634+
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
635+
runWithRetries(new Callable<ComputeRpc.Tuple<String,
636+
Iterable<com.google.api.services.compute.model.Operation>>>() {
637+
@Override
638+
public ComputeRpc.Tuple<String,
639+
Iterable<com.google.api.services.compute.model.Operation>> call() {
640+
return serviceOptions.rpc().listZoneOperations(zone, optionsMap);
641+
}
642+
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
643+
String cursor = result.x();
644+
Iterable<Operation> operations = Iterables.transform(
645+
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
646+
: result.y(),
647+
new Function<com.google.api.services.compute.model.Operation, Operation>() {
648+
@Override
649+
public Operation apply(com.google.api.services.compute.model.Operation operation) {
650+
return Operation.fromPb(serviceOptions.service(), operation);
651+
}
652+
});
653+
return new PageImpl<>(new ZoneOperationPageFetcher(zone, serviceOptions, cursor, optionsMap),
654+
cursor, operations);
655+
} catch (RetryHelper.RetryHelperException e) {
656+
throw ComputeException.translateAndThrow(e);
657+
}
658+
}
659+
660+
@Override
661+
public boolean delete(final OperationId operation) {
662+
try {
663+
return runWithRetries(new Callable<Boolean>() {
664+
@Override
665+
public Boolean call() {
666+
switch (operation.type()) {
667+
case REGION:
668+
RegionOperationId regionOperationId = (RegionOperationId) operation;
669+
return computeRpc.deleteRegionOperation(regionOperationId.region(),
670+
regionOperationId.operation());
671+
case ZONE:
672+
ZoneOperationId zoneOperationId = (ZoneOperationId) operation;
673+
return computeRpc.deleteZoneOperation(zoneOperationId.zone(),
674+
zoneOperationId.operation());
675+
case GLOBAL:
676+
return computeRpc.deleteGlobalOperation(operation.operation());
677+
default:
678+
throw new IllegalArgumentException("Unexpected operation identity type");
679+
}
680+
}
681+
}, options().retryParams(), EXCEPTION_HANDLER);
682+
} catch (RetryHelper.RetryHelperException e) {
683+
throw ComputeException.translateAndThrow(e);
684+
}
685+
}
686+
467687
private Map<ComputeRpc.Option, ?> optionMap(Option... options) {
468688
Map<ComputeRpc.Option, Object> optionMap = Maps.newEnumMap(ComputeRpc.Option.class);
469689
for (Option option : options) {

gcloud-java-compute/src/main/java/com/google/gcloud/compute/DiskType.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*
3333
* @see <a href="https://cloud.google.com/compute/docs/reference/latest/diskTypes">Disk Types</a>
3434
*/
35-
public final class DiskType implements Serializable {
35+
public class DiskType implements Serializable {
3636

3737
static final Function<com.google.api.services.compute.model.DiskType, DiskType> FROM_PB_FUNCTION =
3838
new Function<com.google.api.services.compute.model.DiskType, DiskType>() {
@@ -186,12 +186,12 @@ public String toString() {
186186
}
187187

188188
@Override
189-
public int hashCode() {
189+
public final int hashCode() {
190190
return Objects.hash(diskTypeId);
191191
}
192192

193193
@Override
194-
public boolean equals(Object obj) {
194+
public final boolean equals(Object obj) {
195195
return obj instanceof DiskType && Objects.equals(toPb(), ((DiskType) obj).toPb());
196196
}
197197

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
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.google.gcloud.compute;
18+
19+
import static com.google.common.base.Preconditions.checkNotNull;
20+
21+
import com.google.common.base.MoreObjects;
22+
23+
import java.util.Objects;
24+
import java.util.regex.Matcher;
25+
import java.util.regex.Pattern;
26+
27+
/**
28+
* Identity for a Google Compute Engine global operation.
29+
*/
30+
public class GlobalOperationId extends ResourceId implements OperationId {
31+
32+
private static final String REGEX = ResourceId.REGEX + "global/operations/([^/]+)";
33+
private static final Pattern PATTERN = Pattern.compile(REGEX);
34+
private static final long serialVersionUID = 3945756772641577962L;
35+
36+
private final String operation;
37+
38+
private GlobalOperationId(String project, String operation) {
39+
super(project);
40+
this.operation = checkNotNull(operation);
41+
}
42+
43+
@Override
44+
public Type type() {
45+
return Type.GLOBAL;
46+
}
47+
48+
@Override
49+
public String operation() {
50+
return operation;
51+
}
52+
53+
@Override
54+
public String selfLink() {
55+
return super.selfLink() + "/global/operations/" + operation;
56+
}
57+
58+
@Override
59+
MoreObjects.ToStringHelper toStringHelper() {
60+
return super.toStringHelper().add("operation", operation);
61+
}
62+
63+
@Override
64+
public int hashCode() {
65+
return Objects.hash(baseHashCode(), operation);
66+
}
67+
68+
@Override
69+
public boolean equals(Object obj) {
70+
return obj instanceof GlobalOperationId
71+
&& baseEquals((GlobalOperationId) obj)
72+
&& Objects.equals(operation, ((GlobalOperationId) obj).operation);
73+
}
74+
75+
@Override
76+
GlobalOperationId setProjectId(String projectId) {
77+
if (project() != null) {
78+
return this;
79+
}
80+
return GlobalOperationId.of(projectId, operation);
81+
}
82+
83+
/**
84+
* Returns a global operation identity given the operation name.
85+
*/
86+
public static GlobalOperationId of(String operation) {
87+
return new GlobalOperationId(null, operation);
88+
}
89+
90+
/**
91+
* Returns a global operation identity given project and operation names.
92+
*/
93+
public static GlobalOperationId of(String project, String operation) {
94+
return new GlobalOperationId(project, operation);
95+
}
96+
97+
/**
98+
* Returns {@code true} if the provided string matches the expected format of a global operation
99+
* URL. Returns {@code false} otherwise.
100+
*/
101+
static boolean matchesUrl(String url) {
102+
return PATTERN.matcher(url).matches();
103+
}
104+
105+
static GlobalOperationId fromUrl(String url) {
106+
Matcher matcher = PATTERN.matcher(url);
107+
if (!matcher.matches()) {
108+
throw new IllegalArgumentException(url + " is not a valid global operation URL");
109+
}
110+
return GlobalOperationId.of(matcher.group(1), matcher.group(2));
111+
}
112+
}

0 commit comments

Comments
 (0)