Skip to content

Commit

Permalink
Merge pull request #728 from mziccard/compute
Browse files Browse the repository at this point in the history
Add support for Compute's operations
  • Loading branch information
mziccard committed Mar 16, 2016
2 parents 4e16b54 + cc29929 commit a4f6db9
Show file tree
Hide file tree
Showing 19 changed files with 3,596 additions and 175 deletions.
330 changes: 270 additions & 60 deletions gcloud-java-compute/src/main/java/com/google/gcloud/compute/Compute.java

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,25 @@

final class ComputeImpl extends BaseService<ComputeOptions> implements Compute {

private static class GlobalOperationPageFetcher implements NextPageFetcher<Operation> {

private static final long serialVersionUID = -2488912172182315364L;
private final Map<ComputeRpc.Option, ?> requestOptions;
private final ComputeOptions serviceOptions;

GlobalOperationPageFetcher(ComputeOptions serviceOptions, String cursor,
Map<ComputeRpc.Option, ?> optionMap) {
this.requestOptions =
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
this.serviceOptions = serviceOptions;
}

@Override
public Page<Operation> nextPage() {
return listGlobalOperations(serviceOptions, requestOptions);
}
}

private static class DiskTypePageFetcher implements NextPageFetcher<DiskType> {

private static final long serialVersionUID = -5253916264932522976L;
Expand Down Expand Up @@ -153,6 +172,48 @@ public Page<Zone> nextPage() {
}
}

private static class RegionOperationPageFetcher implements NextPageFetcher<Operation> {

private static final long serialVersionUID = 4111705358926164078L;
private final Map<ComputeRpc.Option, ?> requestOptions;
private final ComputeOptions serviceOptions;
private final String region;

RegionOperationPageFetcher(String region, ComputeOptions serviceOptions, String cursor,
Map<ComputeRpc.Option, ?> optionMap) {
this.requestOptions =
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
this.serviceOptions = serviceOptions;
this.region = region;
}

@Override
public Page<Operation> nextPage() {
return listRegionOperations(region, serviceOptions, requestOptions);
}
}

private static class ZoneOperationPageFetcher implements NextPageFetcher<Operation> {

private static final long serialVersionUID = -9012504536518197793L;
private final Map<ComputeRpc.Option, ?> requestOptions;
private final ComputeOptions serviceOptions;
private final String zone;

ZoneOperationPageFetcher(String zone, ComputeOptions serviceOptions, String cursor,
Map<ComputeRpc.Option, ?> optionMap) {
this.requestOptions =
PageImpl.nextRequestOptions(ComputeRpc.Option.PAGE_TOKEN, cursor, optionMap);
this.serviceOptions = serviceOptions;
this.zone = zone;
}

@Override
public Page<Operation> nextPage() {
return listZoneOperations(zone, serviceOptions, requestOptions);
}
}

private final ComputeRpc computeRpc;

ComputeImpl(ComputeOptions options) {
Expand Down Expand Up @@ -464,6 +525,165 @@ public com.google.api.services.compute.model.License call() {
}
}

@Override
public Operation get(final OperationId operationId, OperationOption... options) {
final Map<ComputeRpc.Option, ?> optionsMap = optionMap(options);
try {
com.google.api.services.compute.model.Operation answer =
runWithRetries(new Callable<com.google.api.services.compute.model.Operation>() {
@Override
public com.google.api.services.compute.model.Operation call() {
switch (operationId.type()) {
case REGION:
RegionOperationId regionOperationId = (RegionOperationId) operationId;
return computeRpc.getRegionOperation(regionOperationId.region(),
regionOperationId.operation(), optionsMap);
case ZONE:
ZoneOperationId zoneOperationId = (ZoneOperationId) operationId;
return computeRpc.getZoneOperation(zoneOperationId.zone(),
zoneOperationId.operation(), optionsMap);
case GLOBAL:
return computeRpc.getGlobalOperation(operationId.operation(), optionsMap);
default:
throw new IllegalArgumentException("Unexpected operation identity type");
}
}
}, options().retryParams(), EXCEPTION_HANDLER);
return answer == null ? null : Operation.fromPb(this, answer);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
}

@Override
public Page<Operation> listGlobalOperations(OperationListOption... options) {
return listGlobalOperations(options(), optionMap(options));
}

private static Page<Operation> listGlobalOperations(final ComputeOptions serviceOptions,
final Map<ComputeRpc.Option, ?> optionsMap) {
try {
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
runWithRetries(new Callable<ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>>>() {
@Override
public ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>> call() {
return serviceOptions.rpc().listGlobalOperations(optionsMap);
}
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
String cursor = result.x();
Iterable<Operation> operations = Iterables.transform(
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
: result.y(),
new Function<com.google.api.services.compute.model.Operation, Operation>() {
@Override
public Operation apply(com.google.api.services.compute.model.Operation operation) {
return Operation.fromPb(serviceOptions.service(), operation);
}
});
return new PageImpl<>(new GlobalOperationPageFetcher(serviceOptions, cursor, optionsMap),
cursor, operations);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
}

@Override
public Page<Operation> listRegionOperations(String region, OperationListOption... options) {
return listRegionOperations(region, options(), optionMap(options));
}

private static Page<Operation> listRegionOperations(final String region,
final ComputeOptions serviceOptions, final Map<ComputeRpc.Option, ?> optionsMap) {
try {
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
runWithRetries(new Callable<ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>>>() {
@Override
public ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>> call() {
return serviceOptions.rpc().listRegionOperations(region, optionsMap);
}
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
String cursor = result.x();
Iterable<Operation> operations = Iterables.transform(
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
: result.y(),
new Function<com.google.api.services.compute.model.Operation, Operation>() {
@Override
public Operation apply(com.google.api.services.compute.model.Operation operation) {
return Operation.fromPb(serviceOptions.service(), operation);
}
});
return new PageImpl<>(new RegionOperationPageFetcher(region, serviceOptions, cursor,
optionsMap), cursor, operations);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
}

@Override
public Page<Operation> listZoneOperations(String zone, OperationListOption... options) {
return listZoneOperations(zone, options(), optionMap(options));
}

private static Page<Operation> listZoneOperations(final String zone,
final ComputeOptions serviceOptions, final Map<ComputeRpc.Option, ?> optionsMap) {
try {
ComputeRpc.Tuple<String, Iterable<com.google.api.services.compute.model.Operation>> result =
runWithRetries(new Callable<ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>>>() {
@Override
public ComputeRpc.Tuple<String,
Iterable<com.google.api.services.compute.model.Operation>> call() {
return serviceOptions.rpc().listZoneOperations(zone, optionsMap);
}
}, serviceOptions.retryParams(), EXCEPTION_HANDLER);
String cursor = result.x();
Iterable<Operation> operations = Iterables.transform(
result.y() == null ? ImmutableList.<com.google.api.services.compute.model.Operation>of()
: result.y(),
new Function<com.google.api.services.compute.model.Operation, Operation>() {
@Override
public Operation apply(com.google.api.services.compute.model.Operation operation) {
return Operation.fromPb(serviceOptions.service(), operation);
}
});
return new PageImpl<>(new ZoneOperationPageFetcher(zone, serviceOptions, cursor, optionsMap),
cursor, operations);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
}

@Override
public boolean delete(final OperationId operation) {
try {
return runWithRetries(new Callable<Boolean>() {
@Override
public Boolean call() {
switch (operation.type()) {
case REGION:
RegionOperationId regionOperationId = (RegionOperationId) operation;
return computeRpc.deleteRegionOperation(regionOperationId.region(),
regionOperationId.operation());
case ZONE:
ZoneOperationId zoneOperationId = (ZoneOperationId) operation;
return computeRpc.deleteZoneOperation(zoneOperationId.zone(),
zoneOperationId.operation());
case GLOBAL:
return computeRpc.deleteGlobalOperation(operation.operation());
default:
throw new IllegalArgumentException("Unexpected operation identity type");
}
}
}, options().retryParams(), EXCEPTION_HANDLER);
} catch (RetryHelper.RetryHelperException e) {
throw ComputeException.translateAndThrow(e);
}
}

private Map<ComputeRpc.Option, ?> optionMap(Option... options) {
Map<ComputeRpc.Option, Object> optionMap = Maps.newEnumMap(ComputeRpc.Option.class);
for (Option option : options) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
*
* @see <a href="https://cloud.google.com/compute/docs/reference/latest/diskTypes">Disk Types</a>
*/
public final class DiskType implements Serializable {
public class DiskType implements Serializable {

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

@Override
public int hashCode() {
public final int hashCode() {
return Objects.hash(diskTypeId);
}

@Override
public boolean equals(Object obj) {
public final boolean equals(Object obj) {
return obj instanceof DiskType && Objects.equals(toPb(), ((DiskType) obj).toPb());
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/*
* Copyright 2016 Google Inc. All Rights Reserved.
*
* 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 com.google.gcloud.compute;

import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.base.MoreObjects;

import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* Identity for a Google Compute Engine global operation.
*/
public class GlobalOperationId extends ResourceId implements OperationId {

private static final String REGEX = ResourceId.REGEX + "global/operations/([^/]+)";
private static final Pattern PATTERN = Pattern.compile(REGEX);
private static final long serialVersionUID = 3945756772641577962L;

private final String operation;

private GlobalOperationId(String project, String operation) {
super(project);
this.operation = checkNotNull(operation);
}

@Override
public Type type() {
return Type.GLOBAL;
}

@Override
public String operation() {
return operation;
}

@Override
public String selfLink() {
return super.selfLink() + "/global/operations/" + operation;
}

@Override
MoreObjects.ToStringHelper toStringHelper() {
return super.toStringHelper().add("operation", operation);
}

@Override
public int hashCode() {
return Objects.hash(baseHashCode(), operation);
}

@Override
public boolean equals(Object obj) {
return obj instanceof GlobalOperationId
&& baseEquals((GlobalOperationId) obj)
&& Objects.equals(operation, ((GlobalOperationId) obj).operation);
}

@Override
GlobalOperationId setProjectId(String projectId) {
if (project() != null) {
return this;
}
return GlobalOperationId.of(projectId, operation);
}

/**
* Returns a global operation identity given the operation name.
*/
public static GlobalOperationId of(String operation) {
return new GlobalOperationId(null, operation);
}

/**
* Returns a global operation identity given project and operation names.
*/
public static GlobalOperationId of(String project, String operation) {
return new GlobalOperationId(project, operation);
}

/**
* Returns {@code true} if the provided string matches the expected format of a global operation
* URL. Returns {@code false} otherwise.
*/
static boolean matchesUrl(String url) {
return PATTERN.matcher(url).matches();
}

static GlobalOperationId fromUrl(String url) {
Matcher matcher = PATTERN.matcher(url);
if (!matcher.matches()) {
throw new IllegalArgumentException(url + " is not a valid global operation URL");
}
return GlobalOperationId.of(matcher.group(1), matcher.group(2));
}
}
Loading

0 comments on commit a4f6db9

Please sign in to comment.