From e213176f7f4f201969a4d301711f60def3943d5f Mon Sep 17 00:00:00 2001 From: Marco Ziccardi Date: Wed, 20 Apr 2016 13:46:55 +0200 Subject: [PATCH] Add support for batches to DNS (#940) --- .../java/com/google/cloud/BatchResult.java | 108 ++ .../com/google/cloud/BatchResultTest.java | 113 ++ gcloud-java-dns/pom.xml | 5 + .../com/google/cloud/dns/ChangeRequest.java | 4 +- .../main/java/com/google/cloud/dns/Dns.java | 5 + .../java/com/google/cloud/dns/DnsBatch.java | 354 ++++++ .../com/google/cloud/dns/DnsBatchResult.java | 38 + .../com/google/cloud/dns/DnsException.java | 5 + .../java/com/google/cloud/dns/DnsImpl.java | 38 +- .../java/com/google/cloud/dns/RecordSet.java | 2 +- .../google/cloud/dns/spi/DefaultDnsRpc.java | 268 +++- .../java/com/google/cloud/dns/spi/DnsRpc.java | 5 + .../com/google/cloud/dns/spi/RpcBatch.java | 117 ++ .../cloud/dns/testing/LocalDnsHelper.java | 126 +- .../google/cloud/dns/DnsBatchResultTest.java | 109 ++ .../com/google/cloud/dns/DnsBatchTest.java | 632 ++++++++++ .../com/google/cloud/dns/DnsImplTest.java | 22 +- .../google/cloud/dns/SerializationTest.java | 2 + .../com/google/cloud/dns/it/ITDnsTest.java | 1068 ++++++++++++++-- .../cloud/dns/testing/LocalDnsHelperTest.java | 1074 ++++++++++++++++- 20 files changed, 3942 insertions(+), 153 deletions(-) create mode 100644 gcloud-java-core/src/main/java/com/google/cloud/BatchResult.java create mode 100644 gcloud-java-core/src/test/java/com/google/cloud/BatchResultTest.java create mode 100644 gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatch.java create mode 100644 gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatchResult.java create mode 100644 gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/RpcBatch.java create mode 100644 gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchResultTest.java create mode 100644 gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchTest.java diff --git a/gcloud-java-core/src/main/java/com/google/cloud/BatchResult.java b/gcloud-java-core/src/main/java/com/google/cloud/BatchResult.java new file mode 100644 index 000000000000..fb78409ea31e --- /dev/null +++ b/gcloud-java-core/src/main/java/com/google/cloud/BatchResult.java @@ -0,0 +1,108 @@ +/* + * 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.cloud; + +import static com.google.common.base.Preconditions.checkNotNull; +import static com.google.common.base.Preconditions.checkState; + +import java.util.LinkedList; +import java.util.List; + +/** + * This class holds a single result of a batch call. The class is not thread-safe. + * + * @param the type of the result + * @param the type of the service-dependent exception thrown when a processing error occurs + * + */ +public abstract class BatchResult { + + private T result; + private boolean completed = false; + private E error; + private final List> toBeNotified = new LinkedList<>(); + + /** + * Returns {@code true} if the batch has been completed and the result is available; {@code false} + * otherwise. + */ + public boolean completed() { + return completed; + } + + /** + * Returns the result of this call. + * + * @throws IllegalStateException if the batch has not been completed yet + * @throws E if an error occurred when processing the batch request + */ + public T get() throws E { + checkState(completed(), "Batch has not been completed yet"); + if (error != null) { + throw error; + } + return result; + } + + /** + * Adds a callback for the batch operation. + * + * @throws IllegalStateException if the batch has been completed already + */ + public void notify(Callback callback) { + checkState(!completed, "The batch has been completed. All the calls to the notify()" + + " method should be done prior to submitting the batch."); + toBeNotified.add(callback); + } + + /** + * Sets an error and status as completed. Notifies all callbacks. + */ + protected void error(E error) { + this.error = checkNotNull(error); + this.completed = true; + for (Callback callback : toBeNotified) { + callback.error(error); + } + } + + /** + * Sets a result and status as completed. Notifies all callbacks. + */ + protected void success(T result) { + this.result = result; + this.completed = true; + for (Callback callback : toBeNotified) { + callback.success(result); + } + } + + /** + * An interface for the batch callbacks. + */ + public interface Callback { + /** + * The method to be called when the batched operation succeeds. + */ + void success(T result); + + /** + * The method to be called when the batched operation fails. + */ + void error(E exception); + } +} diff --git a/gcloud-java-core/src/test/java/com/google/cloud/BatchResultTest.java b/gcloud-java-core/src/test/java/com/google/cloud/BatchResultTest.java new file mode 100644 index 000000000000..8fb26bc8ce36 --- /dev/null +++ b/gcloud-java-core/src/test/java/com/google/cloud/BatchResultTest.java @@ -0,0 +1,113 @@ +/* + * 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.cloud; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +public class BatchResultTest { + + private BatchResult result; + + @Before + public void setUp() { + result = new BatchResult() {}; + } + + @Test + public void testSuccess() { + assertFalse(result.completed()); + try { + result.get(); + fail("This was not completed yet."); + } catch (IllegalStateException ex) { + // expected + } + result.success(true); + assertTrue(result.get()); + // test that null is allowed + result.success(null); + } + + @Test + public void testError() { + assertFalse(result.completed()); + try { + result.get(); + fail("This was not completed yet."); + } catch (IllegalStateException ex) { + // expected + } + try { + result.error(null); + fail(); + } catch (NullPointerException exc) { + // expected + } + BaseServiceException ex = new BaseServiceException(0, "message", "reason", false); + result.error(ex); + try { + result.get(); + fail("This is a failed operation and should have thrown a DnsException."); + } catch (BaseServiceException real) { + assertSame(ex, real); + } + } + + @Test + public void testNotifyError() { + final BaseServiceException ex = new BaseServiceException(0, "message", "reason", false); + assertFalse(result.completed()); + BatchResult.Callback callback = + EasyMock.createStrictMock(BatchResult.Callback.class); + callback.error(ex); + EasyMock.replay(callback); + result.notify(callback); + result.error(ex); + try { + result.notify(callback); + fail("The batch has been completed."); + } catch (IllegalStateException exception) { + // expected + } + EasyMock.verify(callback); + } + + @Test + public void testNotifySuccess() { + assertFalse(result.completed()); + BatchResult.Callback callback = + EasyMock.createStrictMock(BatchResult.Callback.class); + callback.success(true); + EasyMock.replay(callback); + result.notify(callback); + result.success(true); + try { + result.notify(callback); + fail("The batch has been completed."); + } catch (IllegalStateException exception) { + // expected + } + EasyMock.verify(callback); + } +} diff --git a/gcloud-java-dns/pom.xml b/gcloud-java-dns/pom.xml index 73e949dd5b1e..8acd6abee783 100644 --- a/gcloud-java-dns/pom.xml +++ b/gcloud-java-dns/pom.xml @@ -40,6 +40,11 @@ + + commons-fileupload + commons-fileupload + 1.3.1 + ${project.groupId} gcloud-java-core diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/ChangeRequest.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/ChangeRequest.java index 3538a5c411e9..267acf199b87 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/ChangeRequest.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/ChangeRequest.java @@ -173,8 +173,8 @@ public ChangeRequest reload(Dns.ChangeRequestOption... options) { /** * Returns {@code true} if the change request has been completed. If the status is not {@link - * Status#DONE} already, the method makes an API call to Google Cloud DNS to update the change - * request first. + * ChangeRequestInfo.Status#DONE} already, the method makes an API call to Google Cloud DNS to + * update the change request first. * * @throws DnsException upon failure of the API call or if the associated zone was not found */ diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/Dns.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/Dns.java index 2aa080fb63d3..38faad7854e7 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/Dns.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/Dns.java @@ -503,4 +503,9 @@ ChangeRequest getChangeRequest(String zoneName, String changeRequestId, * @see Cloud DNS Chages: list */ Page listChangeRequests(String zoneName, ChangeRequestListOption... options); + + /** + * Creates a new empty batch for grouping multiple service calls in one underlying RPC call. + */ + DnsBatch batch(); } diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatch.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatch.java new file mode 100644 index 000000000000..d81fc27f3a1a --- /dev/null +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatch.java @@ -0,0 +1,354 @@ +/* + * 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.cloud.dns; + +import static java.net.HttpURLConnection.HTTP_NOT_FOUND; + +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.services.dns.model.Change; +import com.google.api.services.dns.model.ChangesListResponse; +import com.google.api.services.dns.model.ManagedZone; +import com.google.api.services.dns.model.ManagedZonesListResponse; +import com.google.api.services.dns.model.Project; +import com.google.api.services.dns.model.ResourceRecordSet; +import com.google.api.services.dns.model.ResourceRecordSetsListResponse; +import com.google.cloud.Page; +import com.google.cloud.PageImpl; +import com.google.cloud.dns.spi.DnsRpc; +import com.google.cloud.dns.spi.RpcBatch; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; + +import java.util.List; +import java.util.Map; + +/** + * A batch of operations to be submitted to Google Cloud DNS using a single RPC request. + */ +public class DnsBatch { + + private final RpcBatch batch; + private final DnsRpc dnsRpc; + private final DnsOptions options; + + DnsBatch(DnsOptions options) { + this.options = options; + this.dnsRpc = options.rpc(); + this.batch = dnsRpc.createBatch(); + } + + @VisibleForTesting + Object batch() { + return batch; + } + + @VisibleForTesting + DnsRpc dnsRpc() { + return dnsRpc; + } + + @VisibleForTesting + DnsOptions options() { + return options; + } + + /** + * Adds a request representing the "list zones" operation to this batch. The {@code options} can + * be used to restrict the fields returned or provide page size limits in the same way as for + * {@link Dns#listZones(Dns.ZoneListOption...)}. Calling {@link DnsBatchResult#get()} on the + * return value yields a page of zones if successful and throws a {@link DnsException} otherwise. + */ + public DnsBatchResult> listZones(Dns.ZoneListOption... options) { + DnsBatchResult> result = new DnsBatchResult<>(); + Map optionMap = DnsImpl.optionMap(options); + RpcBatch.Callback callback = + createListZonesCallback(result, optionMap); + batch.addListZones(callback, optionMap); + return result; + } + + /** + * Adds a request representing the "create zone" operation to this batch. The {@code options} can + * be used to restrict the fields returned in the same way as for {@link Dns#create(ZoneInfo, + * Dns.ZoneOption...)}. Calling {@link DnsBatchResult#get()} on the return value yields the + * created {@link Zone} if successful and throws a {@link DnsException} otherwise. + */ + public DnsBatchResult createZone(ZoneInfo zone, Dns.ZoneOption... options) { + DnsBatchResult result = new DnsBatchResult<>(); + // todo this can cause misleading report of a failure, intended to be fixed within #924 + RpcBatch.Callback callback = createZoneCallback(this.options, result, true); + Map optionMap = DnsImpl.optionMap(options); + batch.addCreateZone(zone.toPb(), callback, optionMap); + return result; + } + + /** + * Adds a request representing the "delete zone" operation to this batch. Calling {@link + * DnsBatchResult#get()} on the return value yields {@code true} upon successful deletion, {@code + * false} if the zone was not found, or throws a {@link DnsException} if the operation failed. + */ + public DnsBatchResult deleteZone(String zoneName) { + DnsBatchResult result = new DnsBatchResult<>(); + RpcBatch.Callback callback = createDeleteZoneCallback(result); + batch.addDeleteZone(zoneName, callback); + return result; + } + + /** + * Adds a request representing the "get zone" operation to this batch. The {@code options} can be + * used to restrict the fields returned in the same way as for {@link Dns#getZone(String, + * Dns.ZoneOption...)}. Calling {@link DnsBatchResult#get()} on the return value yields the + * requested {@link Zone} if successful, {@code null} if no such zone exists, or throws a + * {@link DnsException} if the operation failed. + */ + public DnsBatchResult getZone(String zoneName, Dns.ZoneOption... options) { + DnsBatchResult result = new DnsBatchResult<>(); + RpcBatch.Callback callback = createZoneCallback(this.options, result, true); + Map optionMap = DnsImpl.optionMap(options); + batch.addGetZone(zoneName, callback, optionMap); + return result; + } + + /** + * Adds a request representing the "get project" operation to this batch. The {@code options} can + * be used to restrict the fields returned in the same way as for {@link + * Dns#getProject(Dns.ProjectOption...)}. Calling {@link DnsBatchResult#get()} on the return value + * yields the created {@link ProjectInfo} if successful and throws a {@link DnsException} if the + * operation failed. + */ + public DnsBatchResult getProject(Dns.ProjectOption... options) { + DnsBatchResult result = new DnsBatchResult<>(); + RpcBatch.Callback callback = createProjectCallback(result); + Map optionMap = DnsImpl.optionMap(options); + batch.addGetProject(callback, optionMap); + return result; + } + + /** + * Adds a request representing the "list record sets" operation in the zone specified by {@code + * zoneName} to this batch. The {@code options} can be used to restrict the fields returned or + * provide page size limits in the same way as for {@link Dns#listRecordSets(String, + * Dns.RecordSetListOption...)}. Calling {@link DnsBatchResult#get()} on the return value yields a + * page of record sets if successful and throws a {@link DnsException} if the operation failed or + * the zone does not exist. + */ + public DnsBatchResult> listRecordSets(String zoneName, + Dns.RecordSetListOption... options) { + DnsBatchResult> result = new DnsBatchResult<>(); + Map optionMap = DnsImpl.optionMap(options); + RpcBatch.Callback callback = + createListRecordSetsCallback(zoneName, result, optionMap); + batch.addListRecordSets(zoneName, callback, optionMap); + return result; + } + + /** + * Adds a request representing the "list change requests" operation in the zone specified by + * {@code zoneName} to this batch. The {@code options} can be used to restrict the fields returned + * or provide page size limits in the same way as for {@link Dns#listChangeRequests(String, + * Dns.ChangeRequestListOption...)}. Calling {@link DnsBatchResult#get()} on the return value + * yields a page of change requests if successful and throws a {@link DnsException} if the + * operation failed or the zone does not exist. + */ + public DnsBatchResult> listChangeRequests(String zoneName, + Dns.ChangeRequestListOption... options) { + DnsBatchResult> result = new DnsBatchResult<>(); + Map optionMap = DnsImpl.optionMap(options); + RpcBatch.Callback callback = + createListChangeRequestsCallback(zoneName, result, optionMap); + batch.addListChangeRequests(zoneName, callback, optionMap); + return result; + } + + /** + * Adds a request representing the "get change request" operation for the zone specified by {@code + * zoneName} to this batch. The {@code options} can be used to restrict the fields returned in the + * same way as for {@link Dns#getChangeRequest(String, String, Dns.ChangeRequestOption...)}. + * Calling {@link DnsBatchResult#get()} on the return value yields the requested {@link + * ChangeRequest} if successful, {@code null} if the change request does not exist, or throws a + * {@link DnsException} if the operation failed or the zone does not exist. + */ + public DnsBatchResult getChangeRequest(String zoneName, String changeRequestId, + Dns.ChangeRequestOption... options) { + DnsBatchResult result = new DnsBatchResult<>(); + RpcBatch.Callback callback = createChangeRequestCallback(zoneName, result, true); + Map optionMap = DnsImpl.optionMap(options); + batch.addGetChangeRequest(zoneName, changeRequestId, callback, optionMap); + return result; + } + + /** + * Adds a request representing the "apply change request" operation to the zone specified by + * {@code zoneName} to this batch. The {@code options} can be used to restrict the fields returned + * in the same way as for {@link Dns#applyChangeRequest(String, ChangeRequestInfo, + * Dns.ChangeRequestOption...)}. Calling {@link DnsBatchResult#get()} on the return value yields + * the created {@link ChangeRequest} if successful, {@code null} if the change request does not + * exist, or throws a {@link DnsException} if the operation failed or the zone does not exist. + */ + public DnsBatchResult applyChangeRequest(String zoneName, + ChangeRequestInfo changeRequest, Dns.ChangeRequestOption... options) { + DnsBatchResult result = new DnsBatchResult<>(); + RpcBatch.Callback callback = createChangeRequestCallback(zoneName, result, false); + Map optionMap = DnsImpl.optionMap(options); + batch.addApplyChangeRequest(zoneName, changeRequest.toPb(), callback, optionMap); + return result; + } + + /** + * Submits this batch for processing using a single HTTP request. + */ + public void submit() { + batch.submit(); + } + + private RpcBatch.Callback createListZonesCallback( + final DnsBatchResult> result, final Map optionMap) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + List zones = response.getManagedZones(); + Page zonePage = new PageImpl<>( + new DnsImpl.ZonePageFetcher(options, response.getNextPageToken(), optionMap), + response.getNextPageToken(), zones == null ? ImmutableList.of() + : Iterables.transform(zones, DnsImpl.zoneFromPb(options))); + result.success(zonePage); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, true)); + } + }; + } + + private RpcBatch.Callback createDeleteZoneCallback(final DnsBatchResult result) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(Void response) { + result.success(true); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + DnsException serviceException = new DnsException(googleJsonError, false); + if (serviceException.code() == HTTP_NOT_FOUND) { + result.success(false); + } else { + result.error(serviceException); + } + } + }; + } + + /** + * A joint callback for both "get zone" and "create zone" operations. + */ + private RpcBatch.Callback createZoneCallback(final DnsOptions serviceOptions, + final DnsBatchResult result, final boolean idempotent) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(ManagedZone response) { + result.success(response == null ? null : Zone.fromPb(serviceOptions.service(), response)); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, idempotent)); + } + }; + } + + private RpcBatch.Callback createProjectCallback( + final DnsBatchResult result) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(Project response) { + result.success(response == null ? null : ProjectInfo.fromPb(response)); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, true)); + } + }; + } + + private RpcBatch.Callback createListRecordSetsCallback( + final String zoneName, final DnsBatchResult> result, + final Map optionMap) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + List recordSets = response.getRrsets(); + Page page = new PageImpl<>( + new DnsImpl.RecordSetPageFetcher(zoneName, options, response.getNextPageToken(), + optionMap), + response.getNextPageToken(), recordSets == null ? ImmutableList.of() + : Iterables.transform(recordSets, RecordSet.FROM_PB_FUNCTION)); + result.success(page); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, true)); + } + }; + } + + private RpcBatch.Callback createListChangeRequestsCallback( + final String zoneName, final DnsBatchResult> result, + final Map optionMap) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(ChangesListResponse response) { + List changes = response.getChanges(); + Page page = new PageImpl<>( + new DnsImpl.ChangeRequestPageFetcher(zoneName, options, response.getNextPageToken(), + optionMap), + response.getNextPageToken(), changes == null ? ImmutableList.of() + : Iterables.transform(changes, ChangeRequest.fromPbFunction(options.service(), + zoneName))); + result.success(page); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, true)); + } + }; + } + + /** + * A joint callback for both "get change request" and "create change request" operations. + */ + private RpcBatch.Callback createChangeRequestCallback(final String zoneName, + final DnsBatchResult result, final boolean idempotent) { + return new RpcBatch.Callback() { + @Override + public void onSuccess(Change response) { + result.success(response == null ? null : ChangeRequest.fromPb(options.service(), + zoneName, response)); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError) { + result.error(new DnsException(googleJsonError, idempotent)); + } + }; + } +} diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatchResult.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatchResult.java new file mode 100644 index 000000000000..41c217ddc60e --- /dev/null +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsBatchResult.java @@ -0,0 +1,38 @@ +/* + * 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.cloud.dns; + +import com.google.cloud.BatchResult; + +/** + * This class holds a single result of a batch call to the Cloud DNS. + */ +public class DnsBatchResult extends BatchResult { + + DnsBatchResult() { + } + + @Override + protected void error(DnsException error) { + super.error(error); + } + + @Override + protected void success(T result) { + super.success(result); + } +} diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsException.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsException.java index f725984b6661..274ff91b3bd0 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsException.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsException.java @@ -16,6 +16,7 @@ package com.google.cloud.dns; +import com.google.api.client.googleapis.json.GoogleJsonError; import com.google.cloud.BaseServiceException; import com.google.cloud.RetryHelper.RetryHelperException; import com.google.cloud.RetryHelper.RetryInterruptedException; @@ -43,6 +44,10 @@ public DnsException(IOException exception, boolean idempotent) { super(exception, idempotent); } + public DnsException(GoogleJsonError error, boolean idempotent) { + super(error, idempotent); + } + private DnsException(int code, String message) { super(code, message, null, true); } diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsImpl.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsImpl.java index cdb311adc823..be0e8621cf41 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsImpl.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/DnsImpl.java @@ -44,7 +44,7 @@ final class DnsImpl extends BaseService implements Dns { private final DnsRpc dnsRpc; - private static class ZonePageFetcher implements PageImpl.NextPageFetcher { + static class ZonePageFetcher implements PageImpl.NextPageFetcher { private static final long serialVersionUID = 2158209410430566961L; private final Map requestOptions; @@ -63,7 +63,7 @@ public Page nextPage() { } } - private static class ChangeRequestPageFetcher implements PageImpl.NextPageFetcher { + static class ChangeRequestPageFetcher implements PageImpl.NextPageFetcher { private static final long serialVersionUID = 4473265130673029139L; private final String zoneName; @@ -84,14 +84,14 @@ public Page nextPage() { } } - private static class DnsRecordPageFetcher implements PageImpl.NextPageFetcher { + static class RecordSetPageFetcher implements PageImpl.NextPageFetcher { private static final long serialVersionUID = -6039369212511530846L; private final Map requestOptions; private final DnsOptions serviceOptions; private final String zoneName; - DnsRecordPageFetcher(String zoneName, DnsOptions serviceOptions, String cursor, + RecordSetPageFetcher(String zoneName, DnsOptions serviceOptions, String cursor, Map optionMap) { this.zoneName = zoneName; this.requestOptions = @@ -110,6 +110,15 @@ public Page nextPage() { dnsRpc = options.rpc(); } + static Function zoneFromPb(final DnsOptions options) { + return new Function() { + @Override + public Zone apply(ManagedZone zonePb) { + return Zone.fromPb(options.service(), zonePb); + } + }; + } + @Override public Page listZones(ZoneListOption... options) { return listZones(options(), optionMap(options)); @@ -117,14 +126,6 @@ public Page listZones(ZoneListOption... options) { private static Page listZones(final DnsOptions serviceOptions, final Map optionsMap) { - // define transformation function - // this differs from the other list operations since zone is functional and requires dns service - Function pbToZoneFunction = new Function() { - @Override - public Zone apply(ManagedZone zonePb) { - return Zone.fromPb(serviceOptions.service(), zonePb); - } - }; try { // get a list of managed zones final DnsRpc rpc = serviceOptions.rpc(); @@ -137,8 +138,8 @@ public DnsRpc.ListResult call() { }, serviceOptions.retryParams(), EXCEPTION_HANDLER); String cursor = result.pageToken(); // transform that list into zone objects - Iterable zones = result.results() == null - ? ImmutableList.of() : Iterables.transform(result.results(), pbToZoneFunction); + Iterable zones = result.results() == null ? ImmutableList.of() + : Iterables.transform(result.results(), zoneFromPb(serviceOptions)); return new PageImpl<>(new ZonePageFetcher(serviceOptions, cursor, optionsMap), cursor, zones); } catch (RetryHelper.RetryHelperException e) { @@ -198,7 +199,7 @@ public DnsRpc.ListResult call() { Iterable recordSets = result.results() == null ? ImmutableList.of() : Iterables.transform(result.results(), RecordSet.FROM_PB_FUNCTION); - return new PageImpl<>(new DnsRecordPageFetcher(zoneName, serviceOptions, cursor, optionsMap), + return new PageImpl<>(new RecordSetPageFetcher(zoneName, serviceOptions, cursor, optionsMap), cursor, recordSets); } catch (RetryHelper.RetryHelperException e) { throw DnsException.translateAndThrow(e); @@ -306,7 +307,12 @@ public Change call() { } } - private Map optionMap(Option... options) { + @Override + public DnsBatch batch() { + return new DnsBatch(this.options()); + } + + static Map optionMap(Option... options) { Map temp = Maps.newEnumMap(DnsRpc.Option.class); for (Option option : options) { Object prev = temp.put(option.rpcOption(), option.value()); diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/RecordSet.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/RecordSet.java index 5e061b5164e8..e9d2e1b2527e 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/RecordSet.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/RecordSet.java @@ -154,7 +154,7 @@ private Builder(RecordSet record) { * RFC 1034 (section 3.6.1). Examples of records are available in Google DNS documentation. * * @see Google - * DNS documentation . + * DNS documentation */ public Builder addRecord(String record) { this.rrdatas.add(checkNotNull(record)); diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DefaultDnsRpc.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DefaultDnsRpc.java index 08f14a0ba254..4ee117cc7ea1 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DefaultDnsRpc.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DefaultDnsRpc.java @@ -1,3 +1,19 @@ +/* + * 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.cloud.dns.spi; import static com.google.cloud.dns.spi.DnsRpc.ListResult.of; @@ -10,6 +26,10 @@ import static com.google.cloud.dns.spi.DnsRpc.Option.SORTING_ORDER; import static java.net.HttpURLConnection.HTTP_NOT_FOUND; +import com.google.api.client.googleapis.batch.BatchRequest; +import com.google.api.client.googleapis.batch.json.JsonBatchCallback; +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.client.http.HttpHeaders; import com.google.api.client.http.HttpRequestInitializer; import com.google.api.client.http.HttpTransport; import com.google.api.client.json.jackson.JacksonFactory; @@ -36,6 +56,129 @@ public class DefaultDnsRpc implements DnsRpc { private final Dns dns; private final DnsOptions options; + private class DefaultRpcBatch implements RpcBatch { + + private final BatchRequest batch; + + private DefaultRpcBatch(BatchRequest batch) { + this.batch = batch; + } + + @Override + public void addListZones(RpcBatch.Callback callback, + Map options) { + try { + listZonesCall(options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addCreateZone(ManagedZone zone, RpcBatch.Callback callback, + Map options) { + try { + createZoneCall(zone, options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addGetZone(String zoneName, RpcBatch.Callback callback, + Map options) { + try { + getZoneCall(zoneName, options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addDeleteZone(String zoneName, RpcBatch.Callback callback) { + try { + deleteZoneCall(zoneName).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addGetProject(RpcBatch.Callback callback, + Map options) { + try { + getProjectCall(options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addListRecordSets(String zoneName, + RpcBatch.Callback callback, Map options) { + try { + listRecordSetsCall(zoneName, options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addListChangeRequests(String zoneName, + RpcBatch.Callback callback, Map options) { + try { + listChangeRequestsCall(zoneName, options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addGetChangeRequest(String zoneName, String changeRequestId, + RpcBatch.Callback callback, Map options) { + try { + getChangeRequestCall(zoneName, changeRequestId, options).queue(batch, + toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void addApplyChangeRequest(String zoneName, Change change, + RpcBatch.Callback callback, Map options) { + try { + applyChangeRequestCall(zoneName, change, options).queue(batch, toJsonCallback(callback)); + } catch (IOException ex) { + throw translate(ex, false); + } + } + + @Override + public void submit() { + try { + batch.execute(); + } catch (IOException ex) { + throw translate(ex, false); + } + } + } + + private static JsonBatchCallback toJsonCallback(final RpcBatch.Callback callback) { + return new JsonBatchCallback() { + @Override + public void onSuccess(T response, HttpHeaders httpHeaders) throws IOException { + callback.onSuccess(response); + } + + @Override + public void onFailure(GoogleJsonError googleJsonError, HttpHeaders httpHeaders) + throws IOException { + callback.onFailure(googleJsonError); + } + }; + } + private static DnsException translate(IOException exception, boolean idempotent) { return new DnsException(exception, idempotent); } @@ -56,23 +199,25 @@ public DefaultDnsRpc(DnsOptions options) { @Override public ManagedZone create(ManagedZone zone, Map options) throws DnsException { try { - return dns.managedZones() - .create(this.options.projectId(), zone) - .setFields(FIELDS.getString(options)) - .execute(); + return createZoneCall(zone, options).execute(); } catch (IOException ex) { // todo this can cause misleading report of a failure, intended to be fixed within #924 throw translate(ex, true); } } + private Dns.ManagedZones.Create createZoneCall(ManagedZone zone, Map options) + throws IOException { + return dns.managedZones() + .create(this.options.projectId(), zone) + .setFields(FIELDS.getString(options)); + } + @Override public ManagedZone getZone(String zoneName, Map options) throws DnsException { // just fields option try { - return dns.managedZones().get(this.options.projectId(), zoneName) - .setFields(FIELDS.getString(options)) - .execute(); + return getZoneCall(zoneName, options).execute(); } catch (IOException ex) { DnsException serviceException = translate(ex, true); if (serviceException.code() == HTTP_NOT_FOUND) { @@ -82,26 +227,36 @@ public ManagedZone getZone(String zoneName, Map options) throws DnsEx } } + private Dns.ManagedZones.Get getZoneCall(String zoneName, Map options) + throws IOException { + return dns.managedZones() + .get(this.options.projectId(), zoneName) + .setFields(FIELDS.getString(options)); + } + @Override public ListResult listZones(Map options) throws DnsException { // fields, page token, page size try { - ManagedZonesListResponse zoneList = dns.managedZones().list(this.options.projectId()) - .setFields(FIELDS.getString(options)) - .setMaxResults(PAGE_SIZE.getInt(options)) - .setDnsName(DNS_NAME.getString(options)) - .setPageToken(PAGE_TOKEN.getString(options)) - .execute(); + ManagedZonesListResponse zoneList = listZonesCall(options).execute(); return of(zoneList.getNextPageToken(), zoneList.getManagedZones()); } catch (IOException ex) { throw translate(ex, true); } } + private Dns.ManagedZones.List listZonesCall(Map options) throws IOException { + return dns.managedZones().list(this.options.projectId()) + .setFields(FIELDS.getString(options)) + .setMaxResults(PAGE_SIZE.getInt(options)) + .setDnsName(DNS_NAME.getString(options)) + .setPageToken(PAGE_TOKEN.getString(options)); + } + @Override public boolean deleteZone(String zoneName) throws DnsException { try { - dns.managedZones().delete(this.options.projectId(), zoneName).execute(); + deleteZoneCall(zoneName).execute(); return true; } catch (IOException ex) { DnsException serviceException = translate(ex, false); @@ -112,54 +267,68 @@ public boolean deleteZone(String zoneName) throws DnsException { } } + private Dns.ManagedZones.Delete deleteZoneCall(String zoneName) throws IOException { + return dns.managedZones().delete(this.options.projectId(), zoneName); + } + @Override public ListResult listRecordSets(String zoneName, Map options) throws DnsException { - // options are fields, page token, dns name, type try { - ResourceRecordSetsListResponse response = dns.resourceRecordSets() - .list(this.options.projectId(), zoneName) - .setFields(FIELDS.getString(options)) - .setPageToken(PAGE_TOKEN.getString(options)) - .setMaxResults(PAGE_SIZE.getInt(options)) - .setName(NAME.getString(options)) - .setType(DNS_TYPE.getString(options)) - .execute(); + ResourceRecordSetsListResponse response = listRecordSetsCall(zoneName, options).execute(); return of(response.getNextPageToken(), response.getRrsets()); } catch (IOException ex) { throw translate(ex, true); } } + private Dns.ResourceRecordSets.List listRecordSetsCall(String zoneName, Map options) + throws IOException { + // options are fields, page token, dns name, type + return dns.resourceRecordSets() + .list(this.options.projectId(), zoneName) + .setFields(FIELDS.getString(options)) + .setPageToken(PAGE_TOKEN.getString(options)) + .setMaxResults(PAGE_SIZE.getInt(options)) + .setName(NAME.getString(options)) + .setType(DNS_TYPE.getString(options)); + } + @Override public Project getProject(Map options) throws DnsException { try { - return dns.projects().get(this.options.projectId()) - .setFields(FIELDS.getString(options)).execute(); + return getProjectCall(options).execute(); } catch (IOException ex) { throw translate(ex, true); } } + private Dns.Projects.Get getProjectCall(Map options) throws IOException { + return dns.projects().get(this.options.projectId()).setFields(FIELDS.getString(options)); + } + @Override public Change applyChangeRequest(String zoneName, Change changeRequest, Map options) throws DnsException { try { - return dns.changes().create(this.options.projectId(), zoneName, changeRequest) - .setFields(FIELDS.getString(options)) - .execute(); + return applyChangeRequestCall(zoneName, changeRequest, options).execute(); } catch (IOException ex) { throw translate(ex, false); } } + private Dns.Changes.Create applyChangeRequestCall(String zoneName, Change changeRequest, + Map options) throws IOException { + return dns.changes() + .create(this.options.projectId(), zoneName, changeRequest) + .setFields(FIELDS.getString(options)); + } + @Override public Change getChangeRequest(String zoneName, String changeRequestId, Map options) throws DnsException { try { - return dns.changes().get(this.options.projectId(), zoneName, changeRequestId) - .setFields(FIELDS.getString(options)) - .execute(); + return getChangeRequestCall(zoneName, changeRequestId, options).execute(); } catch (IOException ex) { DnsException serviceException = translate(ex, true); if (serviceException.code() == HTTP_NOT_FOUND) { @@ -175,23 +344,40 @@ public Change getChangeRequest(String zoneName, String changeRequestId, Map options) throws IOException { + return dns.changes() + .get(this.options.projectId(), zoneName, changeRequestId) + .setFields(FIELDS.getString(options)); + } + @Override public ListResult listChangeRequests(String zoneName, Map options) throws DnsException { - // options are fields, page token, page size, sort order try { - Dns.Changes.List request = dns.changes().list(this.options.projectId(), zoneName) - .setFields(FIELDS.getString(options)) - .setMaxResults(PAGE_SIZE.getInt(options)) - .setPageToken(PAGE_TOKEN.getString(options)); - if (SORTING_ORDER.getString(options) != null) { - // todo check and change if more sorting options are implemented, issue #604 - request = request.setSortBy(SORT_BY).setSortOrder(SORTING_ORDER.getString(options)); - } - ChangesListResponse response = request.execute(); + ChangesListResponse response = listChangeRequestsCall(zoneName, options).execute(); return of(response.getNextPageToken(), response.getChanges()); } catch (IOException ex) { throw translate(ex, true); } } + + private Dns.Changes.List listChangeRequestsCall(String zoneName, Map options) + throws IOException { + // options are fields, page token, page size, sort order + Dns.Changes.List request = dns.changes().list(this.options.projectId(), zoneName) + .setFields(FIELDS.getString(options)) + .setMaxResults(PAGE_SIZE.getInt(options)) + .setPageToken(PAGE_TOKEN.getString(options)); + if (SORTING_ORDER.getString(options) != null) { + // todo check and change if more sorting options are implemented, issue #604 + request = request.setSortBy(SORT_BY).setSortOrder(SORTING_ORDER.getString(options)); + } + return request; + } + + @Override + public RpcBatch createBatch() { + return new DefaultRpcBatch(dns.batch()); + } } diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DnsRpc.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DnsRpc.java index ba74f14f0527..5d0054d86379 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DnsRpc.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/DnsRpc.java @@ -171,4 +171,9 @@ Change getChangeRequest(String zoneName, String changeRequestId, Map */ ListResult listChangeRequests(String zoneName, Map options) throws DnsException; + + /** + * Creates an empty batch. + */ + RpcBatch createBatch(); } diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/RpcBatch.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/RpcBatch.java new file mode 100644 index 000000000000..154ffa4a3c99 --- /dev/null +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/spi/RpcBatch.java @@ -0,0 +1,117 @@ +/* + * 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.cloud.dns.spi; + +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.services.dns.model.Change; +import com.google.api.services.dns.model.ChangesListResponse; +import com.google.api.services.dns.model.ManagedZone; +import com.google.api.services.dns.model.ManagedZonesListResponse; +import com.google.api.services.dns.model.Project; +import com.google.api.services.dns.model.ResourceRecordSetsListResponse; + +import java.util.Map; + +/** + * An interface for the collection of batch operations. + */ +public interface RpcBatch { + + /** + * An interface for batch callbacks. + */ + interface Callback { + + /** + * This method will be called upon success of the batch operation. + */ + void onSuccess(T response); + + /** + * This method will be called upon failure of the batch operation. + */ + void onFailure(GoogleJsonError googleJsonError); + } + + /** + * Adds a call to "list zones" to the batch with the provided {@code callback} and {@code + * options}. + */ + void addListZones(Callback callback, Map options); + + /** + * Adds a call to "create zone" to the batch with the provided {@code callback} and {@code + * options}. + */ + void addCreateZone(ManagedZone zone, Callback callback, + Map options); + + /** + * Adds a call to "get zone" to the batch with the provided {@code callback} and {@code options}. + * The zone to be retrieved is identified by {@code zoneName}. + */ + void addGetZone(String zoneName, Callback callback, Map options); + + /** + * Adds a call to "get project" to the batch with the provided {@code callback} and {@code + * options}. + */ + void addGetProject(Callback callback, Map options); + + /** + * Adds a call to "delete zone" to the batch with the provided {@code callback}. The zone to be + * deleted is identified by {@code zoneName}. + */ + void addDeleteZone(String zoneName, Callback callback); + + /** + * Adds a call to "list record sets" to the batch with the provided {@code callback} and {@code + * options}. The zone whose record sets are to be listed is identified by {@code zoneName}. + */ + void addListRecordSets(String zoneName, Callback callback, + Map options); + + /** + * Adds a call to "list change requests" to the batch with the provided {@code callback} and + * {@code options}. The zone whose change requests are to be listed is identified by {@code + * zoneName}. + */ + void addListChangeRequests(String zoneName, Callback callback, + Map options); + + /** + * Adds a call to "get change request" to the batch with the provided {@code callback} and {@code + * options}. The change request to be retrieved is identified by {@code changeRequestId}. The zone + * to which the change request was applied is identified by {@code zoneName}. + */ + void addGetChangeRequest(String zoneName, String changeRequestId, Callback callback, + Map options); + + /** + * Adds a call to "apply change request" to the batch with the provided {@code callback} and + * {@code options}. The parameter {@code change} is the change request to be applied. The zone to + * which the change request should be applied is identified by {@code zoneName}. + */ + void addApplyChangeRequest(String zoneName, Change change, Callback callback, + Map options); + + /** + * Submits a batch of requests for processing using a single HTTP request to Cloud DNS. + */ + void submit(); +} + diff --git a/gcloud-java-dns/src/main/java/com/google/cloud/dns/testing/LocalDnsHelper.java b/gcloud-java-dns/src/main/java/com/google/cloud/dns/testing/LocalDnsHelper.java index 1f35193409ee..774bc566a458 100644 --- a/gcloud-java-dns/src/main/java/com/google/cloud/dns/testing/LocalDnsHelper.java +++ b/gcloud-java-dns/src/main/java/com/google/cloud/dns/testing/LocalDnsHelper.java @@ -20,6 +20,7 @@ import static java.net.HttpURLConnection.HTTP_NO_CONTENT; import static java.net.HttpURLConnection.HTTP_OK; +import com.google.api.client.http.HttpMediaType; import com.google.api.client.json.JsonFactory; import com.google.api.client.json.jackson.JacksonFactory; import com.google.api.services.dns.model.Change; @@ -27,6 +28,7 @@ import com.google.api.services.dns.model.Project; import com.google.api.services.dns.model.Quota; import com.google.api.services.dns.model.ResourceRecordSet; +import com.google.cloud.AuthCredentials; import com.google.cloud.dns.DnsOptions; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Joiner; @@ -37,19 +39,21 @@ import com.google.common.collect.Lists; import com.google.common.collect.Sets; import com.google.common.io.ByteStreams; - import com.sun.net.httpserver.Headers; import com.sun.net.httpserver.HttpExchange; import com.sun.net.httpserver.HttpHandler; import com.sun.net.httpserver.HttpServer; +import org.apache.commons.fileupload.MultipartStream; import org.joda.time.format.ISODateTimeFormat; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.math.BigInteger; import java.net.InetSocketAddress; +import java.net.Socket; import java.net.URI; import java.net.URISyntaxException; import java.nio.charset.StandardCharsets; @@ -62,6 +66,7 @@ import java.util.NavigableMap; import java.util.NavigableSet; import java.util.Random; +import java.util.Scanner; import java.util.Set; import java.util.SortedMap; import java.util.TreeMap; @@ -112,6 +117,9 @@ public class LocalDnsHelper { private static final ScheduledExecutorService EXECUTORS = Executors.newScheduledThreadPool(2, Executors.defaultThreadFactory()); private static final String PROJECT_ID = "dummyprojectid"; + private static final String RESPONSE_BOUNDARY = "____THIS_IS_HELPERS_BOUNDARY____"; + private static final String RESPONSE_SEPARATOR = "--" + RESPONSE_BOUNDARY + "\r\n"; + private static final String RESPONSE_END = "--" + RESPONSE_BOUNDARY + "--\r\n\r\n"; static { try { @@ -138,7 +146,8 @@ private enum CallRegex { ZONE_GET("GET", CONTEXT + "/[^/]+/managedZones/[^/]+"), ZONE_LIST("GET", CONTEXT + "/[^/]+/managedZones"), PROJECT_GET("GET", CONTEXT + "/[^/]+"), - RECORD_LIST("GET", CONTEXT + "/[^/]+/managedZones/[^/]+/rrsets"); + RECORD_LIST("GET", CONTEXT + "/[^/]+/managedZones/[^/]+/rrsets"), + BATCH("POST", "/batch"); private final String method; private final String pathRegex; @@ -307,6 +316,12 @@ private Response pickHandler(HttpExchange exchange, CallRegex regex) { } catch (IOException ex) { return Error.BAD_REQUEST.response(ex.getMessage()); } + case BATCH: + try { + return handleBatch(exchange); + } catch (IOException | URISyntaxException ex) { + return Error.BAD_REQUEST.response(ex.getMessage()); + } default: return Error.INTERNAL_ERROR.response("Operation without a handler."); } @@ -319,7 +334,11 @@ public void handle(HttpExchange exchange) throws IOException { for (CallRegex regex : CallRegex.values()) { if (requestMethod.equals(regex.method) && rawPath.matches(regex.pathRegex)) { Response response = pickHandler(exchange, regex); - writeResponse(exchange, response); + if (response != null) { + /* null response is returned by batch request, because it handles writing + the response on its own */ + writeResponse(exchange, response); + } return; } } @@ -328,6 +347,84 @@ public void handle(HttpExchange exchange) throws IOException { requestMethod, exchange.getRequestURI()))); } + private Response handleBatch(final HttpExchange exchange) throws IOException, + URISyntaxException { + String contentType = exchange.getRequestHeaders().getFirst("Content-type"); + if (contentType != null) { + HttpMediaType httpMediaType = new HttpMediaType(contentType); + String boundary = httpMediaType.getParameter("boundary"); + MultipartStream multipartStream = + new MultipartStream(exchange.getRequestBody(), boundary.getBytes(), 1024, null); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] bytes = new byte[1024]; + boolean nextPart = multipartStream.skipPreamble(); + while (nextPart) { + String line; + String contentId = null; + String headers = multipartStream.readHeaders(); + Scanner scanner = new Scanner(headers); + while (scanner.hasNextLine()) { + line = scanner.nextLine(); + if (line.toLowerCase().startsWith("content-id")) { + contentId = line.split(":")[1].trim(); + } + } + // TODO: remove and write directly to socket once api client provides a complete + // location line (e.g. GET /aaa/bbb HTTP/1.0) + // and uses a request path for location instead of a complete URL. + ByteArrayOutputStream bouts = new ByteArrayOutputStream(); + multipartStream.readBodyData(bouts); + byte[] contentBytes = bouts.toByteArray(); + int indexOfCr = -1; + for (int i = 0; i < contentBytes.length; i++) { + if (contentBytes[i] == '\r') { + indexOfCr = i; + break; + } + } + Socket socket = new Socket("127.0.0.1", server.getAddress().getPort()); + OutputStream socketOutput = socket.getOutputStream(); + InputStream socketInput = socket.getInputStream(); + //multipartStream.readBodyData(socketOutput); + if (indexOfCr < 0) { + socketOutput.write(contentBytes); + } else { + String[] requestLine = + new String(contentBytes, 0, indexOfCr, StandardCharsets.UTF_8).split(" "); + socketOutput.write(requestLine[0].getBytes()); + socketOutput.write(' '); + URI uri = new URI(requestLine[1]); + socketOutput.write(uri.getRawPath().getBytes()); + if (uri.getRawQuery() != null) { + socketOutput.write('?'); + socketOutput.write(uri.getRawQuery().getBytes()); + } + if (uri.getRawFragment() != null) { + socketOutput.write('#'); + socketOutput.write(uri.getRawFragment().getBytes()); + } + socketOutput.write(" HTTP/1.0".getBytes()); + socketOutput.write(contentBytes, indexOfCr, contentBytes.length - indexOfCr); + } + socketOutput.flush(); + out.write(RESPONSE_SEPARATOR.getBytes()); + out.write("Content-Type: application/http\r\n".getBytes()); + out.write(("Content-ID: " + contentId + "\r\n\r\n").getBytes()); + int length; + while ((length = socketInput.read(bytes)) != -1) { + out.write(bytes, 0, length); + } + socket.close(); + nextPart = multipartStream.skipPreamble(); + } + out.write(RESPONSE_END.getBytes()); + writeBatchResponse(exchange, out); + } else { + return Error.BAD_REQUEST.response("Content-type header was not provided for batch."); + } + return null; + } + /** * @throws IOException if the request cannot be parsed. */ @@ -368,7 +465,8 @@ private LocalDnsHelper(long delay) { try { server = HttpServer.create(new InetSocketAddress(0), 0); port = server.getAddress().getPort(); - server.createContext(CONTEXT, new RequestHandler()); + server.setExecutor(Executors.newCachedThreadPool()); + server.createContext("/", new RequestHandler()); } catch (IOException e) { throw new RuntimeException("Could not bind the mock DNS server.", e); } @@ -397,7 +495,11 @@ public static LocalDnsHelper create(Long delay) { * Returns a {@link DnsOptions} instance that sets the host to use the mock server. */ public DnsOptions options() { - return DnsOptions.builder().projectId(PROJECT_ID).host("http://localhost:" + port).build(); + return DnsOptions.builder() + .projectId(PROJECT_ID) + .host("http://localhost:" + port) + .authCredentials(AuthCredentials.noAuth()) + .build(); } /** @@ -430,6 +532,20 @@ private static void writeResponse(HttpExchange exchange, Response response) { } } + private static void writeBatchResponse(HttpExchange exchange, ByteArrayOutputStream output) { + exchange.getResponseHeaders().set( + "Content-type", "multipart/mixed; boundary=" + RESPONSE_BOUNDARY); + try { + exchange.getResponseHeaders().add("Connection", "close"); + exchange.sendResponseHeaders(200, output.toByteArray().length); + OutputStream responseBody = exchange.getResponseBody(); + output.writeTo(responseBody); + responseBody.close(); + } catch (IOException e) { + log.log(Level.WARNING, "IOException encountered when sending response.", e); + } + } + private static String decodeContent(Headers headers, InputStream inputStream) throws IOException { List contentEncoding = headers.get("Content-encoding"); InputStream input = inputStream; diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchResultTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchResultTest.java new file mode 100644 index 000000000000..96ca99cc9e3e --- /dev/null +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchResultTest.java @@ -0,0 +1,109 @@ +/* + * 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.cloud.dns; + +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.cloud.BatchResult; + +import org.easymock.EasyMock; +import org.junit.Before; +import org.junit.Test; + +import java.io.IOException; + +public class DnsBatchResultTest { + + private DnsBatchResult result; + + @Before + public void setUp() { + result = new DnsBatchResult<>(); + } + + @Test + public void testSuccess() { + assertFalse(result.completed()); + try { + result.get(); + fail("This was not completed yet."); + } catch (IllegalStateException ex) { + // expected + } + result.success(true); + assertTrue(result.get()); + } + + @Test + public void testError() { + assertFalse(result.completed()); + try { + result.get(); + fail("This was not completed yet."); + } catch (IllegalStateException ex) { + // expected + } + DnsException ex = new DnsException(new IOException("some error"), true); + result.error(ex); + try { + result.get(); + fail("This is a failed operation and should have thrown a DnsException."); + } catch (DnsException real) { + assertSame(ex, real); + } + } + + @Test + public void testNotifyError() { + DnsException ex = new DnsException(new IOException("some error"), false); + assertFalse(result.completed()); + BatchResult.Callback callback = + EasyMock.createStrictMock(BatchResult.Callback.class); + callback.error(ex); + EasyMock.replay(callback); + result.notify(callback); + result.error(ex); + try { + result.notify(callback); + fail("The batch has been completed."); + } catch (IllegalStateException exception) { + // expected + } + EasyMock.verify(callback); + } + + @Test + public void testNotifySuccess() { + assertFalse(result.completed()); + BatchResult.Callback callback = + EasyMock.createStrictMock(BatchResult.Callback.class); + callback.success(true); + EasyMock.replay(callback); + result.notify(callback); + result.success(true); + try { + result.notify(callback); + fail("The batch has been completed."); + } catch (IllegalStateException exception) { + // expected + } + EasyMock.verify(callback); + } +} diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchTest.java new file mode 100644 index 000000000000..bd743a3babb6 --- /dev/null +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsBatchTest.java @@ -0,0 +1,632 @@ +/* + * 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.cloud.dns; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertSame; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import com.google.api.client.googleapis.json.GoogleJsonError; +import com.google.api.services.dns.model.Change; +import com.google.api.services.dns.model.ChangesListResponse; +import com.google.api.services.dns.model.ManagedZone; +import com.google.api.services.dns.model.ManagedZonesListResponse; +import com.google.api.services.dns.model.Project; +import com.google.api.services.dns.model.ResourceRecordSet; +import com.google.api.services.dns.model.ResourceRecordSetsListResponse; +import com.google.cloud.Page; +import com.google.cloud.dns.spi.DnsRpc; +import com.google.cloud.dns.spi.RpcBatch; +import com.google.common.collect.ImmutableList; + +import org.easymock.Capture; +import org.easymock.EasyMock; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +public class DnsBatchTest { + + private static final String ZONE_NAME = "somezonename"; + private static final String DNS_NAME = "example.com."; + private static final String DESCRIPTION = "desc"; + private static final Integer MAX_SIZE = 20; + private static final String PAGE_TOKEN = "some token"; + + private static final ZoneInfo ZONE_INFO = ZoneInfo.of(ZONE_NAME, DNS_NAME, DESCRIPTION); + private static final Dns.ZoneOption ZONE_FIELDS = + Dns.ZoneOption.fields(Dns.ZoneField.CREATION_TIME); + private static final Dns.ProjectOption PROJECT_FIELDS = + Dns.ProjectOption.fields(Dns.ProjectField.QUOTA); + private static final Dns.ZoneListOption[] ZONE_LIST_OPTIONS = { + Dns.ZoneListOption.pageSize(MAX_SIZE), Dns.ZoneListOption.pageToken(PAGE_TOKEN), + Dns.ZoneListOption.fields(Dns.ZoneField.DESCRIPTION), + Dns.ZoneListOption.dnsName(DNS_NAME)}; + private static final ProjectInfo PROJECT_INFO = ProjectInfo.builder().build(); + private static final Dns.RecordSetListOption[] RECORD_SET_LIST_OPTIONS = { + Dns.RecordSetListOption.pageSize(MAX_SIZE), + Dns.RecordSetListOption.pageToken(PAGE_TOKEN), + Dns.RecordSetListOption.fields(Dns.RecordSetField.TTL), + Dns.RecordSetListOption.dnsName(DNS_NAME), + Dns.RecordSetListOption.type(RecordSet.Type.AAAA)}; + private static final RecordSet RECORD_SET = + RecordSet.builder("Something", RecordSet.Type.AAAA).build(); + private static final ChangeRequestInfo CHANGE_REQUEST_PARTIAL = ChangeRequestInfo.builder() + .add(RECORD_SET) + .build(); + private static final String CHANGE_ID = "some change id"; + private static final ChangeRequestInfo CHANGE_REQUEST_COMPLETE = ChangeRequestInfo.builder() + .add(RECORD_SET) + .startTimeMillis(123L) + .status(ChangeRequest.Status.PENDING) + .generatedId(CHANGE_ID) + .build(); + private static final Dns.ChangeRequestListOption[] CHANGE_LIST_OPTIONS = { + Dns.ChangeRequestListOption.pageSize(MAX_SIZE), + Dns.ChangeRequestListOption.pageToken(PAGE_TOKEN), + Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.STATUS), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING)}; + private static final Dns.ChangeRequestOption CHANGE_GET_FIELDS = + Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS); + private static final List RECORD_SET_LIST = ImmutableList.of( + RECORD_SET.toPb(), RECORD_SET.toPb(), RECORD_SET.toPb(), RECORD_SET.toPb()); + private static final List CHANGE_LIST = ImmutableList.of(CHANGE_REQUEST_COMPLETE.toPb(), + CHANGE_REQUEST_COMPLETE.toPb(), CHANGE_REQUEST_COMPLETE.toPb()); + private static final List ZONE_LIST = ImmutableList.of(ZONE_INFO.toPb(), + ZONE_INFO.toPb()); + private static final GoogleJsonError GOOGLE_JSON_ERROR = new GoogleJsonError(); + + private DnsOptions optionsMock; + private DnsRpc dnsRpcMock; + private RpcBatch batchMock; + private DnsBatch dnsBatch; + private final Dns dns = EasyMock.createStrictMock(Dns.class); + + @Before + public void setUp() { + optionsMock = EasyMock.createMock(DnsOptions.class); + dnsRpcMock = EasyMock.createMock(DnsRpc.class); + batchMock = EasyMock.createMock(RpcBatch.class); + EasyMock.expect(optionsMock.rpc()).andReturn(dnsRpcMock); + EasyMock.expect(dnsRpcMock.createBatch()).andReturn(batchMock); + EasyMock.replay(optionsMock, dnsRpcMock, batchMock, dns); + dnsBatch = new DnsBatch(optionsMock); + } + + @After + public void tearDown() { + EasyMock.verify(batchMock, dnsRpcMock, optionsMock, dns); + } + + @Test + public void testConstructor() { + assertSame(batchMock, dnsBatch.batch()); + assertSame(optionsMock, dnsBatch.options()); + assertSame(dnsRpcMock, dnsBatch.dnsRpc()); + } + + @Test + public void testListZones() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListZones(EasyMock.capture(callback), EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = dnsBatch.listZones(); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testListZonesWithOptions() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListZones(EasyMock.capture(callback), EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = dnsBatch.listZones(ZONE_LIST_OPTIONS); + assertNotNull(callback.getValue()); + Integer size = (Integer) capturedOptions.getValue().get(ZONE_LIST_OPTIONS[0].rpcOption()); + assertEquals(MAX_SIZE, size); + String selector = (String) capturedOptions.getValue().get(ZONE_LIST_OPTIONS[1].rpcOption()); + assertEquals(PAGE_TOKEN, selector); + selector = (String) capturedOptions.getValue().get(ZONE_LIST_OPTIONS[2].rpcOption()); + assertTrue(selector.contains(Dns.ZoneField.DESCRIPTION.selector())); + assertTrue(selector.contains(Dns.ZoneField.NAME.selector())); + selector = (String) capturedOptions.getValue().get(ZONE_LIST_OPTIONS[3].rpcOption()); + assertEquals(DNS_NAME, selector); + // check the callback + ManagedZonesListResponse response = new ManagedZonesListResponse() + .setManagedZones(ZONE_LIST) + .setNextPageToken(PAGE_TOKEN); + RpcBatch.Callback capturedCallback = callback.getValue(); + EasyMock.verify(optionsMock); + EasyMock.reset(optionsMock); + EasyMock.expect(optionsMock.service()).andReturn(dns).times(ZONE_LIST.size()); + EasyMock.replay(optionsMock); + capturedCallback.onSuccess(response); + Page page = batchResult.get(); + assertEquals(PAGE_TOKEN, page.nextPageCursor()); + Iterator iterator = page.values().iterator(); + int resultSize = 0; + EasyMock.verify(dns); + EasyMock.reset(dns); + EasyMock.expect(dns.options()).andReturn(optionsMock).times(ZONE_LIST.size() + 1); + EasyMock.replay(dns); + Zone zoneInfoFunctional = new Zone(dns, new ZoneInfo.BuilderImpl(ZONE_INFO)); + while (iterator.hasNext()) { + assertEquals(zoneInfoFunctional, iterator.next()); + resultSize++; + } + assertEquals(ZONE_LIST.size(), resultSize); + } + + @Test + public void testCreateZone() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + Capture capturedZone = Capture.newInstance(); + batchMock.addCreateZone(EasyMock.capture(capturedZone), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.createZone(ZONE_INFO); + assertEquals(0, capturedOptions.getValue().size()); + assertEquals(ZONE_INFO.toPb(), capturedZone.getValue()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testCreateZoneWithOptions() { + EasyMock.reset(dns, batchMock, optionsMock); + EasyMock.expect(dns.options()).andReturn(optionsMock); + EasyMock.expect(optionsMock.service()).andReturn(dns); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + Capture capturedZone = Capture.newInstance(); + batchMock.addCreateZone(EasyMock.capture(capturedZone), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(dns, batchMock, optionsMock); + DnsBatchResult batchResult = dnsBatch.createZone(ZONE_INFO, ZONE_FIELDS); + assertEquals(ZONE_INFO.toPb(), capturedZone.getValue()); + assertNotNull(callback.getValue()); + String selector = (String) capturedOptions.getValue().get(ZONE_FIELDS.rpcOption()); + assertTrue(selector.contains(Dns.ZoneField.CREATION_TIME.selector())); + assertTrue(selector.contains(Dns.ZoneField.NAME.selector())); + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onSuccess(ZONE_INFO.toPb()); + assertEquals(ZONE_INFO.toPb(), batchResult.get().toPb()); + } + + @Test + public void testGetZone() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetZone(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.getZone(ZONE_NAME); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testGetZoneWithOptions() { + EasyMock.reset(dns, batchMock, optionsMock); + EasyMock.expect(dns.options()).andReturn(optionsMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetZone(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.expect(optionsMock.service()).andReturn(dns); + EasyMock.replay(dns, batchMock, optionsMock); + DnsBatchResult batchResult = dnsBatch.getZone(ZONE_NAME, ZONE_FIELDS); + assertNotNull(callback.getValue()); + String selector = (String) capturedOptions.getValue().get(ZONE_FIELDS.rpcOption()); + assertTrue(selector.contains(Dns.ZoneField.CREATION_TIME.selector())); + assertTrue(selector.contains(Dns.ZoneField.NAME.selector())); + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onSuccess(ZONE_INFO.toPb()); + assertEquals(ZONE_INFO.toPb(), batchResult.get().toPb()); + } + + @Test + public void testDeleteZone() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + batchMock.addDeleteZone(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.deleteZone(ZONE_NAME); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertFalse(ex.idempotent()); + } + } + + @Test + public void testDeleteZoneOnSuccess() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + batchMock.addDeleteZone(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.deleteZone(ZONE_NAME); + assertNotNull(callback.getValue()); + RpcBatch.Callback capturedCallback = callback.getValue(); + Void result = null; + capturedCallback.onSuccess(result); + assertTrue(batchResult.get()); + } + + @Test + public void testGetProject() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetProject(EasyMock.capture(callback), EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.getProject(); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testGetProjectWithOptions() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetProject(EasyMock.capture(callback), EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.getProject(PROJECT_FIELDS); + assertNotNull(callback.getValue()); + String selector = (String) capturedOptions.getValue().get(PROJECT_FIELDS.rpcOption()); + assertTrue(selector.contains(Dns.ProjectField.QUOTA.selector())); + assertTrue(selector.contains(Dns.ProjectField.PROJECT_ID.selector())); + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onSuccess(PROJECT_INFO.toPb()); + assertEquals(PROJECT_INFO, batchResult.get()); + } + + @Test + public void testListRecordSets() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListRecordSets(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = dnsBatch.listRecordSets(ZONE_NAME); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testListRecordSetsWithOptions() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListRecordSets(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = + dnsBatch.listRecordSets(ZONE_NAME, RECORD_SET_LIST_OPTIONS); + assertNotNull(callback.getValue()); + Integer size = (Integer) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[0].rpcOption()); + assertEquals(MAX_SIZE, size); + String selector = (String) capturedOptions.getValue() + .get(RECORD_SET_LIST_OPTIONS[1].rpcOption()); + assertEquals(PAGE_TOKEN, selector); + selector = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[2].rpcOption()); + assertTrue(selector.contains(Dns.RecordSetField.NAME.selector())); + assertTrue(selector.contains(Dns.RecordSetField.TTL.selector())); + selector = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[3].rpcOption()); + assertEquals(RECORD_SET_LIST_OPTIONS[3].value(), selector); + String type = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[4] + .rpcOption()); + assertEquals(RECORD_SET_LIST_OPTIONS[4].value(), type); + RpcBatch.Callback capturedCallback = callback.getValue(); + ResourceRecordSetsListResponse response = new ResourceRecordSetsListResponse() + .setRrsets(RECORD_SET_LIST) + .setNextPageToken(PAGE_TOKEN); + capturedCallback.onSuccess(response); + Page page = batchResult.get(); + assertEquals(PAGE_TOKEN, page.nextPageCursor()); + Iterator iterator = page.values().iterator(); + int resultSize = 0; + while (iterator.hasNext()) { + assertEquals(RECORD_SET, iterator.next()); + resultSize++; + } + assertEquals(RECORD_SET_LIST.size(), resultSize); + } + + @Test + public void testListChangeRequests() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListChangeRequests(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = dnsBatch.listChangeRequests(ZONE_NAME); + assertNotNull(callback.getValue()); + assertEquals(0, capturedOptions.getValue().size()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testListChangeRequestsWithOptions() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addListChangeRequests(EasyMock.eq(ZONE_NAME), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult> batchResult = + dnsBatch.listChangeRequests(ZONE_NAME, CHANGE_LIST_OPTIONS); + assertNotNull(callback.getValue()); + Integer size = (Integer) capturedOptions.getValue().get(CHANGE_LIST_OPTIONS[0].rpcOption()); + assertEquals(MAX_SIZE, size); + String selector = (String) capturedOptions.getValue().get(CHANGE_LIST_OPTIONS[1].rpcOption()); + assertEquals(PAGE_TOKEN, selector); + selector = (String) capturedOptions.getValue().get(CHANGE_LIST_OPTIONS[2].rpcOption()); + assertTrue(selector.contains(Dns.ChangeRequestField.STATUS.selector())); + assertTrue(selector.contains(Dns.ChangeRequestField.ID.selector())); + selector = (String) capturedOptions.getValue().get(CHANGE_LIST_OPTIONS[3].rpcOption()); + assertTrue(selector.contains(Dns.SortingOrder.ASCENDING.selector())); + // check the callback + ChangesListResponse response = new ChangesListResponse() + .setChanges(CHANGE_LIST) + .setNextPageToken(PAGE_TOKEN); + RpcBatch.Callback capturedCallback = callback.getValue(); + EasyMock.verify(optionsMock); + EasyMock.reset(optionsMock); + EasyMock.expect(optionsMock.service()).andReturn(dns); + EasyMock.replay(optionsMock); + capturedCallback.onSuccess(response); + Page page = batchResult.get(); + assertEquals(PAGE_TOKEN, page.nextPageCursor()); + Iterator iterator = page.values().iterator(); + int resultSize = 0; + EasyMock.verify(dns); + EasyMock.reset(dns); + EasyMock.expect(dns.options()).andReturn(optionsMock).times(CHANGE_LIST.size()); + EasyMock.replay(dns); + while (iterator.hasNext()) { + assertEquals(CHANGE_REQUEST_COMPLETE.toPb(), iterator.next().toPb()); + resultSize++; + } + assertEquals(CHANGE_LIST.size(), resultSize); + } + + @Test + public void testGetChangeRequest() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetChangeRequest(EasyMock.eq(ZONE_NAME), + EasyMock.eq(CHANGE_REQUEST_COMPLETE.generatedId()), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.getChangeRequest(ZONE_NAME, + CHANGE_REQUEST_COMPLETE.generatedId()); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertTrue(ex.idempotent()); + } + } + + @Test + public void testGetChangeRequestWithOptions() { + EasyMock.reset(dns, batchMock, optionsMock); + EasyMock.expect(dns.options()).andReturn(optionsMock); + EasyMock.expect(optionsMock.service()).andReturn(dns); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addGetChangeRequest(EasyMock.eq(ZONE_NAME), + EasyMock.eq(CHANGE_REQUEST_COMPLETE.generatedId()), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(dns, batchMock, optionsMock); + DnsBatchResult batchResult = dnsBatch.getChangeRequest(ZONE_NAME, + CHANGE_REQUEST_COMPLETE.generatedId(), CHANGE_GET_FIELDS); + assertNotNull(callback.getValue()); + String selector = (String) capturedOptions.getValue().get(CHANGE_GET_FIELDS.rpcOption()); + assertTrue(selector.contains(Dns.ChangeRequestField.STATUS.selector())); + assertTrue(selector.contains(Dns.ChangeRequestField.ID.selector())); + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onSuccess(CHANGE_REQUEST_COMPLETE.toPb()); + assertEquals(CHANGE_REQUEST_COMPLETE.toPb(), batchResult.get().toPb()); + } + + @Test + public void testApplyChangeRequest() { + EasyMock.reset(batchMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addApplyChangeRequest(EasyMock.eq(ZONE_NAME), + EasyMock.eq(CHANGE_REQUEST_PARTIAL.toPb()), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.replay(batchMock); + DnsBatchResult batchResult = dnsBatch.applyChangeRequest(ZONE_INFO.name(), + CHANGE_REQUEST_PARTIAL); + assertEquals(0, capturedOptions.getValue().size()); + assertNotNull(callback.getValue()); + try { + batchResult.get(); + fail("No result available yet."); + } catch (IllegalStateException ex) { + // expected + } + // testing error here, success is tested with options + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onFailure(GOOGLE_JSON_ERROR); + try { + batchResult.get(); + fail("Should throw a DnsException on error."); + } catch (DnsException ex) { + // expected + assertFalse(ex.idempotent()); + } + } + + @Test + public void testApplyChangeRequestWithOptions() { + EasyMock.reset(dns, batchMock, optionsMock); + EasyMock.expect(dns.options()).andReturn(optionsMock); + Capture> callback = Capture.newInstance(); + Capture> capturedOptions = Capture.newInstance(); + batchMock.addApplyChangeRequest(EasyMock.eq(ZONE_NAME), + EasyMock.eq(CHANGE_REQUEST_PARTIAL.toPb()), EasyMock.capture(callback), + EasyMock.capture(capturedOptions)); + EasyMock.expect(optionsMock.service()).andReturn(dns); + EasyMock.replay(dns, batchMock, optionsMock); + DnsBatchResult batchResult = dnsBatch.applyChangeRequest(ZONE_INFO.name(), + CHANGE_REQUEST_PARTIAL, CHANGE_GET_FIELDS); + String selector = (String) capturedOptions.getValue().get(CHANGE_GET_FIELDS.rpcOption()); + assertTrue(selector.contains(Dns.ChangeRequestField.STATUS.selector())); + assertTrue(selector.contains(Dns.ChangeRequestField.ID.selector())); + RpcBatch.Callback capturedCallback = callback.getValue(); + capturedCallback.onSuccess(CHANGE_REQUEST_COMPLETE.toPb()); + assertEquals(CHANGE_REQUEST_COMPLETE.toPb(), batchResult.get().toPb()); + } +} diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsImplTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsImplTest.java index 457f5ed3adb3..d34cb340e6e3 100644 --- a/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsImplTest.java +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/DnsImplTest.java @@ -91,7 +91,7 @@ public class DnsImplTest { Dns.ChangeRequestListOption.pageToken(PAGE_TOKEN), Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.STATUS), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING)}; - private static final Dns.RecordSetListOption[] DNS_RECORD_LIST_OPTIONS = { + private static final Dns.RecordSetListOption[] RECORD_SET_LIST_OPTIONS = { Dns.RecordSetListOption.pageSize(MAX_SIZE), Dns.RecordSetListOption.pageToken(PAGE_TOKEN), Dns.RecordSetListOption.fields(Dns.RecordSetField.TTL), @@ -350,7 +350,7 @@ public void testListZonesWithOptions() { } @Test - public void testListDnsRecords() { + public void testListRecordSets() { EasyMock.expect(dnsRpcMock.listRecordSets(ZONE_INFO.name(), EMPTY_RPC_OPTIONS)) .andReturn(LIST_OF_PB_DNS_RECORDS); EasyMock.replay(dnsRpcMock); @@ -362,28 +362,28 @@ public void testListDnsRecords() { } @Test - public void testListDnsRecordsWithOptions() { + public void testListRecordSetsWithOptions() { Capture> capturedOptions = Capture.newInstance(); EasyMock.expect(dnsRpcMock.listRecordSets(EasyMock.eq(ZONE_NAME), EasyMock.capture(capturedOptions))).andReturn(LIST_OF_PB_DNS_RECORDS); EasyMock.replay(dnsRpcMock); dns = options.service(); // creates DnsImpl - Page dnsPage = dns.listRecordSets(ZONE_NAME, DNS_RECORD_LIST_OPTIONS); + Page dnsPage = dns.listRecordSets(ZONE_NAME, RECORD_SET_LIST_OPTIONS); assertEquals(2, Lists.newArrayList(dnsPage.values()).size()); assertTrue(Lists.newArrayList(dnsPage.values()).contains(DNS_RECORD1)); assertTrue(Lists.newArrayList(dnsPage.values()).contains(DNS_RECORD2)); - Integer size = (Integer) capturedOptions.getValue().get(DNS_RECORD_LIST_OPTIONS[0].rpcOption()); + Integer size = (Integer) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[0].rpcOption()); assertEquals(MAX_SIZE, size); String selector = (String) capturedOptions.getValue() - .get(DNS_RECORD_LIST_OPTIONS[1].rpcOption()); + .get(RECORD_SET_LIST_OPTIONS[1].rpcOption()); assertEquals(PAGE_TOKEN, selector); - selector = (String) capturedOptions.getValue().get(DNS_RECORD_LIST_OPTIONS[2].rpcOption()); + selector = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[2].rpcOption()); assertTrue(selector.contains(Dns.RecordSetField.NAME.selector())); assertTrue(selector.contains(Dns.RecordSetField.TTL.selector())); - selector = (String) capturedOptions.getValue().get(DNS_RECORD_LIST_OPTIONS[3].rpcOption()); - assertEquals(DNS_RECORD_LIST_OPTIONS[3].value(), selector); - String type = (String) capturedOptions.getValue().get(DNS_RECORD_LIST_OPTIONS[4] + selector = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[3].rpcOption()); + assertEquals(RECORD_SET_LIST_OPTIONS[3].value(), selector); + String type = (String) capturedOptions.getValue().get(RECORD_SET_LIST_OPTIONS[4] .rpcOption()); - assertEquals(DNS_RECORD_LIST_OPTIONS[4].value(), type); + assertEquals(RECORD_SET_LIST_OPTIONS[4].value(), type); } } diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/SerializationTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/SerializationTest.java index e510850f62ab..2115c9dd98bf 100644 --- a/gcloud-java-dns/src/test/java/com/google/cloud/dns/SerializationTest.java +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/SerializationTest.java @@ -22,6 +22,8 @@ import com.google.cloud.RetryParams; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableList; + import java.io.Serializable; import java.math.BigInteger; import java.util.concurrent.TimeUnit; diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/it/ITDnsTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/it/ITDnsTest.java index dd8eafa775cd..5a27af8e28ae 100644 --- a/gcloud-java-dns/src/test/java/com/google/cloud/dns/it/ITDnsTest.java +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/it/ITDnsTest.java @@ -27,6 +27,12 @@ import com.google.cloud.dns.ChangeRequest; import com.google.cloud.dns.ChangeRequestInfo; import com.google.cloud.dns.Dns; +import com.google.cloud.dns.Dns.ChangeRequestField; +import com.google.cloud.dns.Dns.ProjectField; +import com.google.cloud.dns.Dns.RecordSetField; +import com.google.cloud.dns.Dns.ZoneField; +import com.google.cloud.dns.DnsBatch; +import com.google.cloud.dns.DnsBatchResult; import com.google.cloud.dns.DnsException; import com.google.cloud.dns.DnsOptions; import com.google.cloud.dns.ProjectInfo; @@ -34,6 +40,7 @@ import com.google.cloud.dns.Zone; import com.google.cloud.dns.ZoneInfo; import com.google.common.collect.ImmutableList; +import com.google.common.collect.Iterables; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -87,7 +94,7 @@ public class ITDnsTest { .build(); private static final List ZONE_NAMES = ImmutableList.of(ZONE_NAME1, ZONE_NAME_EMPTY_DESCRIPTION); - + @Rule public Timeout globalTimeout = Timeout.seconds(300); @@ -106,8 +113,7 @@ private static void clear() { List toDelete = new LinkedList<>(); while (recordSetIterator.hasNext()) { RecordSet recordSet = recordSetIterator.next(); - if (!ImmutableList.of(RecordSet.Type.NS, RecordSet.Type.SOA) - .contains(recordSet.type())) { + if (!ImmutableList.of(RecordSet.Type.NS, RecordSet.Type.SOA).contains(recordSet.type())) { toDelete.add(recordSet); } } @@ -151,7 +157,7 @@ private static void assertEqChangesIgnoreStatus(ChangeRequest expected, ChangeRe private static void waitForChangeToComplete(String zoneName, String changeId) { ChangeRequest changeRequest = DNS.getChangeRequest(zoneName, changeId, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); waitForChangeToComplete(changeRequest); } @@ -220,7 +226,7 @@ public void testCreateZoneWithErrors() { @Test public void testCreateZoneWithOptions() { try { - Zone created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.CREATION_TIME)); + Zone created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.CREATION_TIME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNotNull(created.creationTimeMillis()); assertNull(created.description()); @@ -229,7 +235,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.DESCRIPTION)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.DESCRIPTION)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertEquals(ZONE1.description(), created.description()); @@ -238,7 +244,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.DNS_NAME)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.DNS_NAME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertEquals(ZONE1.dnsName(), created.dnsName()); @@ -247,7 +253,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -256,7 +262,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME_SERVER_SET)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME_SERVER_SET)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -265,7 +271,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); // we did not set it assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME_SERVERS)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME_SERVERS)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -274,7 +280,7 @@ public void testCreateZoneWithOptions() { assertNull(created.nameServerSet()); assertNull(created.generatedId()); created.delete(); - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.ZONE_ID)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.ZONE_ID)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -284,8 +290,8 @@ public void testCreateZoneWithOptions() { assertNotNull(created.generatedId()); created.delete(); // combination of multiple things - created = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.ZONE_ID, - Dns.ZoneField.NAME_SERVERS, Dns.ZoneField.NAME_SERVER_SET, Dns.ZoneField.DESCRIPTION)); + created = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.ZONE_ID, + ZoneField.NAME_SERVERS, ZoneField.NAME_SERVER_SET, ZoneField.DESCRIPTION)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -301,8 +307,8 @@ public void testCreateZoneWithOptions() { @Test public void testGetZone() { try { - DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME)); - Zone created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.CREATION_TIME)); + DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); + Zone created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.CREATION_TIME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNotNull(created.creationTimeMillis()); assertNull(created.description()); @@ -310,7 +316,7 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNull(created.nameServerSet()); assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.DESCRIPTION)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.DESCRIPTION)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertEquals(ZONE1.description(), created.description()); @@ -318,7 +324,7 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNull(created.nameServerSet()); assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.DNS_NAME)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.DNS_NAME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertEquals(ZONE1.dnsName(), created.dnsName()); @@ -326,7 +332,7 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNull(created.nameServerSet()); assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.NAME)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -334,7 +340,7 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNull(created.nameServerSet()); assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.NAME_SERVER_SET)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME_SERVER_SET)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -342,7 +348,7 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNull(created.nameServerSet()); // we did not set it assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.NAME_SERVERS)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME_SERVERS)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -350,7 +356,7 @@ public void testGetZone() { assertFalse(created.nameServers().isEmpty()); assertNull(created.nameServerSet()); assertNull(created.generatedId()); - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.ZONE_ID)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.ZONE_ID)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -359,8 +365,8 @@ public void testGetZone() { assertTrue(created.nameServers().isEmpty()); // never returns null assertNotNull(created.generatedId()); // combination of multiple things - created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(Dns.ZoneField.ZONE_ID, - Dns.ZoneField.NAME_SERVERS, Dns.ZoneField.NAME_SERVER_SET, Dns.ZoneField.DESCRIPTION)); + created = DNS.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.ZONE_ID, + ZoneField.NAME_SERVERS, ZoneField.NAME_SERVER_SET, ZoneField.DESCRIPTION)); assertEquals(ZONE1.name(), created.name()); // always returned assertNull(created.creationTimeMillis()); assertNull(created.dnsName()); @@ -421,7 +427,7 @@ public void testListZones() { assertEquals(1, zones.size()); // field options Iterator zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.ZONE_ID)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.ZONE_ID)).iterateAll(); Zone zone = zoneIterator.next(); assertNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -432,7 +438,7 @@ public void testListZones() { assertNotNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.CREATION_TIME)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.CREATION_TIME)).iterateAll(); zone = zoneIterator.next(); assertNotNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -443,7 +449,7 @@ public void testListZones() { assertNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.DNS_NAME)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.DNS_NAME)).iterateAll(); zone = zoneIterator.next(); assertNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -454,7 +460,7 @@ public void testListZones() { assertNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.DESCRIPTION)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.DESCRIPTION)).iterateAll(); zone = zoneIterator.next(); assertNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -465,7 +471,7 @@ public void testListZones() { assertNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.NAME_SERVERS)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.NAME_SERVERS)).iterateAll(); zone = zoneIterator.next(); assertNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -476,7 +482,7 @@ public void testListZones() { assertNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); zoneIterator = DNS.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), - Dns.ZoneListOption.fields(Dns.ZoneField.NAME_SERVER_SET)).iterateAll(); + Dns.ZoneListOption.fields(ZoneField.NAME_SERVER_SET)).iterateAll(); zone = zoneIterator.next(); assertNull(zone.creationTimeMillis()); assertNotNull(zone.name()); @@ -487,8 +493,8 @@ public void testListZones() { assertNull(zone.generatedId()); assertFalse(zoneIterator.hasNext()); // several combined - zones = filter(DNS.listZones(Dns.ZoneListOption.fields(Dns.ZoneField.ZONE_ID, - Dns.ZoneField.DESCRIPTION), + zones = filter(DNS.listZones(Dns.ZoneListOption.fields(ZoneField.ZONE_ID, + ZoneField.DESCRIPTION), Dns.ZoneListOption.pageSize(1)).iterateAll()); assertEquals(2, zones.size()); for (Zone current : zones) { @@ -521,12 +527,12 @@ public void testDeleteZone() { @Test public void testCreateChange() { try { - DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME)); + DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); ChangeRequest created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1); assertEquals(CHANGE_ADD_ZONE1.additions(), created.additions()); assertNotNull(created.startTimeMillis()); assertTrue(created.deletions().isEmpty()); - assertEquals("1", created.generatedId()); + assertNotNull(created.generatedId()); assertTrue(ImmutableList.of(ChangeRequest.Status.PENDING, ChangeRequest.Status.DONE) .contains(created.status())); assertEqChangesIgnoreStatus(created, DNS.getChangeRequest(ZONE1.name(), "1")); @@ -535,51 +541,51 @@ public void testCreateChange() { waitForChangeToComplete(created); // with options created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ID)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ID)); assertTrue(created.additions().isEmpty()); assertNull(created.startTimeMillis()); assertTrue(created.deletions().isEmpty()); - assertEquals("3", created.generatedId()); + assertNotNull(created.generatedId()); assertNull(created.status()); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); assertTrue(created.additions().isEmpty()); assertNull(created.startTimeMillis()); assertTrue(created.deletions().isEmpty()); - assertEquals("5", created.generatedId()); + assertNotNull(created.generatedId()); assertNotNull(created.status()); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.START_TIME)); + Dns.ChangeRequestOption.fields(ChangeRequestField.START_TIME)); assertTrue(created.additions().isEmpty()); assertNotNull(created.startTimeMillis()); assertTrue(created.deletions().isEmpty()); - assertEquals("7", created.generatedId()); + assertNotNull(created.generatedId()); assertNull(created.status()); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ADDITIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ADDITIONS)); assertEquals(CHANGE_ADD_ZONE1.additions(), created.additions()); assertNull(created.startTimeMillis()); assertTrue(created.deletions().isEmpty()); - assertEquals("9", created.generatedId()); + assertNotNull(created.generatedId()); assertNull(created.status()); // finishes with delete otherwise we cannot delete the zone waitForChangeToComplete(created); created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.DELETIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); waitForChangeToComplete(created); assertEquals(CHANGE_DELETE_ZONE1.deletions(), created.deletions()); assertNull(created.startTimeMillis()); assertTrue(created.additions().isEmpty()); - assertEquals("10", created.generatedId()); + assertNotNull(created.generatedId()); assertNull(created.status()); waitForChangeToComplete(created); } finally { @@ -721,47 +727,47 @@ public void testListChanges() { // field options changes = ImmutableList.copyOf(DNS.listChangeRequests(ZONE1.name(), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), - Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.ADDITIONS)).iterateAll()); + Dns.ChangeRequestListOption.fields(ChangeRequestField.ADDITIONS)).iterateAll()); change = changes.get(1); assertEquals(CHANGE_ADD_ZONE1.additions(), change.additions()); assertTrue(change.deletions().isEmpty()); - assertEquals("1", change.generatedId()); + assertNotNull(change.generatedId()); assertNull(change.startTimeMillis()); assertNull(change.status()); changes = ImmutableList.copyOf(DNS.listChangeRequests(ZONE1.name(), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), - Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.DELETIONS)).iterateAll()); + Dns.ChangeRequestListOption.fields(ChangeRequestField.DELETIONS)).iterateAll()); change = changes.get(2); assertTrue(change.additions().isEmpty()); assertNotNull(change.deletions()); - assertEquals("2", change.generatedId()); + assertNotNull(change.generatedId()); assertNull(change.startTimeMillis()); assertNull(change.status()); changes = ImmutableList.copyOf(DNS.listChangeRequests(ZONE1.name(), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), - Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.ID)).iterateAll()); + Dns.ChangeRequestListOption.fields(ChangeRequestField.ID)).iterateAll()); change = changes.get(1); assertTrue(change.additions().isEmpty()); assertTrue(change.deletions().isEmpty()); - assertEquals("1", change.generatedId()); + assertNotNull(change.generatedId()); assertNull(change.startTimeMillis()); assertNull(change.status()); changes = ImmutableList.copyOf(DNS.listChangeRequests(ZONE1.name(), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), - Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.START_TIME)).iterateAll()); + Dns.ChangeRequestListOption.fields(ChangeRequestField.START_TIME)).iterateAll()); change = changes.get(1); assertTrue(change.additions().isEmpty()); assertTrue(change.deletions().isEmpty()); - assertEquals("1", change.generatedId()); + assertNotNull(change.generatedId()); assertNotNull(change.startTimeMillis()); assertNull(change.status()); changes = ImmutableList.copyOf(DNS.listChangeRequests(ZONE1.name(), Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), - Dns.ChangeRequestListOption.fields(Dns.ChangeRequestField.STATUS)).iterateAll()); + Dns.ChangeRequestListOption.fields(ChangeRequestField.STATUS)).iterateAll()); change = changes.get(1); assertTrue(change.additions().isEmpty()); assertTrue(change.deletions().isEmpty()); - assertEquals("1", change.generatedId()); + assertNotNull(change.generatedId()); assertNull(change.startTimeMillis()); assertEquals(ChangeRequest.Status.DONE, change.status()); } finally { @@ -772,7 +778,7 @@ public void testListChanges() { @Test public void testGetChange() { try { - Zone zone = DNS.create(ZONE1, Dns.ZoneOption.fields(Dns.ZoneField.NAME)); + Zone zone = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); ChangeRequest created = zone.applyChangeRequest(CHANGE_ADD_ZONE1); ChangeRequest retrieved = DNS.getChangeRequest(zone.name(), created.generatedId()); assertEqChangesIgnoreStatus(created, retrieved); @@ -780,37 +786,37 @@ public void testGetChange() { zone.applyChangeRequest(CHANGE_DELETE_ZONE1); // with options created = zone.applyChangeRequest(CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ID)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ID)); retrieved = DNS.getChangeRequest(zone.name(), created.generatedId(), - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ID)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ID)); assertEqChangesIgnoreStatus(created, retrieved); waitForChangeToComplete(zone.name(), created.generatedId()); zone.applyChangeRequest(CHANGE_DELETE_ZONE1); created = zone.applyChangeRequest(CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); retrieved = DNS.getChangeRequest(zone.name(), created.generatedId(), - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.STATUS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); assertEqChangesIgnoreStatus(created, retrieved); waitForChangeToComplete(zone.name(), created.generatedId()); zone.applyChangeRequest(CHANGE_DELETE_ZONE1); created = zone.applyChangeRequest(CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.START_TIME)); + Dns.ChangeRequestOption.fields(ChangeRequestField.START_TIME)); retrieved = DNS.getChangeRequest(zone.name(), created.generatedId(), - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.START_TIME)); + Dns.ChangeRequestOption.fields(ChangeRequestField.START_TIME)); assertEqChangesIgnoreStatus(created, retrieved); waitForChangeToComplete(zone.name(), created.generatedId()); zone.applyChangeRequest(CHANGE_DELETE_ZONE1); created = zone.applyChangeRequest(CHANGE_ADD_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ADDITIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ADDITIONS)); retrieved = DNS.getChangeRequest(zone.name(), created.generatedId(), - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.ADDITIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.ADDITIONS)); assertEqChangesIgnoreStatus(created, retrieved); waitForChangeToComplete(zone.name(), created.generatedId()); // finishes with delete otherwise we cannot delete the zone created = zone.applyChangeRequest(CHANGE_DELETE_ZONE1, - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.DELETIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); retrieved = DNS.getChangeRequest(zone.name(), created.generatedId(), - Dns.ChangeRequestOption.fields(Dns.ChangeRequestField.DELETIONS)); + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); assertEqChangesIgnoreStatus(created, retrieved); waitForChangeToComplete(zone.name(), created.generatedId()); } finally { @@ -824,14 +830,14 @@ public void testGetProject() { ProjectInfo project = DNS.getProject(); assertNotNull(project.quota()); // options - project = DNS.getProject(Dns.ProjectOption.fields(Dns.ProjectField.QUOTA)); + project = DNS.getProject(Dns.ProjectOption.fields(ProjectField.QUOTA)); assertNotNull(project.quota()); - project = DNS.getProject(Dns.ProjectOption.fields(Dns.ProjectField.PROJECT_ID)); + project = DNS.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_ID)); assertNull(project.quota()); - project = DNS.getProject(Dns.ProjectOption.fields(Dns.ProjectField.PROJECT_NUMBER)); + project = DNS.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_NUMBER)); assertNull(project.quota()); - project = DNS.getProject(Dns.ProjectOption.fields(Dns.ProjectField.PROJECT_NUMBER, - Dns.ProjectField.QUOTA, Dns.ProjectField.PROJECT_ID)); + project = DNS.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_NUMBER, + ProjectField.QUOTA, ProjectField.PROJECT_ID)); assertNotNull(project.quota()); } @@ -849,7 +855,7 @@ public void testListDnsRecords() { } // field options Iterator recordSetIterator = DNS.listRecordSets(zone.name(), - Dns.RecordSetListOption.fields(Dns.RecordSetField.TTL)).iterateAll(); + Dns.RecordSetListOption.fields(RecordSetField.TTL)).iterateAll(); int counter = 0; while (recordSetIterator.hasNext()) { RecordSet recordSet = recordSetIterator.next(); @@ -861,7 +867,7 @@ public void testListDnsRecords() { } assertEquals(2, counter); recordSetIterator = DNS.listRecordSets(zone.name(), - Dns.RecordSetListOption.fields(Dns.RecordSetField.NAME)).iterateAll(); + Dns.RecordSetListOption.fields(RecordSetField.NAME)).iterateAll(); counter = 0; while (recordSetIterator.hasNext()) { RecordSet recordSet = recordSetIterator.next(); @@ -873,7 +879,7 @@ public void testListDnsRecords() { } assertEquals(2, counter); recordSetIterator = DNS.listRecordSets(zone.name(), - Dns.RecordSetListOption.fields(Dns.RecordSetField.DNS_RECORDS)) + Dns.RecordSetListOption.fields(RecordSetField.DNS_RECORDS)) .iterateAll(); counter = 0; while (recordSetIterator.hasNext()) { @@ -886,7 +892,7 @@ public void testListDnsRecords() { } assertEquals(2, counter); recordSetIterator = DNS.listRecordSets(zone.name(), - Dns.RecordSetListOption.fields(Dns.RecordSetField.TYPE), + Dns.RecordSetListOption.fields(RecordSetField.TYPE), Dns.RecordSetListOption.pageSize(1)).iterateAll(); // also test paging counter = 0; while (recordSetIterator.hasNext()) { @@ -900,7 +906,7 @@ public void testListDnsRecords() { assertEquals(2, counter); // test page size Page recordSetPage = DNS.listRecordSets(zone.name(), - Dns.RecordSetListOption.fields(Dns.RecordSetField.TYPE), + Dns.RecordSetListOption.fields(RecordSetField.TYPE), Dns.RecordSetListOption.pageSize(1)); assertEquals(1, ImmutableList.copyOf(recordSetPage.values().iterator()).size()); // test name filter @@ -920,8 +926,7 @@ public void testListDnsRecords() { waitForChangeToComplete(ZONE1.name(), change.generatedId()); recordSetIterator = DNS.listRecordSets(ZONE1.name(), Dns.RecordSetListOption.dnsName(A_RECORD_ZONE1.name()), - Dns.RecordSetListOption.type(A_RECORD_ZONE1.type())) - .iterateAll(); + Dns.RecordSetListOption.type(A_RECORD_ZONE1.type())).iterateAll(); counter = 0; while (recordSetIterator.hasNext()) { RecordSet recordSet = recordSetIterator.next(); @@ -962,4 +967,915 @@ public void testListDnsRecords() { clear(); } } + + @Test + public void testListZonesBatch() { + try { + DnsBatch batch = DNS.batch(); + DnsBatchResult> result = batch.listZones(); + batch.submit(); + List zones = filter(result.get().iterateAll()); + assertEquals(0, zones.size()); + // some zones exists + Zone firstZone = DNS.create(ZONE1); + batch = DNS.batch(); + result = batch.listZones(); + batch.submit(); + zones = filter(result.get().iterateAll()); + assertEquals(1, zones.size()); + assertEquals(firstZone, zones.get(0)); + Zone created = DNS.create(ZONE_EMPTY_DESCRIPTION); + batch = DNS.batch(); + result = batch.listZones(); + DnsBatchResult> zeroSizeError = + batch.listZones(Dns.ZoneListOption.pageSize(0)); + DnsBatchResult> negativeSizeError = + batch.listZones(Dns.ZoneListOption.pageSize(-1)); + DnsBatchResult> okSize = batch.listZones(Dns.ZoneListOption.pageSize(1)); + DnsBatchResult> nameError = batch.listZones(Dns.ZoneListOption.dnsName("aaaaa")); + DnsBatchResult> okName = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName())); + DnsBatchResult> idResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.ZONE_ID)); + DnsBatchResult> timeResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.CREATION_TIME)); + DnsBatchResult> dnsNameResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.DNS_NAME)); + DnsBatchResult> descriptionResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.DESCRIPTION)); + DnsBatchResult> nameServersResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.NAME_SERVERS)); + DnsBatchResult> nameServerSetResult = + batch.listZones(Dns.ZoneListOption.dnsName(ZONE1.dnsName()), + Dns.ZoneListOption.fields(ZoneField.NAME_SERVER_SET)); + DnsBatchResult> combinationResult = + batch.listZones(Dns.ZoneListOption.fields(ZoneField.ZONE_ID, ZoneField.DESCRIPTION), + Dns.ZoneListOption.pageSize(1)); + batch.submit(); + zones = filter(result.get().iterateAll()); + assertEquals(2, zones.size()); + assertTrue(zones.contains(firstZone)); + assertTrue(zones.contains(created)); + // error in options + try { + zeroSizeError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + try { + negativeSizeError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + // ok size + assertEquals(1, Iterables.size(okSize.get().values())); + // dns name problems + try { + nameError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + // ok name + zones = filter(okName.get().iterateAll()); + assertEquals(1, zones.size()); + // field options + Iterator zoneIterator = idResult.get().iterateAll(); + Zone zone = zoneIterator.next(); + assertNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNull(zone.dnsName()); + assertNull(zone.description()); + assertNull(zone.nameServerSet()); + assertTrue(zone.nameServers().isEmpty()); + assertNotNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + zoneIterator = timeResult.get().iterateAll(); + zone = zoneIterator.next(); + assertNotNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNull(zone.dnsName()); + assertNull(zone.description()); + assertNull(zone.nameServerSet()); + assertTrue(zone.nameServers().isEmpty()); + assertNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + zoneIterator = dnsNameResult.get().iterateAll(); + zone = zoneIterator.next(); + assertNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNotNull(zone.dnsName()); + assertNull(zone.description()); + assertNull(zone.nameServerSet()); + assertTrue(zone.nameServers().isEmpty()); + assertNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + zoneIterator = descriptionResult.get().iterateAll(); + zone = zoneIterator.next(); + assertNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNull(zone.dnsName()); + assertNotNull(zone.description()); + assertNull(zone.nameServerSet()); + assertTrue(zone.nameServers().isEmpty()); + assertNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + zoneIterator = nameServersResult.get().iterateAll(); + zone = zoneIterator.next(); + assertNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNull(zone.dnsName()); + assertNull(zone.description()); + assertNull(zone.nameServerSet()); + assertFalse(zone.nameServers().isEmpty()); + assertNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + zoneIterator = nameServerSetResult.get().iterateAll(); + zone = zoneIterator.next(); + assertNull(zone.creationTimeMillis()); + assertNotNull(zone.name()); + assertNull(zone.dnsName()); + assertNull(zone.description()); + assertNull(zone.nameServerSet()); // we cannot set it using gcloud java + assertTrue(zone.nameServers().isEmpty()); + assertNull(zone.generatedId()); + assertFalse(zoneIterator.hasNext()); + // several combined + zones = filter(combinationResult.get().iterateAll()); + assertEquals(2, zones.size()); + for (Zone current : zones) { + assertNull(current.creationTimeMillis()); + assertNotNull(current.name()); + assertNull(current.dnsName()); + assertNotNull(current.description()); + assertNull(current.nameServerSet()); + assertTrue(zone.nameServers().isEmpty()); + assertNotNull(current.generatedId()); + } + } finally { + DNS.delete(ZONE1.name()); + DNS.delete(ZONE_EMPTY_DESCRIPTION.name()); + } + } + + @Test + public void testCreateValidZoneBatch() { + try { + DnsBatch batch = DNS.batch(); + DnsBatchResult completeZoneResult = batch.createZone(ZONE1); + DnsBatchResult partialZoneResult = batch.createZone(ZONE_EMPTY_DESCRIPTION); + batch.submit(); + Zone created = completeZoneResult.get(); + assertEquals(ZONE1.description(), created.description()); + assertEquals(ZONE1.dnsName(), created.dnsName()); + assertEquals(ZONE1.name(), created.name()); + assertNotNull(created.creationTimeMillis()); + assertNotNull(created.nameServers()); + assertNull(created.nameServerSet()); + assertNotNull(created.generatedId()); + Zone retrieved = DNS.getZone(ZONE1.name()); + assertEquals(created, retrieved); + created = partialZoneResult.get(); + assertEquals(ZONE_EMPTY_DESCRIPTION.description(), created.description()); + assertEquals(ZONE_EMPTY_DESCRIPTION.dnsName(), created.dnsName()); + assertEquals(ZONE_EMPTY_DESCRIPTION.name(), created.name()); + assertNotNull(created.creationTimeMillis()); + assertNotNull(created.nameServers()); + assertNull(created.nameServerSet()); + assertNotNull(created.generatedId()); + retrieved = DNS.getZone(ZONE_EMPTY_DESCRIPTION.name()); + assertEquals(created, retrieved); + } finally { + DNS.delete(ZONE1.name()); + DNS.delete(ZONE_EMPTY_DESCRIPTION.name()); + } + } + + @Test + public void testCreateZoneWithErrorsBatch() { + try { + DnsBatch batch = DNS.batch(); + DnsBatchResult nameErrorResult = batch.createZone(ZONE_NAME_ERROR); + DnsBatchResult noPeriodResult = batch.createZone(ZONE_DNS_NO_PERIOD); + batch.submit(); + try { + nameErrorResult.get(); + fail("Zone name is missing a period. The service returns an error."); + } catch (DnsException ex) { + // expected + assertFalse(ex.retryable()); + } + try { + noPeriodResult.get(); + fail("Zone name is missing a period. The service returns an error."); + } catch (DnsException ex) { + // expected + assertFalse(ex.retryable()); + } + } finally { + DNS.delete(ZONE_NAME_ERROR.name()); + DNS.delete(ZONE_DNS_NO_PERIOD.name()); + } + } + + @Test + public void testCreateZoneWithOptionsBatch() { + try { + DnsBatch batch = DNS.batch(); + DnsBatchResult batchResult = + batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.CREATION_TIME)); + batch.submit(); + Zone created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNotNull(created.creationTimeMillis()); + assertNull(created.description()); + assertNull(created.dnsName()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.DESCRIPTION)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertEquals(ZONE1.description(), created.description()); + assertNull(created.dnsName()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.DNS_NAME)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertEquals(ZONE1.dnsName(), created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME_SERVER_SET)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); // we did not set it + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME_SERVERS)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertFalse(created.nameServers().isEmpty()); + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.ZONE_ID)); + batch.submit(); + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertNotNull(created.nameServers()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNotNull(created.generatedId()); + created.delete(); + batch = DNS.batch(); + batchResult = batch.createZone(ZONE1, Dns.ZoneOption.fields(ZoneField.ZONE_ID, + ZoneField.NAME_SERVERS, ZoneField.NAME_SERVER_SET, ZoneField.DESCRIPTION)); + batch.submit(); + // combination of multiple things + created = batchResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertEquals(ZONE1.description(), created.description()); + assertFalse(created.nameServers().isEmpty()); + assertNull(created.nameServerSet()); // we did not set it + assertNotNull(created.generatedId()); + } finally { + DNS.delete(ZONE1.name()); + } + } + + @Test + public void testGetZoneBatch() { + try { + DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); + DnsBatch batch = DNS.batch(); + DnsBatchResult timeResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.CREATION_TIME)); + DnsBatchResult descriptionResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.DESCRIPTION)); + DnsBatchResult dnsNameResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.DNS_NAME)); + DnsBatchResult nameResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME)); + DnsBatchResult nameServerSetResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME_SERVER_SET)); + DnsBatchResult nameServersResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.NAME_SERVERS)); + DnsBatchResult idResult = + batch.getZone(ZONE1.name(), Dns.ZoneOption.fields(ZoneField.ZONE_ID)); + DnsBatchResult combinationResult = batch.getZone(ZONE1.name(), + Dns.ZoneOption.fields(ZoneField.ZONE_ID, ZoneField.NAME_SERVERS, + ZoneField.NAME_SERVER_SET, ZoneField.DESCRIPTION)); + batch.submit(); + Zone created = timeResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNotNull(created.creationTimeMillis()); + assertNull(created.description()); + assertNull(created.dnsName()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created = descriptionResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertEquals(ZONE1.description(), created.description()); + assertNull(created.dnsName()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created = dnsNameResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertEquals(ZONE1.dnsName(), created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created = nameResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created = nameServerSetResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNull(created.nameServerSet()); // we did not set it + assertNull(created.generatedId()); + created = nameServersResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertFalse(created.nameServers().isEmpty()); + assertNull(created.nameServerSet()); + assertNull(created.generatedId()); + created = idResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertNull(created.description()); + assertNotNull(created.nameServers()); + assertTrue(created.nameServers().isEmpty()); // never returns null + assertNotNull(created.generatedId()); + // combination of multiple things + created = combinationResult.get(); + assertEquals(ZONE1.name(), created.name()); // always returned + assertNull(created.creationTimeMillis()); + assertNull(created.dnsName()); + assertEquals(ZONE1.description(), created.description()); + assertFalse(created.nameServers().isEmpty()); + assertNull(created.nameServerSet()); // we did not set it + assertNotNull(created.generatedId()); + } finally { + DNS.delete(ZONE1.name()); + } + } + + @Test + public void testDeleteZoneBatch() { + try { + Zone created = DNS.create(ZONE1); + assertEquals(created, DNS.getZone(ZONE1.name())); + DnsBatch batch = DNS.batch(); + DnsBatchResult result = batch.deleteZone(ZONE1.name()); + batch.submit(); + assertNull(DNS.getZone(ZONE1.name())); + assertTrue(result.get()); + } finally { + DNS.delete(ZONE1.name()); + } + } + + @Test + public void testGetProjectBatch() { + // fetches all fields + DnsBatch batch = DNS.batch(); + DnsBatchResult result = batch.getProject(); + DnsBatchResult resultQuota = + batch.getProject(Dns.ProjectOption.fields(ProjectField.QUOTA)); + DnsBatchResult resultId = + batch.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_ID)); + DnsBatchResult resultNumber = + batch.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_NUMBER)); + DnsBatchResult resultCombination = + batch.getProject(Dns.ProjectOption.fields(ProjectField.PROJECT_NUMBER, + ProjectField.QUOTA, ProjectField.PROJECT_ID)); + batch.submit(); + assertNotNull(result.get().quota()); + assertNotNull(resultQuota.get().quota()); + assertNull(resultId.get().quota()); + assertNull(resultNumber.get().quota()); + assertNotNull(resultCombination.get().quota()); + } + + @Test + public void testCreateChangeBatch() { + try { + DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); + DnsBatch batch = DNS.batch(); + DnsBatchResult result = + batch.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1); + batch.submit(); + ChangeRequest created = result.get(); + assertEquals(CHANGE_ADD_ZONE1.additions(), created.additions()); + assertNotNull(created.startTimeMillis()); + assertTrue(created.deletions().isEmpty()); + assertNotNull(created.generatedId()); + assertTrue(ImmutableList.of(ChangeRequest.Status.PENDING, ChangeRequest.Status.DONE) + .contains(created.status())); + assertEqChangesIgnoreStatus(created, DNS.getChangeRequest(ZONE1.name(), "1")); + waitForChangeToComplete(created); + created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); + waitForChangeToComplete(created); + // with options + batch = DNS.batch(); + result = batch.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.ID)); + batch.submit(); + created = result.get(); + assertTrue(created.additions().isEmpty()); + assertNull(created.startTimeMillis()); + assertTrue(created.deletions().isEmpty()); + assertNotNull(created.generatedId()); + assertNull(created.status()); + waitForChangeToComplete(created); + created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); + waitForChangeToComplete(created); + batch = DNS.batch(); + result = batch.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); + batch.submit(); + created = result.get(); + assertTrue(created.additions().isEmpty()); + assertNull(created.startTimeMillis()); + assertTrue(created.deletions().isEmpty()); + assertNotNull(created.generatedId()); + assertNotNull(created.status()); + waitForChangeToComplete(created); + created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); + waitForChangeToComplete(created); + batch = DNS.batch(); + result = batch.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.START_TIME)); + batch.submit(); + created = result.get(); + assertTrue(created.additions().isEmpty()); + assertNotNull(created.startTimeMillis()); + assertTrue(created.deletions().isEmpty()); + assertNotNull(created.generatedId()); + assertNull(created.status()); + waitForChangeToComplete(created); + created = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); + waitForChangeToComplete(created); + batch = DNS.batch(); + result = batch.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.ADDITIONS)); + batch.submit(); + created = result.get(); + assertEquals(CHANGE_ADD_ZONE1.additions(), created.additions()); + assertNull(created.startTimeMillis()); + assertTrue(created.deletions().isEmpty()); + assertNotNull(created.generatedId()); + assertNull(created.status()); + // finishes with delete otherwise we cannot delete the zone + waitForChangeToComplete(created); + batch = DNS.batch(); + result = batch.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); + batch.submit(); + created = result.get(); + waitForChangeToComplete(created); + assertEquals(CHANGE_DELETE_ZONE1.deletions(), created.deletions()); + assertNull(created.startTimeMillis()); + assertTrue(created.additions().isEmpty()); + assertNotNull(created.generatedId()); + assertNull(created.status()); + waitForChangeToComplete(created); + } finally { + clear(); + } + } + + @Test + public void testGetChangeBatch() { + try { + Zone zone = DNS.create(ZONE1, Dns.ZoneOption.fields(ZoneField.NAME)); + ChangeRequest created = zone.applyChangeRequest(CHANGE_ADD_ZONE1); + waitForChangeToComplete(zone.name(), created.generatedId()); + DnsBatch batch = DNS.batch(); + DnsBatchResult completeResult = + batch.getChangeRequest(zone.name(), created.generatedId()); + DnsBatchResult idResult = + batch.getChangeRequest(zone.name(), created.generatedId(), + Dns.ChangeRequestOption.fields(ChangeRequestField.ID)); + DnsBatchResult statusResult = + batch.getChangeRequest(zone.name(), created.generatedId(), + Dns.ChangeRequestOption.fields(ChangeRequestField.STATUS)); + DnsBatchResult timeResult = + batch.getChangeRequest(zone.name(), created.generatedId(), + Dns.ChangeRequestOption.fields(ChangeRequestField.START_TIME)); + DnsBatchResult additionsResult = + batch.getChangeRequest(zone.name(), created.generatedId(), + Dns.ChangeRequestOption.fields(ChangeRequestField.ADDITIONS)); + batch.submit(); + assertEqChangesIgnoreStatus(created, completeResult.get()); + // with options + ChangeRequest retrieved = idResult.get(); + assertEquals(created.generatedId(), retrieved.generatedId()); + assertEquals(0, retrieved.additions().size()); + assertEquals(0, retrieved.deletions().size()); + assertNull(retrieved.startTimeMillis()); + assertNull(retrieved.status()); + retrieved = statusResult.get(); + assertEquals(created.generatedId(), retrieved.generatedId()); + assertEquals(0, retrieved.additions().size()); + assertEquals(0, retrieved.deletions().size()); + assertNull(retrieved.startTimeMillis()); + assertEquals(ChangeRequestInfo.Status.DONE, retrieved.status()); + retrieved = timeResult.get(); + assertEquals(created.generatedId(), retrieved.generatedId()); + assertEquals(0, retrieved.additions().size()); + assertEquals(0, retrieved.deletions().size()); + assertEquals(created.startTimeMillis(), retrieved.startTimeMillis()); + assertNull(retrieved.status()); + retrieved = additionsResult.get(); + assertEquals(created.generatedId(), retrieved.generatedId()); + assertEquals(2, retrieved.additions().size()); + assertTrue(retrieved.additions().contains(A_RECORD_ZONE1)); + assertTrue(retrieved.additions().contains(AAAA_RECORD_ZONE1)); + assertEquals(0, retrieved.deletions().size()); + assertNull(retrieved.startTimeMillis()); + assertNull(retrieved.status()); + // finishes with delete otherwise we cannot delete the zone + created = zone.applyChangeRequest(CHANGE_DELETE_ZONE1, + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); + batch = DNS.batch(); + DnsBatchResult deletionsResult = + batch.getChangeRequest(zone.name(), created.generatedId(), + Dns.ChangeRequestOption.fields(ChangeRequestField.DELETIONS)); + batch.submit(); + retrieved = deletionsResult.get(); + assertEquals(created.generatedId(), retrieved.generatedId()); + assertEquals(0, retrieved.additions().size()); + assertEquals(2, retrieved.deletions().size()); + assertTrue(retrieved.deletions().contains(AAAA_RECORD_ZONE1)); + assertTrue(retrieved.deletions().contains(A_RECORD_ZONE1)); + assertNull(retrieved.startTimeMillis()); + assertNull(retrieved.status()); + waitForChangeToComplete(zone.name(), created.generatedId()); + } finally { + clear(); + } + } + + @Test + public void testListChangesBatch() { + try { + DnsBatch batch = DNS.batch(); + DnsBatchResult> result = batch.listChangeRequests(ZONE1.name()); + batch.submit(); + try { + result.get(); + fail("Zone does not exist yet"); + } catch (DnsException ex) { + // expected + assertEquals(404, ex.code()); + assertFalse(ex.retryable()); + } + // zone exists but has no changes + DNS.create(ZONE1); + batch = DNS.batch(); + result = batch.listChangeRequests(ZONE1.name()); + batch.submit(); + assertEquals(1, Iterables.size(result.get().values())); // default change creating SOA and NS + // zone has changes + ChangeRequest change = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1); + waitForChangeToComplete(ZONE1.name(), change.generatedId()); + change = DNS.applyChangeRequest(ZONE1.name(), CHANGE_DELETE_ZONE1); + waitForChangeToComplete(ZONE1.name(), change.generatedId()); + batch = DNS.batch(); + result = batch.listChangeRequests(ZONE1.name()); + DnsBatchResult> errorPageSize = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.pageSize(0)); + DnsBatchResult> errorPageNegative = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.pageSize(-1)); + DnsBatchResult> resultAscending = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING)); + DnsBatchResult> resultDescending = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.DESCENDING)); + DnsBatchResult> resultAdditions = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), + Dns.ChangeRequestListOption.fields(ChangeRequestField.ADDITIONS)); + DnsBatchResult> resultDeletions = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), + Dns.ChangeRequestListOption.fields(ChangeRequestField.DELETIONS)); + DnsBatchResult> resultId = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), + Dns.ChangeRequestListOption.fields(ChangeRequestField.ID)); + DnsBatchResult> resultTime = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), + Dns.ChangeRequestListOption.fields(ChangeRequestField.START_TIME)); + DnsBatchResult> resultStatus = batch.listChangeRequests(ZONE1.name(), + Dns.ChangeRequestListOption.sortOrder(Dns.SortingOrder.ASCENDING), + Dns.ChangeRequestListOption.fields(ChangeRequestField.STATUS)); + batch.submit(); + assertEquals(3, Iterables.size(result.get().values())); + // error in options + try { + errorPageSize.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + try { + errorPageNegative.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + // sorting order + ImmutableList ascending = + ImmutableList.copyOf(resultAscending.get().iterateAll()); + ImmutableList descending = + ImmutableList.copyOf(resultDescending.get().iterateAll()); + int size = 3; + assertEquals(size, descending.size()); + assertEquals(size, ascending.size()); + for (int i = 0; i < size; i++) { + assertEquals(descending.get(i), ascending.get(size - i - 1)); + } + // field options + change = Iterables.get(resultAdditions.get().values(), 1); + assertEquals(CHANGE_ADD_ZONE1.additions(), change.additions()); + assertTrue(change.deletions().isEmpty()); + assertNotNull(change.generatedId()); + assertNull(change.startTimeMillis()); + assertNull(change.status()); + change = Iterables.get(resultDeletions.get().values(), 2); + assertTrue(change.additions().isEmpty()); + assertNotNull(change.deletions()); + assertNotNull(change.generatedId()); + assertNull(change.startTimeMillis()); + assertNull(change.status()); + change = Iterables.get(resultId.get().values(), 1); + assertTrue(change.additions().isEmpty()); + assertTrue(change.deletions().isEmpty()); + assertNotNull(change.generatedId()); + assertNull(change.startTimeMillis()); + assertNull(change.status()); + change = Iterables.get(resultTime.get().values(), 1); + assertTrue(change.additions().isEmpty()); + assertTrue(change.deletions().isEmpty()); + assertNotNull(change.generatedId()); + assertNotNull(change.startTimeMillis()); + assertNull(change.status()); + change = Iterables.get(resultStatus.get().values(), 1); + assertTrue(change.additions().isEmpty()); + assertTrue(change.deletions().isEmpty()); + assertNotNull(change.generatedId()); + assertNull(change.startTimeMillis()); + assertEquals(ChangeRequest.Status.DONE, change.status()); + } finally { + clear(); + } + } + + @Test + public void testListDnsRecordSetsBatch() { + try { + Zone zone = DNS.create(ZONE1); + DnsBatch batch = DNS.batch(); + DnsBatchResult> result = batch.listRecordSets(zone.name()); + batch.submit(); + ImmutableList recordSets = ImmutableList.copyOf(result.get().iterateAll()); + assertEquals(2, recordSets.size()); + ImmutableList defaultRecords = + ImmutableList.of(RecordSet.Type.NS, RecordSet.Type.SOA); + for (RecordSet recordSet : recordSets) { + assertTrue(defaultRecords.contains(recordSet.type())); + } + // field options + batch = DNS.batch(); + DnsBatchResult> ttlResult = batch.listRecordSets(zone.name(), + Dns.RecordSetListOption.fields(RecordSetField.TTL)); + DnsBatchResult> nameResult = batch.listRecordSets(zone.name(), + Dns.RecordSetListOption.fields(RecordSetField.NAME)); + DnsBatchResult> recordsResult = batch.listRecordSets(zone.name(), + Dns.RecordSetListOption.fields(RecordSetField.DNS_RECORDS)); + DnsBatchResult> pageSizeResult = batch.listRecordSets(zone.name(), + Dns.RecordSetListOption.fields(RecordSetField.TYPE), + Dns.RecordSetListOption.pageSize(1)); + batch.submit(); + Iterator recordSetIterator = ttlResult.get().iterateAll(); + int counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertEquals(recordSets.get(counter).ttl(), recordSet.ttl()); + assertEquals(recordSets.get(counter).name(), recordSet.name()); + assertEquals(recordSets.get(counter).type(), recordSet.type()); + assertTrue(recordSet.records().isEmpty()); + counter++; + } + assertEquals(2, counter); + recordSetIterator = nameResult.get().iterateAll(); + counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertEquals(recordSets.get(counter).name(), recordSet.name()); + assertEquals(recordSets.get(counter).type(), recordSet.type()); + assertTrue(recordSet.records().isEmpty()); + assertNull(recordSet.ttl()); + counter++; + } + assertEquals(2, counter); + recordSetIterator = recordsResult.get().iterateAll(); + counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertEquals(recordSets.get(counter).records(), recordSet.records()); + assertEquals(recordSets.get(counter).name(), recordSet.name()); + assertEquals(recordSets.get(counter).type(), recordSet.type()); + assertNull(recordSet.ttl()); + counter++; + } + assertEquals(2, counter); + recordSetIterator = pageSizeResult.get().iterateAll(); // also test paging + counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertEquals(recordSets.get(counter).type(), recordSet.type()); + assertEquals(recordSets.get(counter).name(), recordSet.name()); + assertTrue(recordSet.records().isEmpty()); + assertNull(recordSet.ttl()); + counter++; + } + assertEquals(2, counter); + // test page size + Page recordSetPage = pageSizeResult.get(); + assertEquals(1, ImmutableList.copyOf(recordSetPage.values().iterator()).size()); + // test name filter + ChangeRequest change = DNS.applyChangeRequest(ZONE1.name(), CHANGE_ADD_ZONE1); + waitForChangeToComplete(ZONE1.name(), change.generatedId()); + batch = DNS.batch(); + result = batch.listRecordSets(ZONE1.name(), + Dns.RecordSetListOption.dnsName(A_RECORD_ZONE1.name())); + batch.submit(); + recordSetIterator = result.get().iterateAll(); + counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertTrue(ImmutableList.of(A_RECORD_ZONE1.type(), AAAA_RECORD_ZONE1.type()) + .contains(recordSet.type())); + counter++; + } + assertEquals(2, counter); + // test type filter + batch = DNS.batch(); + result = batch.listRecordSets(ZONE1.name(), + Dns.RecordSetListOption.dnsName(A_RECORD_ZONE1.name()), + Dns.RecordSetListOption.type(A_RECORD_ZONE1.type())); + batch.submit(); + recordSetIterator = result.get().iterateAll(); + counter = 0; + while (recordSetIterator.hasNext()) { + RecordSet recordSet = recordSetIterator.next(); + assertEquals(A_RECORD_ZONE1, recordSet); + counter++; + } + assertEquals(1, counter); + batch = DNS.batch(); + DnsBatchResult> noNameError = batch.listRecordSets(ZONE1.name(), + Dns.RecordSetListOption.type(A_RECORD_ZONE1.type())); + DnsBatchResult> zeroSizeError = + batch.listRecordSets(ZONE1.name(), Dns.RecordSetListOption.pageSize(0)); + DnsBatchResult> negativeSizeError = + batch.listRecordSets(ZONE1.name(), Dns.RecordSetListOption.pageSize(-1)); + batch.submit(); + // check wrong arguments + try { + // name is not set + noNameError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + try { + zeroSizeError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + try { + negativeSizeError.get(); + fail(); + } catch (DnsException ex) { + // expected + assertEquals(400, ex.code()); + assertFalse(ex.retryable()); + } + waitForChangeToComplete(ZONE1.name(), change.generatedId()); + } finally { + clear(); + } + } + + @Test + public void testBatchCombined() { + // only testing that the combination is possible + // the results are validated in the other test methods + try { + DNS.create(ZONE1); + DnsBatch batch = DNS.batch(); + DnsBatchResult zoneResult = batch.getZone(ZONE_NAME1); + DnsBatchResult changeRequestResult = batch.getChangeRequest(ZONE_NAME1, "0"); + DnsBatchResult> pageResult = batch.listRecordSets(ZONE_NAME1); + DnsBatchResult projectResult = batch.getProject(); + assertFalse(zoneResult.completed()); + try { + zoneResult.get(); + fail("this should be submitted first"); + } catch (IllegalStateException ex) { + // expected + } + batch.submit(); + assertNotNull(zoneResult.get().creationTimeMillis()); + assertEquals(ZONE1.dnsName(), zoneResult.get().dnsName()); + assertEquals(ZONE1.description(), zoneResult.get().description()); + assertFalse(zoneResult.get().nameServers().isEmpty()); + assertNull(zoneResult.get().nameServerSet()); // we did not set it + assertNotNull(zoneResult.get().generatedId()); + assertNotNull(projectResult.get().quota()); + assertEquals(2, Iterables.size(pageResult.get().values())); + assertNotNull(changeRequestResult.get()); + } finally { + DNS.delete(ZONE1.name()); + } + } } diff --git a/gcloud-java-dns/src/test/java/com/google/cloud/dns/testing/LocalDnsHelperTest.java b/gcloud-java-dns/src/test/java/com/google/cloud/dns/testing/LocalDnsHelperTest.java index fce958d3a126..6831485f821e 100644 --- a/gcloud-java-dns/src/test/java/com/google/cloud/dns/testing/LocalDnsHelperTest.java +++ b/gcloud-java-dns/src/test/java/com/google/cloud/dns/testing/LocalDnsHelperTest.java @@ -23,16 +23,22 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import com.google.api.client.googleapis.json.GoogleJsonError; import com.google.api.services.dns.model.Change; +import com.google.api.services.dns.model.ChangesListResponse; import com.google.api.services.dns.model.ManagedZone; +import com.google.api.services.dns.model.ManagedZonesListResponse; import com.google.api.services.dns.model.Project; import com.google.api.services.dns.model.ResourceRecordSet; +import com.google.api.services.dns.model.ResourceRecordSetsListResponse; import com.google.cloud.dns.DnsException; import com.google.cloud.dns.spi.DefaultDnsRpc; import com.google.cloud.dns.spi.DnsRpc; +import com.google.cloud.dns.spi.RpcBatch; import com.google.common.collect.ImmutableCollection; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import org.junit.AfterClass; @@ -72,6 +78,24 @@ public class LocalDnsHelperTest { private static final String REAL_PROJECT_ID = LOCAL_DNS_HELPER.options().projectId(); private Map optionsMap; + private static abstract class FailExpectedCallback implements RpcBatch.Callback { + @Override + public void onSuccess(T t) { + fail(); + } + + public abstract void onFailure(GoogleJsonError e); + } + + private static abstract class SuccessExpectedCallback implements RpcBatch.Callback { + public abstract void onSuccess(T t); + + @Override + public void onFailure(GoogleJsonError e) { + fail(); + } + } + @BeforeClass public static void before() { ZONE1.setName(ZONE_NAME1); @@ -682,7 +706,7 @@ public void testListZones() { } @Test - public void testListDnsRecords() { + public void testListRecordSets() { // no zone exists try { RPC.listRecordSets(ZONE_NAME1, EMPTY_RPC_OPTIONS); @@ -1445,4 +1469,1052 @@ private static ResourceRecordSet copyRrset(ResourceRecordSet set) { copy.setType(set.getType()); return copy; } + + @Test + public void testGetProjectBatch() { + // the projects are automatically created when getProject is called + assertNotNull(LOCAL_DNS_HELPER.getProject(PROJECT_ID1, null)); + assertNotNull(LOCAL_DNS_HELPER.getProject(PROJECT_ID2, null)); + RpcBatch batch = RPC.createBatch(); + batch.addGetProject(new SuccessExpectedCallback() { + @Override + public void onSuccess(Project project) { + assertNotNull(project.getQuota()); + assertEquals(REAL_PROJECT_ID, project.getId()); + } + }, EMPTY_RPC_OPTIONS); + batch.addGetProject(new SuccessExpectedCallback() { + @Override + public void onSuccess(Project project) { + assertNull(project.getId()); + assertNotNull(project.getNumber()); + assertNull(project.getQuota()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "number")); + batch.addGetProject(new SuccessExpectedCallback() { + @Override + public void onSuccess(Project project) { + assertNotNull(project.getId()); + assertNull(project.getNumber()); + assertNull(project.getQuota()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id")); + batch.addGetProject(new SuccessExpectedCallback() { + @Override + public void onSuccess(Project project) { + assertNull(project.getId()); + assertNull(project.getNumber()); + assertNotNull(project.getQuota()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "quota")); + batch.submit(); + } + + @Test + public void testCreateZoneBatch() { + RpcBatch batch = RPC.createBatch(); + batch.addCreateZone(ZONE1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone created) { + // check that default records were created + DnsRpc.ListResult listResult + = RPC.listRecordSets(ZONE1.getName(), EMPTY_RPC_OPTIONS); + ImmutableList defaultTypes = ImmutableList.of("SOA", "NS"); + Iterator iterator = listResult.results().iterator(); + assertTrue(defaultTypes.contains(iterator.next().getType())); + assertTrue(defaultTypes.contains(iterator.next().getType())); + assertFalse(iterator.hasNext()); + assertEquals(created, LOCAL_DNS_HELPER.findZone(REAL_PROJECT_ID, ZONE1.getName()).zone()); + ManagedZone zone = RPC.getZone(ZONE_NAME1, EMPTY_RPC_OPTIONS); + assertEquals(created, zone); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + batch = RPC.createBatch(); + batch.addCreateZone(null, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError googleJsonError) { + assertEquals(400, googleJsonError.getCode()); + assertTrue(googleJsonError.getMessage().contains("entity.managedZone")); + } + }, EMPTY_RPC_OPTIONS); + batch.addCreateZone(ZONE1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + assertEquals(409, ex.getCode()); + assertTrue(ex.getMessage().contains("already exists")); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // field options + resetProjects(); + batch = RPC.createBatch(); + batch.addCreateZone(copyZoneNewName(ZONE1, "z1"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNotNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z2"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNotNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "creationTime")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z3"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNotNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "dnsName")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z4"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNotNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "description")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z5"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNotNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServers")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z6"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNotNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServerSet")); + batch.addCreateZone(copyZoneNewName(ZONE1, "z7"), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNotNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNotNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNotNull(zone.getNameServerSet()); + assertNotNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServerSet,description,id,name")); + batch.submit(); + } + + @Test + public void testGetZoneBatch() { + // non-existent + assertNull(RPC.getZone(ZONE_NAME1, EMPTY_RPC_OPTIONS)); + // existent + final ManagedZone created = RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + ManagedZone zone = RPC.getZone(ZONE_NAME1, EMPTY_RPC_OPTIONS); + assertEquals(created, zone); + assertEquals(ZONE1.getName(), zone.getName()); + // field options + RpcBatch batch = RPC.createBatch(); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertEquals(created.getId(), zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertEquals(created.getCreationTime(), zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "creationTime")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertEquals(created.getDnsName(), zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "dnsName")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertEquals(created.getDescription(), zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "description")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertEquals(created.getNameServers(), zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServers")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertEquals(created.getNameServerSet(), zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServerSet")); + batch.addGetZone(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone zone) { + assertNull(zone.getCreationTime()); + assertEquals(created.getName(), zone.getName()); + assertNull(zone.getDnsName()); + assertEquals(created.getDescription(), zone.getDescription()); + assertNull(zone.getNameServers()); + assertEquals(created.getNameServerSet(), zone.getNameServerSet()); + assertEquals(created.getId(), zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nameServerSet,description,id,name")); + batch.submit(); + } + + @Test + public void testDeleteZoneBatch() { + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + RpcBatch batch = RPC.createBatch(); + batch.addDeleteZone(ZONE1.getName(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Void response) { + assertNull(RPC.getZone(ZONE1.getName(), EMPTY_RPC_OPTIONS)); + } + }); + batch.submit(); + batch = RPC.createBatch(); + assertNull(RPC.getZone(ZONE1.getName(), EMPTY_RPC_OPTIONS)); + // deleting non-existent zone + batch.addDeleteZone(ZONE1.getName(), new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(404, ex.getCode()); + } + }); + batch.submit(); + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + RPC.create(ZONE2, EMPTY_RPC_OPTIONS); + assertNotNull(RPC.getZone(ZONE1.getName(), EMPTY_RPC_OPTIONS)); + assertNotNull(RPC.getZone(ZONE2.getName(), EMPTY_RPC_OPTIONS)); + // delete mutiple + batch = RPC.createBatch(); + batch.addDeleteZone(ZONE2.getName(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Void response) { + assertNull(RPC.getZone(ZONE2.getName(), EMPTY_RPC_OPTIONS)); + } + }); + batch.addDeleteZone(ZONE1.getName(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Void response) { + assertNull(RPC.getZone(ZONE1.getName(), EMPTY_RPC_OPTIONS)); + } + }); + batch.submit(); + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + RPC.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addDeleteZone(ZONE1.getName(), new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("not empty")); + } + }); + batch.submit(); + } + + private static ManagedZone copyZoneNewName(ManagedZone zone, String name) { + ManagedZone copy = new ManagedZone(); + for (String key : zone.keySet()) { + copy.set(key, zone.get(key)); + } + copy.setName(name); + return copy; + } + + @Test + public void testListZonesBatch() { + RpcBatch batch = RPC.createBatch(); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse zones) { + assertEquals(0, zones.getManagedZones().size()); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // some zones exists + + final ManagedZone first = RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + final ManagedZone second = RPC.create(ZONE2, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse zones) { + List results = zones.getManagedZones(); + assertEquals(2, results.size()); + assertTrue(results.contains(first)); + assertTrue(results.contains(second)); + } + }, EMPTY_RPC_OPTIONS); + // error in options + batch.addListZones(new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 0)); + batch.addListZones(new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, -1)); + // ok size + batch.addListZones(new RpcBatch.Callback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + assertEquals(1, response.getManagedZones().size()); + } + + @Override + public void onFailure(GoogleJsonError ex) { + fail(); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 1)); + // dns name problems + batch.addListZones(new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.dnsName")); + } + }, ImmutableMap.of(DnsRpc.Option.DNS_NAME, "aaa")); + // ok name + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + assertEquals(0, response.getManagedZones().size()); + } + }, ImmutableMap.of(DnsRpc.Option.DNS_NAME, "aaaa.")); + // field options + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNotNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(id)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNotNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(creationTime)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNotNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(dnsName)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNotNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(description)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNotNull(zone.getNameServers()); + assertNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(nameServers)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(response.getNextPageToken()); + assertNull(zone.getCreationTime()); + assertNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNotNull(zone.getNameServerSet()); + assertNull(zone.getId()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "managedZones(nameServerSet)")); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + ManagedZone zone = response.getManagedZones().get(0); + assertNull(zone.getCreationTime()); + assertNotNull(zone.getName()); + assertNull(zone.getDnsName()); + assertNotNull(zone.getDescription()); + assertNull(zone.getNameServers()); + assertNotNull(zone.getNameServerSet()); + assertNotNull(zone.getId()); + assertEquals(zone.getName(), response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, + "managedZones(nameServerSet,description,id,name),nextPageToken", + DnsRpc.Option.PAGE_SIZE, 1)); + batch.submit(); + } + + @Test + public void testListRecordSetsBatch() { + // no zone exists + RpcBatch batch = RPC.createBatch(); + batch.addListRecordSets(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(404, ex.getCode()); + assertTrue(ex.getMessage().contains("managedZone")); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // zone exists but has no records + batch = RPC.createBatch(); + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(2, response.getRrsets().size()); // contains default NS and SOA + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // zone has records + RPC.applyChangeRequest(ZONE_NAME1, CHANGE_KEEP, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(3, response.getRrsets().size()); + } + }, EMPTY_RPC_OPTIONS); + batch.addListRecordSets(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 0)); + batch.addListRecordSets(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, -1)); + // ok size + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(2, response.getRrsets().size()); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 2)); + // dns name filter + batch.addListRecordSets(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.name")); + } + }, ImmutableMap.of(DnsRpc.Option.NAME, "aaa")); + // dns name filter + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(0, response.getRrsets().size()); + } + }, ImmutableMap.of(DnsRpc.Option.NAME, "aaa.")); + // filter type but no name + batch.addListRecordSets(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.name")); + } + }, ImmutableMap.of(DnsRpc.Option.DNS_TYPE, "A")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(1, response.getRrsets().size()); + } + }, ImmutableMap.of(DnsRpc.Option.NAME, ZONE1.getDnsName(), DnsRpc.Option.DNS_TYPE, "SOA")); + // field options + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + ResourceRecordSet record = response.getRrsets().get(0); + assertNotNull(record.getName()); + assertNull(record.getRrdatas()); + assertNull(record.getType()); + assertNull(record.getTtl()); + assertNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "rrsets(name)")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + ResourceRecordSet record = response.getRrsets().get(0); + assertNull(record.getName()); + assertNotNull(record.getRrdatas()); + assertNull(record.getType()); + assertNull(record.getTtl()); + assertNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "rrsets(rrdatas)")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + ResourceRecordSet record = response.getRrsets().get(0); + assertNull(record.getName()); + assertNull(record.getRrdatas()); + assertNull(record.getType()); + assertNotNull(record.getTtl()); + assertNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "rrsets(ttl)")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + ResourceRecordSet record = response.getRrsets().get(0); + assertNull(record.getName()); + assertNull(record.getRrdatas()); + assertNotNull(record.getType()); + assertNull(record.getTtl()); + assertNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "rrsets(type)")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + ResourceRecordSet record = response.getRrsets().get(0); + assertNull(record.getName()); + assertNull(record.getRrdatas()); + assertNull(record.getType()); + assertNull(record.getTtl()); + assertNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nextPageToken")); + batch.addListRecordSets(ZONE_NAME1, + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(1, response.getRrsets().size()); + ResourceRecordSet record = response.getRrsets().get(0); + assertNotNull(record.getName()); + assertNotNull(record.getRrdatas()); + assertNull(record.getType()); + assertNull(record.getTtl()); + assertNotNull(response.getNextPageToken()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "nextPageToken,rrsets(name,rrdatas)", + DnsRpc.Option.PAGE_SIZE, 1)); + batch.submit(); + } + + @Test + public void testCreateChangeBatch() { + // non-existent zone + RpcBatch batch = RPC.createBatch(); + batch.addApplyChangeRequest(ZONE_NAME1, CHANGE1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(404, ex.getCode()); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // existent zone + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + assertNull(RPC.getChangeRequest(ZONE_NAME1, "1", EMPTY_RPC_OPTIONS)); + batch = RPC.createBatch(); + batch.addApplyChangeRequest(ZONE_NAME1, CHANGE1, new SuccessExpectedCallback() { + @Override + public void onSuccess(Change response) { + assertEquals(RPC.getChangeRequest(ZONE_NAME1, "1", EMPTY_RPC_OPTIONS), response); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // field options + RPC.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addApplyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, + new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNotNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "additions")); + batch.addApplyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, + new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNotNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "deletions")); + batch.addApplyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, + new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNotNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id")); + batch.addApplyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, + new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNotNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "startTime")); + batch.addApplyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, + new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNotNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "status")); + batch.submit(); + } + + @Test + public void testGetChangeBatch() { + // existent + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + final Change created = RPC.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS); + RpcBatch batch = RPC.createBatch(); + batch.addGetChangeRequest(ZONE1.getName(), "1", new SuccessExpectedCallback() { + @Override + public void onSuccess(Change retrieved) { + assertEquals(created, retrieved); + } + }, EMPTY_RPC_OPTIONS); + // non-existent + batch.addGetChangeRequest(ZONE1.getName(), "2", new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError googleJsonError) { + // expected + assertEquals(404, googleJsonError.getCode()); + } + }, EMPTY_RPC_OPTIONS); + // non-existent zone + batch.addGetChangeRequest(ZONE_NAME2, "1", new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(404, ex.getCode()); + assertTrue(ex.getMessage().contains("managedZone")); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // field options + RPC.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS); + Change keep = RPC.applyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addGetChangeRequest(ZONE1.getName(), keep.getId(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNotNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "additions")); + batch.addGetChangeRequest(ZONE1.getName(), keep.getId(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNotNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "deletions")); + batch.addGetChangeRequest(ZONE1.getName(), keep.getId(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNotNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id")); + batch.addGetChangeRequest(ZONE1.getName(), keep.getId(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNotNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "startTime")); + batch.addGetChangeRequest(ZONE1.getName(), keep.getId(), new SuccessExpectedCallback() { + @Override + public void onSuccess(Change complex) { + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNotNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "status")); + batch.submit(); + } + + @Test + public void testListChangesBatch() { + RpcBatch batch = RPC.createBatch(); + batch.addListChangeRequests(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(404, ex.getCode()); + assertTrue(ex.getMessage().contains("managedZone")); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + + // zone exists but has no changes bu the default + batch = RPC.createBatch(); + RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + batch.addListChangeRequests(ZONE_NAME1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + assertEquals(1, response.getChanges().size()); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + // zone has changes + RPC.applyChangeRequest(ZONE1.getName(), CHANGE1, EMPTY_RPC_OPTIONS); + RPC.applyChangeRequest(ZONE1.getName(), CHANGE2, EMPTY_RPC_OPTIONS); + RPC.applyChangeRequest(ZONE1.getName(), CHANGE_KEEP, EMPTY_RPC_OPTIONS); + batch = RPC.createBatch(); + batch.addListChangeRequests(ZONE_NAME1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + assertEquals(4, response.getChanges().size()); + } + }, EMPTY_RPC_OPTIONS); + // error in options + batch.addListChangeRequests(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 0)); + batch.addListChangeRequests(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.maxResults")); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, -1)); + // ok size + batch.addListChangeRequests(ZONE_NAME1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + assertEquals(2, response.getChanges().size()); + } + }, ImmutableMap.of(DnsRpc.Option.PAGE_SIZE, 2)); + final Iterable descending = RPC.listChangeRequests(ZONE1.getName(), + ImmutableMap.of(DnsRpc.Option.SORTING_ORDER, "descending")).results(); + batch.addListChangeRequests(ZONE_NAME1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + List changes = response.getChanges(); + for (int i = 0; i < 4; i++) { + assertEquals(Iterables.get(descending, i), changes.get(i)); + } + } + }, ImmutableMap.of(DnsRpc.Option.SORTING_ORDER, "descending")); + batch.addListChangeRequests(ZONE_NAME1, new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + List changes = response.getChanges(); + for (int i = 0; i < 4; i++) { + assertEquals(Iterables.get(descending, i), changes.get(3 - i)); + } + } + }, ImmutableMap.of(DnsRpc.Option.SORTING_ORDER, "ascending")); + batch.addListChangeRequests(ZONE_NAME1, new FailExpectedCallback() { + @Override + public void onFailure(GoogleJsonError ex) { + // expected + assertEquals(400, ex.getCode()); + assertTrue(ex.getMessage().contains("parameters.sortOrder")); + } + }, ImmutableMap.of(DnsRpc.Option.SORTING_ORDER, "something else")); + batch.submit(); + // field options + batch = RPC.createBatch(); + RPC.applyChangeRequest(ZONE1.getName(), CHANGE_COMPLEX, EMPTY_RPC_OPTIONS); + batch.addListChangeRequests(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + Change complex = response.getChanges().get(0); + assertNotNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "additions", + DnsRpc.Option.SORTING_ORDER, "descending")); + batch.addListChangeRequests(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + Change complex = response.getChanges().get(0); + assertNull(complex.getAdditions()); + assertNotNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "deletions", + DnsRpc.Option.SORTING_ORDER, "descending")); + batch.addListChangeRequests(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + Change complex = response.getChanges().get(0); + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNotNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "id", + DnsRpc.Option.SORTING_ORDER, "descending")); + batch.addListChangeRequests(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + Change complex = response.getChanges().get(0); + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNotNull(complex.getStartTime()); + assertNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "startTime", + DnsRpc.Option.SORTING_ORDER, "descending")); + batch.addListChangeRequests(ZONE1.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + Change complex = response.getChanges().get(0); + assertNull(complex.getAdditions()); + assertNull(complex.getDeletions()); + assertNull(complex.getId()); + assertNull(complex.getStartTime()); + assertNotNull(complex.getStatus()); + } + }, ImmutableMap.of(DnsRpc.Option.FIELDS, "status", + DnsRpc.Option.SORTING_ORDER, "descending")); + batch.submit(); + } + + @Test + public void testCombined() { + final ManagedZone created = RPC.create(ZONE1, EMPTY_RPC_OPTIONS); + RpcBatch batch = RPC.createBatch(); + batch.addListZones(new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZonesListResponse response) { + assertEquals(1, response.getManagedZones().size()); + assertEquals(created, response.getManagedZones().get(0)); + } + }, EMPTY_RPC_OPTIONS); + batch.addGetZone(created.getName(), new SuccessExpectedCallback() { + @Override + public void onSuccess(ManagedZone response) { + assertEquals(created, response); + } + }, EMPTY_RPC_OPTIONS); + batch.addListChangeRequests(created.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ChangesListResponse response) { + assertEquals(1, response.getChanges().size()); + assertEquals(RPC.getChangeRequest(created.getName(), "0", EMPTY_RPC_OPTIONS), + response.getChanges().get(0)); + } + }, EMPTY_RPC_OPTIONS); + batch.addListRecordSets(created.getName(), + new SuccessExpectedCallback() { + @Override + public void onSuccess(ResourceRecordSetsListResponse response) { + assertEquals(2, response.getRrsets().size()); + } + }, EMPTY_RPC_OPTIONS); + batch.addGetChangeRequest(created.getName(), "0", new SuccessExpectedCallback() { + @Override + public void onSuccess(Change response) { + assertEquals(RPC.getChangeRequest(created.getName(), "0", EMPTY_RPC_OPTIONS), response); + } + }, EMPTY_RPC_OPTIONS); + batch.submit(); + } }