Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Compute's operations #728

Merged
merged 6 commits into from
Mar 16, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

This comment was marked as spam.

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