diff --git a/src/main/java/io/vinyldns/java/VinylDNSClient.java b/src/main/java/io/vinyldns/java/VinylDNSClient.java
index 6f8ab16..a20c3cf 100644
--- a/src/main/java/io/vinyldns/java/VinylDNSClient.java
+++ b/src/main/java/io/vinyldns/java/VinylDNSClient.java
@@ -1,25 +1,30 @@
-/**
+/*
* Copyright 2018 Comcast Cable Communications Management, LLC
*
- *
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
+ * 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
+ * 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
+ * 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 io.vinyldns.java;
+import io.vinyldns.java.model.acl.*;
import io.vinyldns.java.model.batch.*;
+import io.vinyldns.java.model.health.*;
import io.vinyldns.java.model.membership.*;
import io.vinyldns.java.model.record.set.*;
import io.vinyldns.java.model.zone.*;
import io.vinyldns.java.responses.VinylDNSFailureResponse;
import io.vinyldns.java.responses.VinylDNSResponse;
import io.vinyldns.java.responses.VinylDNSSuccessResponse;
+import java.util.List;
public interface VinylDNSClient {
// Zone
@@ -364,11 +369,247 @@ VinylDNSResponse listRecordSetChanges(
* minimum of two alpha-numeric characters is required.
*
* @param request See {@link SearchRecordSetsRequest SearchRecordSetsRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<SearchRecordSetsResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<SearchRecordSetsResponse>} in case of failure
+ */
+ VinylDNSResponse searchRecordSets(SearchRecordSetsRequest request);
+
+ /**
+ * Retrieves a user by ID.
+ *
+ * @param request See {@link GetUserRequest GetUserRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetUserResponse>} in case
+ * of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetUserResponse>} in case of failure
+ */
+ VinylDNSResponse getUser(GetUserRequest request);
+
+ /**
+ * Locks a user account (admin only).
+ *
+ * @param request See {@link LockUserRequest LockUserRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<LockUnlockUserResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<LockUnlockUserResponse>} in case of failure
+ */
+ VinylDNSResponse lockUser(LockUserRequest request);
+
+ /**
+ * Unlocks a user account (admin only).
+ *
+ * @param request See {@link UnlockUserRequest UnlockUserRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<LockUnlockUserResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<LockUnlockUserResponse>} in case of failure
+ */
+ VinylDNSResponse unlockUser(UnlockUserRequest request);
+
+ /**
+ * Retrieves details of a specific group change.
+ *
+ * @param request See {@link GetGroupChangeRequest GetGroupChangeRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetGroupChangeResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetGroupChangeResponse>} in case of failure
+ */
+ VinylDNSResponse getGroupChange(GetGroupChangeRequest request);
+
+ /**
+ * Retrieves the list of valid email domains for groups.
+ *
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<ListValidDomainsResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<ListValidDomainsResponse>} in case of failure
+ */
+ VinylDNSResponse> listValidDomains();
+
+ /**
+ * Retrieves record set count for a zone.
+ *
+ * @param request See {@link GetRecordSetCountRequest GetRecordSetCountRequest Model}
+ * @return {@link VinylDNSSuccessResponse
+ * VinylDNSSuccessResponse<GetRecordSetCountResponse>} in case of success and {@link
+ * VinylDNSFailureResponse VinylDNSFailureResponse<GetRecordSetCountResponse>} in case
+ * of failure
+ */
+ VinylDNSResponse getRecordSetCount(GetRecordSetCountRequest request);
+
+ /**
+ * Retrieves record set change history for a given FQDN/type.
+ *
+ * @param request See {@link GetRecordSetChangeHistoryRequest}
+ * @return {@code VinylDNSSuccessResponse} in case of success
+ * and {@code VinylDNSFailureResponse} in case of failure
+ */
+ VinylDNSResponse getRecordSetChangeHistory(
+ GetRecordSetChangeHistoryRequest request);
+
+ /**
+ * Retrieves failed record set changes count for a zone.
+ *
+ * @param request See {@link GetFailedRecordSetChangesRequest GetFailedRecordSetChangesRequest
+ * Model}
+ * @return {@link VinylDNSSuccessResponse
+ * VinylDNSSuccessResponse<GetFailedRecordSetChangesResponse>} in case of success and
+ * {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetFailedRecordSetChangesResponse>} in case of failure
+ */
+ VinylDNSResponse getFailedRecordSetChanges(
+ GetFailedRecordSetChangesRequest request);
+
+ /**
+ * Retrieves detailed zone info along with the effective access level for the current principal.
+ *
+ * @param request See {@link GetZoneDetailsRequest GetZoneDetailsRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetZoneDetailsResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetZoneDetailsResponse>} in case of failure
+ */
+ VinylDNSResponse getZoneDetails(GetZoneDetailsRequest request);
+
+ /**
+ * Lists available DNS backend IDs that can be used for zones.
+ *
+ * @return {@link VinylDNSSuccessResponse
+ * VinylDNSSuccessResponse<GetZonesBackendIdsResponse>} in case of success and {@link
+ * VinylDNSFailureResponse VinylDNSFailureResponse<GetZonesBackendIdsResponse>} in case
+ * of failure
+ */
+ VinylDNSResponse> getZonesBackendIds();
+
+ /**
+ * Retrieves the failed zone changes count (global health metric).
+ *
+ * @param request See {@link GetFailedZoneChangesRequest GetFailedZoneChangesRequest Model}
+ * @return {@link VinylDNSSuccessResponse
+ * VinylDNSSuccessResponse<GetFailedZoneChangesResponse>} in case of success and {@link
+ * VinylDNSFailureResponse VinylDNSFailureResponse<GetFailedZoneChangesResponse>} in
+ * case of failure
+ */
+ VinylDNSResponse getFailedZoneChanges(
+ GetFailedZoneChangesRequest request);
+
+ /**
+ * Adds an ACL rule to a zone.
+ *
+ * @param request See {@link AddZoneAclRuleRequest AddZoneAclRuleRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<AddZoneAclRuleResponse>}
+ * in case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<AddZoneAclRuleResponse>} in case of failure
+ */
+ VinylDNSResponse addZoneAclRule(AddZoneAclRuleRequest request);
+
+ /**
+ * Deletes an ACL rule from a zone.
+ *
+ * @param request See {@link DeleteZoneAclRuleRequest DeleteZoneAclRuleRequest Model}
* @return {@link VinylDNSSuccessResponse
- * VinylDNSSuccessResponse<SearchRecordSetsResponse>} in case of success and {@link
- * VinylDNSFailureResponse VinylDNSFailureResponse<SearchRecordSetsResponse>} in case
+ * VinylDNSSuccessResponse<DeleteZoneAclRuleResponse>} in case of success and {@link
+ * VinylDNSFailureResponse VinylDNSFailureResponse<DeleteZoneAclRuleResponse>} in case
* of failure
*/
- VinylDNSResponse searchRecordSets(
- SearchRecordSetsRequest request);
+ VinylDNSResponse deleteZoneAclRule(DeleteZoneAclRuleRequest request);
+ // VinylDNSResponse deleteZoneAclRule(String zoneId, ACLRule rule);
+
+ /**
+ * Simple health check.
+ *
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetPingResponse>} in case
+ * of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetPingResponse>} in case of failure
+ */
+ VinylDNSResponse getPing();
+
+ /**
+ * Comprehensive health check including subsystem statuses.
+ *
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetHealthResponse>} in
+ * case of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetHealthResponse>} in case of failure
+ */
+ VinylDNSResponse getHealth();
+
+ /**
+ * Returns current deployment color (blue/green).
+ *
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<GetColorResponse>} in case
+ * of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<GetColorResponse>} in case of failure
+ */
+ VinylDNSResponse getColor();
+
+ /**
+ * Prometheus metrics in text/plain exposition format.
+ *
+ * @return {@link VinylDNSSuccessResponse
+ * VinylDNSSuccessResponse<GetPrometheusMetricsResponse>} in case of success and {@link
+ * VinylDNSFailureResponse VinylDNSFailureResponse<GetPrometheusMetricsResponse>} in
+ * case of failure
+ */
+ VinylDNSResponse getPrometheusMetrics();
+
+ /**
+ * Retrieves system processing status (enabled/disabled).
+ *
+ * @param request See {@link GetStatusRequest GetStatusRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<StatusResponse>} in case
+ * of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<StatusResponse>} in case of failure
+ */
+ VinylDNSResponse getStatus(GetStatusRequest request);
+
+ /**
+ * Updates system processing status (admin: enable/disable).
+ *
+ * @param request See {@link UpdateStatusRequest UpdateStatusRequest Model}
+ * @return {@link VinylDNSSuccessResponse VinylDNSSuccessResponse<StatusResponse>} in case
+ * of success and {@link VinylDNSFailureResponse
+ * VinylDNSFailureResponse<StatusResponse>} in case of failure
+ */
+ VinylDNSResponse updateStatus(UpdateStatusRequest request);
+
+ /**
+ * Requests ownership transfer for a record seFt.
+ *
+ * @param request See {@link RecordSetOwnershipTransferRequest RecordSetOwnershipTransferRequest}
+ * @return {@link VinylDNSResponse VinylDNSSuccessResponse<RecordSetUpdateResponse>} in case
+ * of success and {@link VinylDNSResponse
+ * VinylDNSFailureResponse<RecordSetUpdateResponse>} in case of failure
+ */
+ VinylDNSResponse requestTransfer(
+ RecordSetOwnershipTransferRequest request);
+
+ /**
+ * Approves a pending ownership transfer request.
+ *
+ * @param request See {@link RecordSetOwnershipTransferRequest RecordSetOwnershipTransferRequest}
+ * @return {@link VinylDNSResponse VinylDNSSuccessResponse<RecordSetUpdateResponse>} in case
+ * of success and {@link VinylDNSResponse
+ * VinylDNSFailureResponse<RecordSetUpdateResponse>} in case of failure
+ */
+ VinylDNSResponse approveTransfer(
+ RecordSetOwnershipTransferRequest request);
+
+ /**
+ * Rejects a pending ownership transfer request.
+ *
+ * @param request See {@link RecordSetOwnershipTransferRequest RecordSetOwnershipTransferRequest}
+ * @return {@link VinylDNSResponse VinylDNSSuccessResponse<RecordSetUpdateResponse>} in case
+ * of success and {@link VinylDNSResponse
+ * VinylDNSFailureResponse<RecordSetUpdateResponse>} in case of failure
+ */
+ VinylDNSResponse rejectTransfer(
+ RecordSetOwnershipTransferRequest request);
+
+ /**
+ * Cancels a pending ownership transfer request.
+ *
+ * @param request See {@link RecordSetOwnershipTransferRequest RecordSetOwnershipTransferRequest}
+ * @return {@link VinylDNSResponse VinylDNSSuccessResponse<RecordSetUpdateResponse>} in case
+ * of success and {@link VinylDNSResponse
+ * VinylDNSFailureResponse<RecordSetUpdateResponse>} in case of failure
+ */
+ VinylDNSResponse cancelTransfer(
+ RecordSetOwnershipTransferRequest request);
}
diff --git a/src/main/java/io/vinyldns/java/VinylDNSClientImpl.java b/src/main/java/io/vinyldns/java/VinylDNSClientImpl.java
index db1d648..a47e3b2 100644
--- a/src/main/java/io/vinyldns/java/VinylDNSClientImpl.java
+++ b/src/main/java/io/vinyldns/java/VinylDNSClientImpl.java
@@ -1,14 +1,16 @@
-/**
+/*
* Copyright 2018 Comcast Cable Communications Management, LLC
*
- * 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
+ * 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
+ * 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
+ * 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 io.vinyldns.java;
@@ -21,11 +23,14 @@
import com.amazonaws.auth.BasicAWSCredentials;
import com.amazonaws.auth.SignerFactory;
import com.amazonaws.http.AmazonHttpClient;
+import com.amazonaws.http.HttpMethodName;
import com.google.gson.Gson;
import io.vinyldns.java.handlers.ErrorResponseHandler;
import io.vinyldns.java.handlers.StringResponseHandler;
import io.vinyldns.java.model.Methods;
+import io.vinyldns.java.model.acl.*;
import io.vinyldns.java.model.batch.*;
+import io.vinyldns.java.model.health.*;
import io.vinyldns.java.model.membership.*;
import io.vinyldns.java.model.record.set.*;
import io.vinyldns.java.model.zone.*;
@@ -34,13 +39,45 @@
import io.vinyldns.java.responses.VinylDNSSuccessResponse;
import io.vinyldns.java.serializers.SerializationFactory;
import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.lang.reflect.Type;
+import java.net.URI;
+import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.util.*;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
public class VinylDNSClientImpl implements VinylDNSClient {
private VinylDNSClientConfig config;
private AmazonHttpClient client;
+ private static final class HttpDeleteWithBody extends HttpEntityEnclosingRequestBase {
+ public static final String METHOD_NAME = "DELETE";
+
+ @Override
+ public String getMethod() {
+ return METHOD_NAME;
+ }
+
+ public HttpDeleteWithBody(final String uri) {
+ setURI(URI.create(uri));
+ }
+
+ public HttpDeleteWithBody(final URI uri) {
+ setURI(uri);
+ }
+
+ public HttpDeleteWithBody() {}
+ }
+
Gson gson = SerializationFactory.createGson();
public VinylDNSClientImpl(VinylDNSClientConfig config) {
@@ -410,11 +447,11 @@ public VinylDNSResponse cancelBatchChanges(String id) {
@Override
public VinylDNSResponse searchRecordSets(
- SearchRecordSetsRequest request) {
+ SearchRecordSetsRequest request) {
String path = "recordsets";
VinylDNSRequest vinylDNSRequest =
- new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
if (request.getStartFrom() != null) {
vinylDNSRequest.addParameter("startFrom", request.getStartFrom());
@@ -429,18 +466,270 @@ public VinylDNSResponse searchRecordSets(
}
if (request.getNameSort() != null) {
- vinylDNSRequest.addParameter( "nameSort", request.getNameSort().name());
+ vinylDNSRequest.addParameter("nameSort", request.getNameSort().name());
}
if (request.getRecordOwnerGroupFilter() != null) {
- vinylDNSRequest.addParameter( "recordOwnerGroupFilter",
- request.getRecordOwnerGroupFilter());
+ vinylDNSRequest.addParameter("recordOwnerGroupFilter", request.getRecordOwnerGroupFilter());
}
return executeRequest(vinylDNSRequest, SearchRecordSetsResponse.class);
}
- private VinylDNSResponse executeRequest(VinylDNSRequest req, Class responseType) {
+ @Override
+ public VinylDNSResponse getUser(GetUserRequest request) {
+ String path = "users/" + request.getUserId();
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, GetUserResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse lockUser(LockUserRequest request) {
+ String path = "users/" + request.getUserId() + "/lock";
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.PUT.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, LockUnlockUserResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse unlockUser(UnlockUserRequest request) {
+ String path = "users/" + request.getUserId() + "/unlock";
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.PUT.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, LockUnlockUserResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse getGroupChange(GetGroupChangeRequest request) {
+ String path = "groups/change/" + request.getGroupChangeId();
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, GetGroupChangeResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse> listValidDomains() {
+ String path = "groups/valid/domains";
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ Type listType = new com.google.gson.reflect.TypeToken>() {}.getType();
+ return executeRequest(vinylDNSRequest, listType);
+ }
+
+ @Override
+ public VinylDNSResponse getRecordSetCount(
+ GetRecordSetCountRequest request) {
+ String path = "zones/" + request.getZoneId() + "/recordsetcount";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ return executeRequest(vinylDNSRequest, GetRecordSetCountResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse getRecordSetChangeHistory(
+ GetRecordSetChangeHistoryRequest request) {
+ String path = "recordsetchange/history";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ if (request.getZoneId() != null) {
+ vinylDNSRequest.addParameter("zoneId", request.getZoneId());
+ }
+ if (request.getFqdn() != null) {
+ vinylDNSRequest.addParameter("fqdn", request.getFqdn());
+ }
+ if (request.getRecordType() != null) {
+ vinylDNSRequest.addParameter("recordType", request.getRecordType());
+ }
+ if (request.getStartFrom() != null) {
+ vinylDNSRequest.addParameter("startFrom", request.getStartFrom());
+ }
+ if (request.getMaxItems() != null) {
+ vinylDNSRequest.addParameter("maxItems", request.getMaxItems().toString());
+ }
+
+ return executeRequest(vinylDNSRequest, GetRecordSetChangeHistoryResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse getFailedRecordSetChanges(
+ GetFailedRecordSetChangesRequest request) {
+ String path = "metrics/health/zones/" + request.getZoneId() + "/recordsetchangesfailure";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ return executeRequest(vinylDNSRequest, GetFailedRecordSetChangesResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse getZoneDetails(GetZoneDetailsRequest request) {
+ String path = "zones/" + request.getZoneId() + "/details";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ return executeRequest(vinylDNSRequest, GetZoneDetailsResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse> getZonesBackendIds() {
+ String path = "zones/backendids";
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ Type listType = new com.google.gson.reflect.TypeToken>() {}.getType();
+ return executeRequest(vinylDNSRequest, listType);
+ }
+
+ @Override
+ public VinylDNSResponse getFailedZoneChanges(
+ GetFailedZoneChangesRequest request) {
+ String path = "metrics/health/zonechangesfailure";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ return executeRequest(vinylDNSRequest, GetFailedZoneChangesResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse addZoneAclRule(AddZoneAclRuleRequest request) {
+ String path = "zones/" + request.getZoneId() + "/acl/rules";
+
+ ACLRule rule = request.getRule();
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.PUT.name(), getBaseUrl(), path, rule);
+ return executeRequest(vinylDNSRequest, AddZoneAclRuleResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse deleteZoneAclRule(
+ DeleteZoneAclRuleRequest request) {
+ String path = "zones/" + request.getZoneId() + "/acl/rules";
+ ACLRule rule = request.getRule();
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.DELETE.name(), getBaseUrl(), path, rule);
+ return executeRequest(vinylDNSRequest, DeleteZoneAclRuleResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse getPing() {
+ String path = "ping";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, String.class);
+ }
+
+ @Override
+ public VinylDNSResponse getHealth() {
+ String path = "health";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, String.class);
+ }
+
+ @Override
+ public VinylDNSResponse getColor() {
+ String path = "color";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, String.class);
+ }
+
+ @Override
+ public VinylDNSResponse getPrometheusMetrics() {
+ String path = "metrics/prometheus";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+
+ return executeRequest(vinylDNSRequest, String.class);
+ }
+
+ @Override
+ public VinylDNSResponse getStatus(GetStatusRequest request) {
+ String path = "status";
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.GET.name(), getBaseUrl(), path, null);
+ return executeRequest(vinylDNSRequest, StatusResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse updateStatus(UpdateStatusRequest requestObj) {
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.POST.name(), getBaseUrl(), "status", requestObj);
+ vinylDNSRequest.addParameter(
+ "processingDisabled", String.valueOf(!requestObj.isProcessingEnabled()));
+ return executeRequest(vinylDNSRequest, StatusResponse.class);
+ }
+
+ @Override
+ public VinylDNSResponse requestTransfer(
+ RecordSetOwnershipTransferRequest requestObj) {
+ RecordSetOwnershipTransferRequest payload =
+ requestObj.withStatus(OwnershipTransferStatus.Requested).withUpdateOwnerGroup(false);
+ return putRecordSet(payload);
+ }
+
+ @Override
+ public VinylDNSResponse approveTransfer(
+ RecordSetOwnershipTransferRequest requestObj) {
+ RecordSetOwnershipTransferRequest payload =
+ requestObj.withStatus(OwnershipTransferStatus.ManuallyApproved).withUpdateOwnerGroup(true);
+ return putRecordSet(payload);
+ }
+
+ @Override
+ public VinylDNSResponse rejectTransfer(
+ RecordSetOwnershipTransferRequest requestObj) {
+ RecordSetOwnershipTransferRequest payload =
+ requestObj.withStatus(OwnershipTransferStatus.ManuallyRejected).withUpdateOwnerGroup(false);
+ return putRecordSet(payload);
+ }
+
+ @Override
+ public VinylDNSResponse cancelTransfer(
+ RecordSetOwnershipTransferRequest requestObj) {
+ RecordSetOwnershipTransferRequest payload =
+ requestObj.withStatus(OwnershipTransferStatus.Cancelled).withUpdateOwnerGroup(false);
+ return putRecordSet(payload);
+ }
+
+ private VinylDNSResponse putRecordSet(
+ RecordSetOwnershipTransferRequest payload) {
+
+ VinylDNSResponse rsResponse =
+ getRecordSet(new GetRecordSetRequest(payload.getZoneId(), payload.getRecordSetId()));
+ if (!(rsResponse instanceof VinylDNSSuccessResponse)) {
+ throw new RuntimeException("Failed to fetch RecordSet before transfer");
+ }
+ RecordSet rs = rsResponse.getValue().getRecordSet();
+ RecordSetTransferPayload body =
+ new RecordSetTransferPayload(
+ rs,
+ payload.getRecordSetGroupChange(),
+ payload.isUpdateOwnerGroup(),
+ payload.getRequestedOwnerGroupId());
+
+ String path =
+ String.format("zones/%s/recordsets/%s", payload.getZoneId(), payload.getRecordSetId());
+
+ VinylDNSRequest vinylDNSRequest =
+ new VinylDNSRequest<>(Methods.PUT.name(), getBaseUrl(), path, body);
+
+ return executeRequest(vinylDNSRequest, RecordSetUpdateResponse.class);
+ }
+
+ private VinylDNSResponse executeRequest(VinylDNSRequest req, Type responseType) {
Request request = new DefaultRequest<>("VinylDNS");
request.setEndpoint(req.getEndpoint());
request.setResourcePath(req.getResourcePath());
@@ -452,12 +741,7 @@ private VinylDNSResponse executeRequest(VinylDNSRequest req, Class<
if (req.getPayload() != null) {
String content = gson.toJson(req.getPayload());
-
- try {
- request.setContent(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
+ request.setContent(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
}
config.getSigner().sign(request, config.getCredentials());
@@ -475,7 +759,126 @@ private VinylDNSResponse executeRequest(VinylDNSRequest req, Class<
if (statusCode / 100 * 100 == 200) {
R responseObject = gson.fromJson(messageBody, responseType);
+ return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ } else {
+ return new VinylDNSFailureResponse<>(messageBody, statusCode);
+ }
+ } catch (AmazonServiceException e) {
+ return new VinylDNSFailureResponse<>(e.getRawResponseContent(), e.getStatusCode());
+ }
+ }
+
+ private VinylDNSResponse executeRequest(VinylDNSRequest req, Class responseType) {
+ Request request = new DefaultRequest<>("VinylDNS");
+ request.setEndpoint(req.getEndpoint());
+ request.setResourcePath(req.getResourcePath());
+ request.setHttpMethod(req.getHttpMethod());
+ request.setHeaders(new HashMap<>(req.getHeaders()));
+ request.setParameters(req.getParameters());
+ request.addHeader("Content-Type", "application/json");
+
+ byte[] payloadBytes = null;
+ if (req.getPayload() != null) {
+ String json = gson.toJson(req.getPayload());
+ payloadBytes = json.getBytes(StandardCharsets.UTF_8);
+ request.setContent(new ByteArrayInputStream(payloadBytes));
+ request.addHeader("x-amz-content-sha256", sha256Hex(payloadBytes));
+ request.addHeader("Content-Type", "application/json");
+ } else {
+ request.addHeader(
+ "x-amz-content-sha256",
+ "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
+ }
+ int port = request.getEndpoint().getPort();
+ String hostHeader =
+ (port == -1 || port == 443 || port == 80)
+ ? request.getEndpoint().getHost()
+ : request.getEndpoint().getHost() + ":" + port;
+ request.addHeader("Host", hostHeader);
+
+ config.getSigner().sign(request, config.getCredentials());
+
+ boolean deleteWithBody =
+ request.getHttpMethod() == HttpMethodName.DELETE && payloadBytes != null;
+
+ if (deleteWithBody) {
+ String base = request.getEndpoint().toString().replaceAll("/$", "");
+ String path = request.getResourcePath();
+ if (path == null) path = "";
+ if (!path.startsWith("/")) path = "/" + path;
+
+ String url = base + path;
+ String qs = buildQueryString(request.getParameters());
+ if (!qs.isEmpty()) url += "?" + qs;
+
+ HttpDeleteWithBody http = new HttpDeleteWithBody(url);
+
+ for (Map.Entry h : request.getHeaders().entrySet()) {
+ String name = h.getKey();
+ if ("Content-Length".equalsIgnoreCase(name) || "Transfer-Encoding".equalsIgnoreCase(name)) {
+ continue;
+ }
+ http.addHeader(name, h.getValue());
+ }
+
+ http.setEntity(new ByteArrayEntity(payloadBytes, ContentType.APPLICATION_JSON));
+
+ try (CloseableHttpClient httpClient =
+ HttpClients.custom().disableContentCompression().build();
+ CloseableHttpResponse resp = httpClient.execute(http)) {
+
+ int statusCode = resp.getStatusLine().getStatusCode();
+ String messageBody =
+ resp.getEntity() != null
+ ? EntityUtils.toString(resp.getEntity(), StandardCharsets.UTF_8)
+ : "";
+
+ if (statusCode >= 200 && statusCode < 300) {
+ if (responseType == String.class) {
+ @SuppressWarnings("unchecked")
+ R responseObject = (R) messageBody;
+ return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ }
+ R responseObject = gson.fromJson(messageBody, responseType);
+ return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ } else {
+ return new VinylDNSFailureResponse<>(messageBody, statusCode);
+ }
+ } catch (IOException e) {
+ StringBuilder sb = new StringBuilder();
+ Throwable cur = e;
+ int depth = 0;
+ while (cur != null && depth < 5) {
+ sb.append(cur.getClass().getName()).append(": ").append(cur.getMessage()).append("\n");
+ cur = cur.getCause();
+ depth++;
+ }
+ for (int i = 0; i < Math.min(6, e.getStackTrace().length); i++) {
+ sb.append(" at ").append(e.getStackTrace()[i].toString()).append("\n");
+ }
+ return new VinylDNSFailureResponse<>(sb.toString(), 599);
+ }
+ }
+
+ try {
+ Response response =
+ client
+ .requestExecutionBuilder()
+ .errorResponseHandler(new ErrorResponseHandler())
+ .request(request)
+ .execute(new StringResponseHandler());
+
+ int statusCode = response.getHttpResponse().getStatusCode();
+ String messageBody = response.getAwsResponse();
+
+ if (statusCode >= 200 && statusCode < 300) {
+ if (responseType == String.class) {
+ @SuppressWarnings("unchecked")
+ R responseObject = (R) messageBody;
+ return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ }
+ R responseObject = gson.fromJson(messageBody, responseType);
return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
} else {
return new VinylDNSFailureResponse<>(messageBody, statusCode);
@@ -485,6 +888,98 @@ private VinylDNSResponse executeRequest(VinylDNSRequest req, Class<
}
}
+ private static String buildQueryString(Map> params) {
+ if (params == null || params.isEmpty()) return "";
+ StringBuilder sb = new StringBuilder();
+ boolean first = true;
+ for (Map.Entry> e : params.entrySet()) {
+ String k = urlEncode(e.getKey());
+ List values = e.getValue();
+ if (values == null || values.isEmpty()) {
+ if (!first) sb.append('&');
+ sb.append(k).append('=');
+ first = false;
+ continue;
+ }
+ for (String v : values) {
+ if (!first) sb.append('&');
+ sb.append(k).append('=').append(urlEncode(v));
+ first = false;
+ }
+ }
+ return sb.toString();
+ }
+
+ private static String urlEncode(String s) {
+ try {
+ return URLEncoder.encode(s, StandardCharsets.UTF_8.name())
+ .replace("+", "%20")
+ .replace("*", "%2A")
+ .replace("%7E", "~");
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String sha256Hex(byte[] bytes) {
+ try {
+ MessageDigest md = MessageDigest.getInstance("SHA-256");
+ byte[] digest = md.digest(bytes);
+ StringBuilder sb = new StringBuilder(digest.length * 2);
+ for (byte b : digest) sb.append(String.format("%02x", b));
+ return sb.toString();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ // private VinylDNSResponse executeRequest(VinylDNSRequest req, Class
+ // responseType) {
+ // Request request = new DefaultRequest<>("VinylDNS");
+ // request.setEndpoint(req.getEndpoint());
+ // request.setResourcePath(req.getResourcePath());
+ // request.setHttpMethod(req.getHttpMethod());
+ // request.setHeaders(req.getHeaders());
+ // request.setParameters(req.getParameters());
+ // request.addHeader("Content-Type", "application/json");
+
+ // if (req.getPayload() != null) {
+ // // String content = gson.toJson(req.getPayload());
+ // // request.setContent(new
+ // ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)));
+ // byte[] payload = gson.toJson(request.getRule()).getBytes(StandardCharsets.UTF_8);
+ // request.setContent(new ByteArrayInputStream(payload));
+ // request.addHeader("Content-Length", String.valueOf(payload.length));
+ // request.addHeader("Content-Type", "application/json");
+
+ // }
+
+ // config.getSigner().sign(request, config.getCredentials());
+ // try {
+ // Response response =
+ // client
+ // .requestExecutionBuilder()
+ // .errorResponseHandler(new ErrorResponseHandler())
+ // .request(request)
+ // .execute(new StringResponseHandler());
+ // int statusCode = response.getHttpResponse().getStatusCode();
+ // String messageBody = response.getAwsResponse();
+ // if (statusCode / 100 * 100 == 200) {
+ // if (responseType == String.class) {
+ // @SuppressWarnings("unchecked")
+ // R responseObject = (R) messageBody;
+ // return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ // }
+ // R responseObject = gson.fromJson(messageBody, responseType);
+ // return new VinylDNSSuccessResponse<>(responseObject, messageBody, statusCode);
+ // } else {
+ // return new VinylDNSFailureResponse<>(messageBody, statusCode);
+ // }
+ // } catch (AmazonServiceException e) {
+ // return new VinylDNSFailureResponse<>(e.getRawResponseContent(), e.getStatusCode());
+ // }
+ // }
+
private String getBaseUrl() {
if (config.getBaseUrl().endsWith("/")) {
return config.getBaseUrl();
diff --git a/src/main/java/io/vinyldns/java/model/acl/ACLRule.java b/src/main/java/io/vinyldns/java/model/acl/ACLRule.java
index 895a5ec..b6399d0 100644
--- a/src/main/java/io/vinyldns/java/model/acl/ACLRule.java
+++ b/src/main/java/io/vinyldns/java/model/acl/ACLRule.java
@@ -1,51 +1,58 @@
-/**
+/*
* Copyright 2018 Comcast Cable Communications Management, LLC
*
- * 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
+ * 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
+ * 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
+ * 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 io.vinyldns.java.model.acl;
import io.vinyldns.java.model.record.RecordType;
+import java.util.Objects;
import java.util.Set;
public class ACLRule {
- private AccessLevel accessLevel;
- private String description; // optional
+ private ZoneAccessLevel accessLevel;
+ private String description;
+ private String displayName;
private String userId; // optional
private String groupId; // optional
- private String recordMask; // optional
+ private String recordMask;
private Set recordTypes;
public ACLRule() {}
public ACLRule(
- AccessLevel accessLevel,
+ ZoneAccessLevel accessLevel,
String description,
+ String displayName,
String userId,
String groupId,
String recordMask,
Set recordTypes) {
this.accessLevel = accessLevel;
this.description = description;
+ this.displayName = displayName;
this.userId = userId;
this.groupId = groupId;
this.recordMask = recordMask;
this.recordTypes = recordTypes;
}
- public AccessLevel getAccessLevel() {
+ public ZoneAccessLevel getAccessLevel() {
return accessLevel;
}
- public void setAccessLevel(AccessLevel accessLevel) {
+ public void setAccessLevel(ZoneAccessLevel accessLevel) {
this.accessLevel = accessLevel;
}
@@ -57,6 +64,14 @@ public void setDescription(String description) {
this.description = description;
}
+ public String getDisplayName() {
+ return displayName;
+ }
+
+ public void setDisplayName(String displayName) {
+ this.displayName = displayName;
+ }
+
public String getUserId() {
return userId;
}
@@ -97,6 +112,9 @@ public String toString() {
+ ", description='"
+ description
+ '\''
+ + ", displayName='"
+ + displayName
+ + '\''
+ ", userId='"
+ userId
+ '\''
@@ -114,29 +132,20 @@ public String toString() {
@Override
public boolean equals(Object o) {
if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
+ if (!(o instanceof ACLRule)) return false;
ACLRule aclRule = (ACLRule) o;
-
- if (accessLevel != aclRule.accessLevel) return false;
- if (description != null
- ? !description.equals(aclRule.description)
- : aclRule.description != null) return false;
- if (userId != null ? !userId.equals(aclRule.userId) : aclRule.userId != null) return false;
- if (groupId != null ? !groupId.equals(aclRule.groupId) : aclRule.groupId != null) return false;
- if (recordMask != null ? !recordMask.equals(aclRule.recordMask) : aclRule.recordMask != null)
- return false;
- return recordTypes.equals(aclRule.recordTypes);
+ return accessLevel == aclRule.accessLevel
+ && Objects.equals(description, aclRule.description)
+ && Objects.equals(displayName, aclRule.displayName)
+ && Objects.equals(userId, aclRule.userId)
+ && Objects.equals(groupId, aclRule.groupId)
+ && Objects.equals(recordMask, aclRule.recordMask)
+ && Objects.equals(recordTypes, aclRule.recordTypes);
}
@Override
public int hashCode() {
- int result = accessLevel.hashCode();
- result = 31 * result + (description != null ? description.hashCode() : 0);
- result = 31 * result + (userId != null ? userId.hashCode() : 0);
- result = 31 * result + (groupId != null ? groupId.hashCode() : 0);
- result = 31 * result + (recordMask != null ? recordMask.hashCode() : 0);
- result = 31 * result + recordTypes.hashCode();
- return result;
+ return Objects.hash(
+ accessLevel, description, displayName, userId, groupId, recordMask, recordTypes);
}
}
diff --git a/src/main/java/io/vinyldns/java/model/acl/ZoneAccessLevel.java b/src/main/java/io/vinyldns/java/model/acl/ZoneAccessLevel.java
new file mode 100644
index 0000000..f16d57f
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/acl/ZoneAccessLevel.java
@@ -0,0 +1,23 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.acl;
+
+public enum ZoneAccessLevel {
+ NoAccess,
+ Read,
+ Write,
+ Delete
+}
diff --git a/src/main/java/io/vinyldns/java/model/health/GetStatusRequest.java b/src/main/java/io/vinyldns/java/model/health/GetStatusRequest.java
new file mode 100644
index 0000000..127033b
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/health/GetStatusRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.health;
+
+import java.util.Objects;
+
+/** Request object for GET /status (no parameters) */
+public class GetStatusRequest {
+ public GetStatusRequest() {}
+
+ @Override
+ public String toString() {
+ return "GetStatusRequest{}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof GetStatusRequest;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash("GetStatusRequest");
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/health/StatusResponse.java b/src/main/java/io/vinyldns/java/model/health/StatusResponse.java
new file mode 100644
index 0000000..7698b7a
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/health/StatusResponse.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.health;
+
+import java.time.Instant;
+import java.util.Objects;
+
+/** Response object for GET /status and POST /status */
+public class StatusResponse {
+ private final boolean processingEnabled;
+ private final Instant lastUpdated;
+ private final String message;
+
+ public StatusResponse(boolean processingEnabled, Instant lastUpdated, String message) {
+ this.processingEnabled = processingEnabled;
+ this.lastUpdated = lastUpdated;
+ this.message = message;
+ }
+
+ public boolean isProcessingEnabled() {
+ return processingEnabled;
+ }
+
+ public Instant getLastUpdated() {
+ return lastUpdated;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return "StatusResponse{"
+ + "processingEnabled="
+ + processingEnabled
+ + ", lastUpdated="
+ + lastUpdated
+ + ", message='"
+ + message
+ + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof StatusResponse)) return false;
+ StatusResponse that = (StatusResponse) o;
+ return processingEnabled == that.processingEnabled
+ && Objects.equals(lastUpdated, that.lastUpdated)
+ && Objects.equals(message, that.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(processingEnabled, lastUpdated, message);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/health/UpdateStatusRequest.java b/src/main/java/io/vinyldns/java/model/health/UpdateStatusRequest.java
new file mode 100644
index 0000000..b0aa841
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/health/UpdateStatusRequest.java
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.health;
+
+import java.util.Objects;
+
+/** Request object for POST /status (enable/disable processing) */
+public class UpdateStatusRequest {
+ private final boolean processingEnabled;
+ private final String message;
+
+ public UpdateStatusRequest(boolean processingEnabled, String message) {
+ this.processingEnabled = processingEnabled;
+ this.message = message;
+ }
+
+ public boolean isProcessingEnabled() {
+ return processingEnabled;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return "UpdateStatusRequest{"
+ + "processingEnabled="
+ + processingEnabled
+ + ", message='"
+ + message
+ + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UpdateStatusRequest)) return false;
+ UpdateStatusRequest that = (UpdateStatusRequest) o;
+ return processingEnabled == that.processingEnabled && Objects.equals(message, that.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(processingEnabled, message);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeRequest.java b/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeRequest.java
new file mode 100644
index 0000000..e828284
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Request object for GET /groups/change/{groupChangeId} */
+public class GetGroupChangeRequest {
+ private final String groupChangeId;
+
+ public GetGroupChangeRequest(String groupChangeId) {
+ this.groupChangeId = groupChangeId;
+ }
+
+ public String getGroupChangeId() {
+ return groupChangeId;
+ }
+
+ @Override
+ public String toString() {
+ return "GetGroupChangeRequest{" + "groupChangeId='" + groupChangeId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetGroupChangeRequest)) return false;
+ GetGroupChangeRequest that = (GetGroupChangeRequest) o;
+ return groupChangeId.equals(that.groupChangeId);
+ }
+
+ @Override
+ public int hashCode() {
+ return groupChangeId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeResponse.java b/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeResponse.java
new file mode 100644
index 0000000..1f4925e
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/GetGroupChangeResponse.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Response object for GET /groups/change/{groupChangeId} */
+public class GetGroupChangeResponse {
+ private final GroupChange groupChange;
+
+ public GetGroupChangeResponse(GroupChange groupChange) {
+ this.groupChange = groupChange;
+ }
+
+ public GroupChange getGroupChange() {
+ return groupChange;
+ }
+
+ @Override
+ public String toString() {
+ return "GetGroupChangeResponse{" + "groupChange=" + groupChange + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetGroupChangeResponse)) return false;
+ GetGroupChangeResponse that = (GetGroupChangeResponse) o;
+ return groupChange.equals(that.groupChange);
+ }
+
+ @Override
+ public int hashCode() {
+ return groupChange.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/GetUserRequest.java b/src/main/java/io/vinyldns/java/model/membership/GetUserRequest.java
new file mode 100644
index 0000000..bf13dff
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/GetUserRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Request object for GET /users/{userId} */
+public class GetUserRequest {
+ private final String userId;
+
+ public GetUserRequest(String userId) {
+ this.userId = userId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ @Override
+ public String toString() {
+ return "GetUserRequest{" + "userId='" + userId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetUserRequest)) return false;
+ GetUserRequest that = (GetUserRequest) o;
+ return userId.equals(that.userId);
+ }
+
+ @Override
+ public int hashCode() {
+ return userId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/GetUserResponse.java b/src/main/java/io/vinyldns/java/model/membership/GetUserResponse.java
new file mode 100644
index 0000000..09b531b
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/GetUserResponse.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Response object for GET /users/{userId} */
+public class GetUserResponse {
+ private final UserInfo user;
+
+ public GetUserResponse(UserInfo user) {
+ this.user = user;
+ }
+
+ public UserInfo getUser() {
+ return user;
+ }
+
+ @Override
+ public String toString() {
+ return "GetUserResponse{" + "user=" + user + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetUserResponse)) return false;
+ GetUserResponse that = (GetUserResponse) o;
+ return user.equals(that.user);
+ }
+
+ @Override
+ public int hashCode() {
+ return user.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/LockUnlockUserResponse.java b/src/main/java/io/vinyldns/java/model/membership/LockUnlockUserResponse.java
new file mode 100644
index 0000000..1a0bef9
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/LockUnlockUserResponse.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Response object for lock/unlock user operations */
+public class LockUnlockUserResponse {
+ private final UserInfo user;
+
+ public LockUnlockUserResponse(UserInfo user) {
+ this.user = user;
+ }
+
+ public UserInfo getUser() {
+ return user;
+ }
+
+ @Override
+ public String toString() {
+ return "LockUnlockUserResponse{" + "user=" + user + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LockUnlockUserResponse)) return false;
+ LockUnlockUserResponse that = (LockUnlockUserResponse) o;
+ return user.equals(that.user);
+ }
+
+ @Override
+ public int hashCode() {
+ return user.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/LockUserRequest.java b/src/main/java/io/vinyldns/java/model/membership/LockUserRequest.java
new file mode 100644
index 0000000..199626c
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/LockUserRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Request object for PUT /users/{userId}/lock */
+public class LockUserRequest {
+ private final String userId;
+
+ public LockUserRequest(String userId) {
+ this.userId = userId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ @Override
+ public String toString() {
+ return "LockUserRequest{" + "userId='" + userId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof LockUserRequest)) return false;
+ LockUserRequest that = (LockUserRequest) o;
+ return userId.equals(that.userId);
+ }
+
+ @Override
+ public int hashCode() {
+ return userId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/membership/UnlockUserRequest.java b/src/main/java/io/vinyldns/java/model/membership/UnlockUserRequest.java
new file mode 100644
index 0000000..0901028
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/membership/UnlockUserRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.membership;
+
+/** Request object for PUT /users/{userId}/unlock */
+public class UnlockUserRequest {
+ private final String userId;
+
+ public UnlockUserRequest(String userId) {
+ this.userId = userId;
+ }
+
+ public String getUserId() {
+ return userId;
+ }
+
+ @Override
+ public String toString() {
+ return "UnlockUserRequest{" + "userId='" + userId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof UnlockUserRequest)) return false;
+ UnlockUserRequest that = (UnlockUserRequest) o;
+ return userId.equals(that.userId);
+ }
+
+ @Override
+ public int hashCode() {
+ return userId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesRequest.java b/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesRequest.java
new file mode 100644
index 0000000..38e5079
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesRequest.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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.
+ */
+
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 License governing permissions and limitations under the License.
+ */
+package io.vinyldns.java.model.record.set;
+
+/** Request object for GET /metrics/health/zones/{zoneId}/recordsetchangesfailure */
+public class GetFailedRecordSetChangesRequest {
+
+ private final String zoneId;
+
+ public GetFailedRecordSetChangesRequest(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ @Override
+ public String toString() {
+ return "GetFailedRecordSetChangesRequest{" + "zoneId='" + zoneId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetFailedRecordSetChangesRequest)) return false;
+ GetFailedRecordSetChangesRequest that = (GetFailedRecordSetChangesRequest) o;
+ return zoneId.equals(that.zoneId);
+ }
+
+ @Override
+ public int hashCode() {
+ return zoneId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesResponse.java b/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesResponse.java
new file mode 100644
index 0000000..9c432d2
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetFailedRecordSetChangesResponse.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+public class GetFailedRecordSetChangesResponse {
+ private final int failureCount;
+
+ public GetFailedRecordSetChangesResponse(int failureCount) {
+ this.failureCount = failureCount;
+ }
+
+ public int getFailureCount() {
+ return failureCount;
+ }
+
+ @Override
+ public String toString() {
+ return "GetFailedRecordSetChangesResponse{" + "failureCount=" + failureCount + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetFailedRecordSetChangesResponse)) return false;
+ GetFailedRecordSetChangesResponse that = (GetFailedRecordSetChangesResponse) o;
+ return failureCount == that.failureCount;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.hashCode(failureCount);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryRequest.java b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryRequest.java
new file mode 100644
index 0000000..acb92d6
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryRequest.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+/**
+ * Request filter for GET /recordsetchange/history.
+ *
+ * Encapsulates query parameters for retrieving record set change history.
+ *
+ * @since 1.0
+ */
+public class GetRecordSetChangeHistoryRequest {
+ private final String zoneId;
+ private final String fqdn;
+ private final String recordType;
+ private final String startFrom; // nullable
+ private final Integer maxItems; // nullable
+
+ /**
+ * Creates a request to query record set change history.
+ *
+ * @param zoneId the zone identifier
+ * @param fqdn the fully qualified domain name
+ * @param recordType the record type (e.g., A, AAAA, CNAME)
+ * @param startFrom an opaque pagination token to start from (nullable)
+ * @param maxItems the maximum number of items to return (nullable)
+ */
+ public GetRecordSetChangeHistoryRequest(
+ String zoneId, String fqdn, String recordType, String startFrom, Integer maxItems) {
+ this.zoneId = zoneId;
+ this.fqdn = fqdn;
+ this.recordType = recordType;
+ this.startFrom = startFrom;
+ this.maxItems = maxItems;
+ }
+
+ /** @return the zone identifier */
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ /** @return the fully qualified domain name */
+ public String getFqdn() {
+ return fqdn;
+ }
+
+ /** @return the record type */
+ public String getRecordType() {
+ return recordType;
+ }
+
+ /** @return the pagination token to start from (nullable) */
+ public String getStartFrom() {
+ return startFrom;
+ }
+
+ /** @return the maximum number of items to return (nullable) */
+ public Integer getMaxItems() {
+ return maxItems;
+ }
+
+ @Override
+ public String toString() {
+ return "GetRecordSetChangeHistoryRequest{"
+ + "zoneId='"
+ + zoneId
+ + '\''
+ + ", fqdn='"
+ + fqdn
+ + '\''
+ + ", recordType='"
+ + recordType
+ + '\''
+ + ", startFrom='"
+ + startFrom
+ + '\''
+ + ", maxItems="
+ + maxItems
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetRecordSetChangeHistoryRequest)) return false;
+ GetRecordSetChangeHistoryRequest that = (GetRecordSetChangeHistoryRequest) o;
+ return zoneId.equals(that.zoneId)
+ && fqdn.equals(that.fqdn)
+ && recordType.equals(that.recordType)
+ && ((startFrom == null && that.startFrom == null)
+ || (startFrom != null && startFrom.equals(that.startFrom)))
+ && ((maxItems == null && that.maxItems == null)
+ || (maxItems != null && maxItems.equals(that.maxItems)));
+ }
+
+ @Override
+ public int hashCode() {
+ int result = zoneId.hashCode();
+ result = 31 * result + fqdn.hashCode();
+ result = 31 * result + recordType.hashCode();
+ result = 31 * result + (startFrom != null ? startFrom.hashCode() : 0);
+ result = 31 * result + (maxItems != null ? maxItems.hashCode() : 0);
+ return result;
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryResponse.java b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryResponse.java
new file mode 100644
index 0000000..4bf1045
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetChangeHistoryResponse.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+import java.util.List;
+
+public class GetRecordSetChangeHistoryResponse {
+ private final List changes;
+
+ public GetRecordSetChangeHistoryResponse(List changes) {
+ this.changes = changes;
+ }
+
+ public List getChanges() {
+ return changes;
+ }
+
+ @Override
+ public String toString() {
+ return "GetRecordSetChangeHistoryResponse{" + "changes=" + changes + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetRecordSetChangeHistoryResponse)) return false;
+ GetRecordSetChangeHistoryResponse that = (GetRecordSetChangeHistoryResponse) o;
+ return changes.equals(that.changes);
+ }
+
+ @Override
+ public int hashCode() {
+ return changes.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountRequest.java b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountRequest.java
new file mode 100644
index 0000000..196bb5b
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountRequest.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+/** Request object for GET /zones/{zoneId}/recordsetcount */
+public class GetRecordSetCountRequest {
+ private final String zoneId;
+
+ public GetRecordSetCountRequest(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ @Override
+ public String toString() {
+ return "GetRecordSetCountRequest{" + "zoneId='" + zoneId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetRecordSetCountRequest)) return false;
+ GetRecordSetCountRequest that = (GetRecordSetCountRequest) o;
+ return zoneId.equals(that.zoneId);
+ }
+
+ @Override
+ public int hashCode() {
+ return zoneId.hashCode();
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountResponse.java b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountResponse.java
new file mode 100644
index 0000000..fd40399
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/GetRecordSetCountResponse.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+/** Response object for GET /zones/{zoneId}/recordsetcount */
+public class GetRecordSetCountResponse {
+ private final int count;
+
+ public GetRecordSetCountResponse(int count) {
+ this.count = count;
+ }
+
+ public int getCount() {
+ return count;
+ }
+
+ @Override
+ public String toString() {
+ return "GetRecordSetCountResponse{" + "count=" + count + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetRecordSetCountResponse)) return false;
+ GetRecordSetCountResponse that = (GetRecordSetCountResponse) o;
+ return count == that.count;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.hashCode(count);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransfer.java b/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransfer.java
new file mode 100644
index 0000000..c854f2e
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransfer.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+import java.util.Objects;
+
+/** Ownership transfer data included in the PUT request body as "recordSetGroupChange". */
+public class OwnershipTransfer {
+ private final OwnershipTransferStatus ownershipTransferStatus;
+ private final String requestedOwnerGroupId;
+
+ public OwnershipTransfer(
+ OwnershipTransferStatus ownershipTransferStatus, String requestedOwnerGroupId) {
+ this.ownershipTransferStatus =
+ Objects.requireNonNull(ownershipTransferStatus, "ownershipTransferStatus");
+ this.requestedOwnerGroupId = requestedOwnerGroupId;
+ }
+
+ public OwnershipTransferStatus getOwnershipTransferStatus() {
+ return ownershipTransferStatus;
+ }
+
+ public String getRequestedOwnerGroupId() {
+ return requestedOwnerGroupId;
+ }
+
+ @Override
+ public String toString() {
+ return "OwnershipTransfer{"
+ + "ownershipTransferStatus="
+ + ownershipTransferStatus
+ + ", requestedOwnerGroupId='"
+ + requestedOwnerGroupId
+ + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof OwnershipTransfer)) return false;
+ OwnershipTransfer that = (OwnershipTransfer) o;
+ return ownershipTransferStatus == that.ownershipTransferStatus
+ && Objects.equals(requestedOwnerGroupId, that.requestedOwnerGroupId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ownershipTransferStatus, requestedOwnerGroupId);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransferStatus.java b/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransferStatus.java
new file mode 100644
index 0000000..788ca09
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/OwnershipTransferStatus.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+public enum OwnershipTransferStatus {
+ AutoApproved,
+ Cancelled,
+ ManuallyApproved,
+ ManuallyRejected,
+ Requested,
+ PendingReview
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/RecordSetOwnershipTransferRequest.java b/src/main/java/io/vinyldns/java/model/record/set/RecordSetOwnershipTransferRequest.java
new file mode 100644
index 0000000..90f8032
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/RecordSetOwnershipTransferRequest.java
@@ -0,0 +1,174 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+import java.util.Objects;
+
+/**
+ * Request object for PUT /zones/{zoneId}/recordsets/{recordSetId} to perform ownership transfer
+ * actions. The body includes ownerGroupId changes (when approving) and recordSetGroupChange
+ * payload.
+ */
+public class RecordSetOwnershipTransferRequest {
+ private final String zoneId;
+ private final String recordSetId;
+ private final String currentOwnerGroupId;
+ private final String requestedOwnerGroupId;
+ private final OwnershipTransferStatus status;
+ private final boolean updateOwnerGroup;
+
+ private final OwnershipTransfer recordSetGroupChange;
+
+ private RecordSetOwnershipTransferRequest(
+ String zoneId,
+ String recordSetId,
+ String currentOwnerGroupId,
+ String requestedOwnerGroupId,
+ OwnershipTransferStatus status,
+ boolean updateOwnerGroup,
+ OwnershipTransfer recordSetGroupChange) {
+ this.zoneId = zoneId;
+ this.recordSetId = recordSetId;
+ this.currentOwnerGroupId = currentOwnerGroupId;
+ this.requestedOwnerGroupId = requestedOwnerGroupId;
+ this.status = status;
+ this.updateOwnerGroup = updateOwnerGroup;
+ this.recordSetGroupChange = recordSetGroupChange;
+ }
+
+ public static RecordSetOwnershipTransferRequest of(
+ String zoneId, String recordSetId, String currentOwnerGroupId, String requestedOwnerGroupId) {
+ Objects.requireNonNull(zoneId, "zoneId is required");
+ Objects.requireNonNull(recordSetId, "recordSetId is required");
+ return new RecordSetOwnershipTransferRequest(
+ zoneId,
+ recordSetId,
+ currentOwnerGroupId,
+ requestedOwnerGroupId,
+ OwnershipTransferStatus.Requested,
+ false,
+ new OwnershipTransfer(OwnershipTransferStatus.Requested, requestedOwnerGroupId));
+ }
+
+ public RecordSetOwnershipTransferRequest withStatus(OwnershipTransferStatus status) {
+ Objects.requireNonNull(status, "status is required");
+ return new RecordSetOwnershipTransferRequest(
+ zoneId,
+ recordSetId,
+ currentOwnerGroupId,
+ requestedOwnerGroupId,
+ status,
+ updateOwnerGroup,
+ new OwnershipTransfer(status, requestedOwnerGroupId));
+ }
+
+ public RecordSetOwnershipTransferRequest withUpdateOwnerGroup(boolean update) {
+ return new RecordSetOwnershipTransferRequest(
+ zoneId,
+ recordSetId,
+ currentOwnerGroupId,
+ requestedOwnerGroupId,
+ status,
+ update,
+ recordSetGroupChange);
+ }
+
+ // --- Getters ---
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ public String getRecordSetId() {
+ return recordSetId;
+ }
+
+ public String getCurrentOwnerGroupId() {
+ return currentOwnerGroupId;
+ }
+
+ public String getRequestedOwnerGroupId() {
+ return requestedOwnerGroupId;
+ }
+
+ public OwnershipTransferStatus getStatus() {
+ return status;
+ }
+
+ public boolean isUpdateOwnerGroup() {
+ return updateOwnerGroup;
+ }
+
+ /**
+ * The API expects the record set body to include { "ownerGroupId": "...", "recordSetGroupChange":
+ * {...} } If updateOwnerGroup is true (approval), the service implementation should set the
+ * ownerGroupId to requestedOwnerGroupId.
+ */
+ public OwnershipTransfer getRecordSetGroupChange() {
+ return recordSetGroupChange;
+ }
+
+ @Override
+ public String toString() {
+ return "RecordSetOwnershipTransferRequest{"
+ + "zoneId='"
+ + zoneId
+ + '\''
+ + ", recordSetId='"
+ + recordSetId
+ + '\''
+ + ", currentOwnerGroupId='"
+ + currentOwnerGroupId
+ + '\''
+ + ", requestedOwnerGroupId='"
+ + requestedOwnerGroupId
+ + '\''
+ + ", status="
+ + status
+ + ", updateOwnerGroup="
+ + updateOwnerGroup
+ + ", recordSetGroupChange="
+ + recordSetGroupChange
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RecordSetOwnershipTransferRequest)) return false;
+ RecordSetOwnershipTransferRequest that = (RecordSetOwnershipTransferRequest) o;
+ return updateOwnerGroup == that.updateOwnerGroup
+ && Objects.equals(zoneId, that.zoneId)
+ && Objects.equals(recordSetId, that.recordSetId)
+ && Objects.equals(currentOwnerGroupId, that.currentOwnerGroupId)
+ && Objects.equals(requestedOwnerGroupId, that.requestedOwnerGroupId)
+ && status == that.status
+ && Objects.equals(recordSetGroupChange, that.recordSetGroupChange);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(
+ zoneId,
+ recordSetId,
+ currentOwnerGroupId,
+ requestedOwnerGroupId,
+ status,
+ updateOwnerGroup,
+ recordSetGroupChange);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/RecordSetTransferPayload.java b/src/main/java/io/vinyldns/java/model/record/set/RecordSetTransferPayload.java
new file mode 100644
index 0000000..0965ba7
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/RecordSetTransferPayload.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+public class RecordSetTransferPayload extends RecordSet {
+
+ private final OwnershipTransfer recordSetGroupChange;
+
+ public RecordSetTransferPayload(
+ RecordSet base,
+ OwnershipTransfer recordSetGroupChange,
+ boolean updateOwnerGroup,
+ String requestedOwnerGroupId) {
+
+ super(
+ base.getZoneId(),
+ base.getName(),
+ base.getType(),
+ base.getTtl(),
+ base.getRecords(),
+ base.getId(),
+ updateOwnerGroup ? requestedOwnerGroupId : base.getOwnerGroupId(),
+ base.getStatus(),
+ base.getCreated(),
+ base.getUpdated());
+
+ this.recordSetGroupChange = recordSetGroupChange;
+ }
+
+ public OwnershipTransfer getRecordSetGroupChange() {
+ return recordSetGroupChange;
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/record/set/RecordSetUpdateResponse.java b/src/main/java/io/vinyldns/java/model/record/set/RecordSetUpdateResponse.java
new file mode 100644
index 0000000..6f34211
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/record/set/RecordSetUpdateResponse.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.record.set;
+
+import java.util.Objects;
+
+/** Response object for PUT /zones/{zoneId}/recordsets/{recordSetId}. */
+public class RecordSetUpdateResponse {
+ private final String recordSetId;
+ private final String zoneId;
+ private final String ownerGroupId;
+ private final OwnershipTransferStatus ownershipTransferStatus;
+ private final String message;
+
+ public RecordSetUpdateResponse(
+ String recordSetId,
+ String zoneId,
+ String ownerGroupId,
+ OwnershipTransferStatus ownershipTransferStatus,
+ String message) {
+ this.recordSetId = recordSetId;
+ this.zoneId = zoneId;
+ this.ownerGroupId = ownerGroupId;
+ this.ownershipTransferStatus = ownershipTransferStatus;
+ this.message = message;
+ }
+
+ public String getRecordSetId() {
+ return recordSetId;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ public String getOwnerGroupId() {
+ return ownerGroupId;
+ }
+
+ public OwnershipTransferStatus getOwnershipTransferStatus() {
+ return ownershipTransferStatus;
+ }
+
+ public String getMessage() {
+ return message;
+ }
+
+ @Override
+ public String toString() {
+ return "RecordSetUpdateResponse{"
+ + "recordSetId='"
+ + recordSetId
+ + '\''
+ + ", zoneId='"
+ + zoneId
+ + '\''
+ + ", ownerGroupId='"
+ + ownerGroupId
+ + '\''
+ + ", ownershipTransferStatus="
+ + ownershipTransferStatus
+ + ", message='"
+ + message
+ + '\''
+ + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof RecordSetUpdateResponse)) return false;
+ RecordSetUpdateResponse that = (RecordSetUpdateResponse) o;
+ return Objects.equals(recordSetId, that.recordSetId)
+ && Objects.equals(zoneId, that.zoneId)
+ && Objects.equals(ownerGroupId, that.ownerGroupId)
+ && ownershipTransferStatus == that.ownershipTransferStatus
+ && Objects.equals(message, that.message);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(recordSetId, zoneId, ownerGroupId, ownershipTransferStatus, message);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleRequest.java b/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleRequest.java
new file mode 100644
index 0000000..341a690
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleRequest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import io.vinyldns.java.model.acl.ACLRule;
+import java.util.Objects;
+
+public class AddZoneAclRuleRequest {
+ private final String zoneId;
+ private final ACLRule rule;
+
+ /**
+ * Constructs a request to add an ACL rule to a zone.
+ *
+ * @param zoneId the target zone identifier
+ * @param rule the ACL rule to add
+ */
+ public AddZoneAclRuleRequest(String zoneId, ACLRule rule) {
+ this.zoneId = zoneId;
+ this.rule = rule;
+ }
+
+ /** Returns the zone identifier. */
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ /** Returns the ACL rule to add. */
+ public ACLRule getRule() {
+ return rule;
+ }
+
+ @Override
+ public String toString() {
+ return "AddZoneAclRuleRequest{" + "zoneId='" + zoneId + '\'' + ", rule=" + rule + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AddZoneAclRuleRequest)) return false;
+ AddZoneAclRuleRequest that = (AddZoneAclRuleRequest) o;
+ return Objects.equals(zoneId, that.zoneId) && Objects.equals(rule, that.rule);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(zoneId, rule);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleResponse.java b/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleResponse.java
new file mode 100644
index 0000000..cba7263
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/AddZoneAclRuleResponse.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import io.vinyldns.java.model.acl.ACLRule;
+import java.util.Objects;
+
+public class AddZoneAclRuleResponse {
+ private final ACLRule rule;
+
+ /**
+ * Constructs the response with the persisted ACL rule.
+ *
+ * @param rule the ACL rule returned by the server
+ */
+ public AddZoneAclRuleResponse(ACLRule rule) {
+ this.rule = rule;
+ }
+
+ /** Returns the persisted ACL rule. */
+ public ACLRule getRule() {
+ return rule;
+ }
+
+ @Override
+ public String toString() {
+ return "AddZoneAclRuleResponse{" + "rule=" + rule + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof AddZoneAclRuleResponse)) return false;
+ AddZoneAclRuleResponse that = (AddZoneAclRuleResponse) o;
+ return Objects.equals(rule, that.rule);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(rule);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleRequest.java b/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleRequest.java
new file mode 100644
index 0000000..4dd3b06
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleRequest.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import io.vinyldns.java.model.acl.ACLRule;
+import java.util.Objects;
+
+public class DeleteZoneAclRuleRequest {
+ private final String zoneId;
+ private final ACLRule rule;
+
+ /**
+ * Constructs a request to delete an ACL rule from a zone.
+ *
+ * @param zoneId the target zone identifier
+ * @param rule the ACL rule to delete (must match the server's stored rule fields)
+ */
+ public DeleteZoneAclRuleRequest(String zoneId, ACLRule rule) {
+ this.zoneId = zoneId;
+ this.rule = rule;
+ }
+
+ /** Returns the zone identifier. */
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ /** Returns the ACL rule to delete. */
+ public ACLRule getRule() {
+ return rule;
+ }
+
+ @Override
+ public String toString() {
+ return "DeleteZoneAclRuleRequest{" + "zoneId='" + zoneId + '\'' + ", rule=" + rule + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DeleteZoneAclRuleRequest)) return false;
+ DeleteZoneAclRuleRequest that = (DeleteZoneAclRuleRequest) o;
+ return Objects.equals(zoneId, that.zoneId) && Objects.equals(rule, that.rule);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(zoneId, rule);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleResponse.java b/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleResponse.java
new file mode 100644
index 0000000..feb94d6
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/DeleteZoneAclRuleResponse.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import io.vinyldns.java.model.acl.ACLRule;
+import java.util.Objects;
+
+public class DeleteZoneAclRuleResponse {
+ private final boolean deleted;
+ private final ACLRule rule;
+
+ /**
+ * Constructs the response.
+ *
+ * @param deleted whether the rule was successfully deleted
+ * @param rule the rule that was deleted (optional; include if server returns it)
+ */
+ public DeleteZoneAclRuleResponse(boolean deleted, ACLRule rule) {
+ this.deleted = deleted;
+ this.rule = rule;
+ }
+
+ /** Returns true if the rule was deleted. */
+ public boolean isDeleted() {
+ return deleted;
+ }
+
+ /** Returns the deleted rule, if the server returns it. May be null. */
+ public ACLRule getRule() {
+ return rule;
+ }
+
+ @Override
+ public String toString() {
+ return "DeleteZoneAclRuleResponse{" + "deleted=" + deleted + ", rule=" + rule + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof DeleteZoneAclRuleResponse)) return false;
+ DeleteZoneAclRuleResponse that = (DeleteZoneAclRuleResponse) o;
+ return deleted == that.deleted && Objects.equals(rule, that.rule);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(deleted, rule);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesRequest.java b/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesRequest.java
new file mode 100644
index 0000000..64e14fa
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesRequest.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import java.util.Objects;
+
+/** Request object for GET /metrics/health/zonechangesfailure (no parameters) */
+public class GetFailedZoneChangesRequest {
+ public GetFailedZoneChangesRequest() {}
+
+ @Override
+ public String toString() {
+ return "GetFailedZoneChangesRequest{}";
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ return o instanceof GetFailedZoneChangesRequest;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash("GetFailedZoneChangesRequest");
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesResponse.java b/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesResponse.java
new file mode 100644
index 0000000..d0888df
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/GetFailedZoneChangesResponse.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+/** Response object for GET /metrics/health/zonechangesfailure */
+public class GetFailedZoneChangesResponse {
+ private final int failureCount;
+
+ public GetFailedZoneChangesResponse(int failureCount) {
+ this.failureCount = failureCount;
+ }
+
+ public int getFailureCount() {
+ return failureCount;
+ }
+
+ @Override
+ public String toString() {
+ return "GetFailedZoneChangesResponse{" + "failureCount=" + failureCount + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetFailedZoneChangesResponse)) return false;
+ GetFailedZoneChangesResponse that = (GetFailedZoneChangesResponse) o;
+ return failureCount == that.failureCount;
+ }
+
+ @Override
+ public int hashCode() {
+ return Integer.hashCode(failureCount);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsRequest.java b/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsRequest.java
new file mode 100644
index 0000000..d1e3a9b
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsRequest.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import java.util.Objects;
+
+/** Request object for GET /zones/{zoneId}/details */
+public class GetZoneDetailsRequest {
+ private final String zoneId;
+
+ public GetZoneDetailsRequest(String zoneId) {
+ this.zoneId = zoneId;
+ }
+
+ public String getZoneId() {
+ return zoneId;
+ }
+
+ @Override
+ public String toString() {
+ return "GetZoneDetailsRequest{" + "zoneId='" + zoneId + '\'' + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetZoneDetailsRequest)) return false;
+ GetZoneDetailsRequest that = (GetZoneDetailsRequest) o;
+ return Objects.equals(zoneId, that.zoneId);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(zoneId);
+ }
+}
diff --git a/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsResponse.java b/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsResponse.java
new file mode 100644
index 0000000..d02a68e
--- /dev/null
+++ b/src/main/java/io/vinyldns/java/model/zone/GetZoneDetailsResponse.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 Comcast Cable Communications Management, LLC
+ *
+ * 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 io.vinyldns.java.model.zone;
+
+import io.vinyldns.java.model.acl.ZoneAccessLevel;
+import java.util.Objects;
+
+/** Response object for GET /zones/{zoneId}/details */
+public class GetZoneDetailsResponse {
+ private final Zone zone;
+ private final ZoneAccessLevel accessLevel;
+
+ public GetZoneDetailsResponse(Zone zone, ZoneAccessLevel accessLevel) {
+ this.zone = zone;
+ this.accessLevel = accessLevel;
+ }
+
+ public Zone getZone() {
+ return zone;
+ }
+
+ public ZoneAccessLevel getAccessLevel() {
+ return accessLevel;
+ }
+
+ @Override
+ public String toString() {
+ return "GetZoneDetailsResponse{" + "zone=" + zone + ", accessLevel=" + accessLevel + '}';
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (!(o instanceof GetZoneDetailsResponse)) return false;
+ GetZoneDetailsResponse that = (GetZoneDetailsResponse) o;
+ return Objects.equals(zone, that.zone) && accessLevel == that.accessLevel;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(zone, accessLevel);
+ }
+}
diff --git a/src/test/java/io/vinyldns/java/VinylDNSClientTest.java b/src/test/java/io/vinyldns/java/VinylDNSClientTest.java
index cb1c0b1..1d9eaaa 100644
--- a/src/test/java/io/vinyldns/java/VinylDNSClientTest.java
+++ b/src/test/java/io/vinyldns/java/VinylDNSClientTest.java
@@ -1,14 +1,16 @@
-/**
+/*
* Copyright 2018 Comcast Cable Communications Management, LLC
*
- * 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
+ * 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
+ * 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
+ * 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 io.vinyldns.java;
@@ -21,11 +23,10 @@
import com.amazonaws.auth.BasicAWSCredentials;
import com.github.tomakehurst.wiremock.WireMockServer;
import com.github.tomakehurst.wiremock.matching.EqualToJsonPattern;
-
import io.vinyldns.java.model.Order;
-import io.vinyldns.java.model.acl.ACLRule;
-import io.vinyldns.java.model.acl.AccessLevel;
+import io.vinyldns.java.model.acl.*;
import io.vinyldns.java.model.batch.*;
+import io.vinyldns.java.model.health.*;
import io.vinyldns.java.model.membership.*;
import io.vinyldns.java.model.record.RecordType;
import io.vinyldns.java.model.record.data.AData;
@@ -1478,26 +1479,25 @@ public void listRecordSetGlobalSuccess() {
int maxItems = 55;
wireMockServer.stubFor(
- get(urlMatching("/recordsets?(.*)"))
- .withQueryParam("recordNameFilter", equalTo(recordNameFilter))
- .withQueryParam("startFrom", equalTo(startFrom))
- .withQueryParam("maxItems", equalTo(String.valueOf(maxItems)))
- .willReturn(
- aResponse()
- .withStatus(200)
- .withHeader("Content-Type", "application/json")
- .withBody(response)));
+ get(urlMatching("/recordsets?(.*)"))
+ .withQueryParam("recordNameFilter", equalTo(recordNameFilter))
+ .withQueryParam("startFrom", equalTo(startFrom))
+ .withQueryParam("maxItems", equalTo(String.valueOf(maxItems)))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(response)));
VinylDNSResponse vinylDNSResponse =
- client.searchRecordSets(
- new SearchRecordSetsRequest(recordNameFilter, null,
- Order.ASC , startFrom, maxItems));
+ client.searchRecordSets(
+ new SearchRecordSetsRequest(recordNameFilter, null, Order.ASC, startFrom, maxItems));
assertTrue(vinylDNSResponse instanceof ResponseMarker.Success);
assertEquals(vinylDNSResponse.getStatusCode(), 200);
- assertEquals(vinylDNSResponse.getValue().getRecordNameFilter(),
- searchRecordSetsResponse.getRecordNameFilter());
-
+ assertEquals(
+ vinylDNSResponse.getValue().getRecordNameFilter(),
+ searchRecordSetsResponse.getRecordNameFilter());
}
@Test
@@ -1507,20 +1507,19 @@ public void listRecordSetGlobalFailure() {
int maxItems = 55;
wireMockServer.stubFor(
- get(urlMatching("/recordsets?(.*)"))
- .withQueryParam("recordNameFilter", equalTo(recordNameFilter))
- .withQueryParam("startFrom", equalTo(startFrom))
- .withQueryParam("maxItems", equalTo(String.valueOf(maxItems)))
- .willReturn(
- aResponse()
- .withStatus(500)
- .withHeader("Content-Type", "application/json")
- .withBody("server error")));
+ get(urlMatching("/recordsets?(.*)"))
+ .withQueryParam("recordNameFilter", equalTo(recordNameFilter))
+ .withQueryParam("startFrom", equalTo(startFrom))
+ .withQueryParam("maxItems", equalTo(String.valueOf(maxItems)))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
VinylDNSResponse vinylDNSResponse =
- client.searchRecordSets(
- new SearchRecordSetsRequest(recordNameFilter, null,
- Order.ASC , startFrom, maxItems));
+ client.searchRecordSets(
+ new SearchRecordSetsRequest(recordNameFilter, null, Order.ASC, startFrom, maxItems));
assertTrue(vinylDNSResponse instanceof ResponseMarker.Failure);
assertEquals(vinylDNSResponse.getStatusCode(), 500);
@@ -1528,82 +1527,1211 @@ public void listRecordSetGlobalFailure() {
assertNull(vinylDNSResponse.getValue());
}
+ @Test
+ public void getUserSuccess() {
+ String userId = "test-user";
+ GetUserRequest request = new GetUserRequest(userId);
- private String rsId = "recordSetId";
- private String zoneId = "zoneId";
- private ZoneConnection testZoneConnection1 =
- new ZoneConnection("name", "keyName", "key", "server");
- private ZoneACL testZoneAcl1 =
- new ZoneACL(
- Collections.singleton(
- new ACLRule(
- AccessLevel.Read,
- "description",
- "userId",
- "groupId",
- "recordMask",
- Collections.singleton(RecordType.A))));
- private Zone testZone1 =
- new Zone(
- "id",
- "name",
- "some@company.com",
- ZoneStatus.Active,
- new DateTime(),
- new DateTime(),
- testZoneConnection1,
- null,
- true,
- testZoneAcl1,
- "group",
- null,
- true,
- "somebackId");
- private List zones = Collections.singletonList(testZone1);
- private ListZonesResponse listZonesResponse =
- new ListZonesResponse(zones, "startFrom", "nextId", 100, "nameFilter");
+ GetUserResponse expected = new GetUserResponse(new UserInfo(userId));
- private String recordSetId = "recordSetId";
- private String recordSetName = "recordSetName";
- private String ownerGroupId = "ownerGroupId";
- private List recordDataList = Collections.singletonList(new AData("192.168.1.1"));
- private RecordSet recordSet =
- new RecordSet(
- zoneId,
- recordSetName,
- RecordType.A,
- 100,
- recordDataList,
- recordSetId,
- ownerGroupId,
- RecordSetStatus.Active,
- new DateTime(),
- new DateTime());
- private RecordSet recordSetNoOwner =
- new RecordSet(
- zoneId,
- recordSetName,
- RecordType.A,
- 100,
- recordDataList,
- recordSetId,
- null,
- RecordSetStatus.Active,
- new DateTime(),
- new DateTime());
- private RecordSet recordSetUpdate =
- new RecordSet(
- zoneId,
- "recordSetNameUpdated",
- RecordType.A,
- 38400,
- recordDataList,
- recordSetId,
- ownerGroupId,
- RecordSetStatus.Active,
- new DateTime(),
- new DateTime());
- private List recordSetList = Collections.singletonList(recordSet);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/users/" + userId))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse actual = client.getUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Success);
+ assertEquals(200, actual.getStatusCode());
+ assertEquals(expected, actual.getValue());
+ }
+
+ @Test
+ public void getUserFailure500() {
+ String userId = "test-user";
+ GetUserRequest request = new GetUserRequest(userId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/users/" + userId))
+ .willReturn(aResponse().withStatus(500).withBody("server error")));
+
+ VinylDNSResponse actual = client.getUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(500, actual.getStatusCode());
+ assertEquals("server error", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void getUserFailure404() {
+ String userId = "test-user";
+ GetUserRequest request = new GetUserRequest(userId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/users/" + userId))
+ .willReturn(aResponse().withStatus(404).withBody("not found")));
+
+ VinylDNSResponse actual = client.getUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(404, actual.getStatusCode());
+ assertEquals("not found", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void lockUserSuccess() {
+ String userId = "u1";
+ LockUserRequest request = new LockUserRequest(userId);
+ UserInfo userInfo = new UserInfo(userId);
+ LockUnlockUserResponse expected = new LockUnlockUserResponse(userInfo);
+
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/lock"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse actual = client.lockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Success);
+ assertEquals(200, actual.getStatusCode());
+ assertEquals(expected, actual.getValue());
+ }
+
+ @Test
+ public void lockUserFailure500() {
+ String userId = "u1";
+ LockUserRequest request = new LockUserRequest(userId);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/lock"))
+ .willReturn(aResponse().withStatus(500).withBody("server error")));
+
+ VinylDNSResponse actual = client.lockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(500, actual.getStatusCode());
+ assertEquals("server error", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void lockUserFailure404() {
+ String userId = "u1";
+ LockUserRequest request = new LockUserRequest(userId);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/lock"))
+ .willReturn(aResponse().withStatus(404).withBody("not found")));
+
+ VinylDNSResponse actual = client.lockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(404, actual.getStatusCode());
+ assertEquals("not found", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void unlockUserSuccess() {
+ String userId = "u1";
+ UnlockUserRequest request = new UnlockUserRequest(userId);
+ UserInfo userInfo = new UserInfo(userId);
+ LockUnlockUserResponse expected = new LockUnlockUserResponse(userInfo);
+
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/unlock"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse actual = client.unlockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Success);
+ assertEquals(200, actual.getStatusCode());
+ assertEquals(expected, actual.getValue());
+ }
+
+ @Test
+ public void unlockUserFailure500() {
+ String userId = "u1";
+ UnlockUserRequest request = new UnlockUserRequest(userId);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/unlock"))
+ .willReturn(aResponse().withStatus(500).withBody("server error")));
+
+ VinylDNSResponse actual = client.unlockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(500, actual.getStatusCode());
+ assertEquals("server error", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void unlockUserFailure404() {
+ String userId = "u1";
+ UnlockUserRequest request = new UnlockUserRequest(userId);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/users/" + userId + "/unlock"))
+ .willReturn(aResponse().withStatus(404).withBody("not found")));
+
+ VinylDNSResponse actual = client.unlockUser(request);
+
+ assertTrue(actual instanceof ResponseMarker.Failure);
+ assertEquals(404, actual.getStatusCode());
+ assertEquals("not found", actual.getMessageBody());
+ assertNull(actual.getValue());
+ }
+
+ @Test
+ public void getGroupChangeSuccess() {
+ String groupChangeId = groupChanges.iterator().next().getId();
+ GetGroupChangeRequest request = new GetGroupChangeRequest(groupChangeId);
+ GroupChange change =
+ new GroupChange(groupChangeId, newGroup, group, "", "", GroupChangeType.Update);
+
+ GetGroupChangeResponse expected = new GetGroupChangeResponse(change);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/groups/change/" + groupChangeId))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.getGroupChange(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(client.gson.toJson(expected), client.gson.toJson(resp.getValue()));
+ }
+
+ @Test
+ public void getGroupChangeFailure() {
+ String groupChangeId = groupChanges.iterator().next().getId();
+ GetGroupChangeRequest request = new GetGroupChangeRequest(groupChangeId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/groups/change/" + groupChangeId))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getGroupChange(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void listValidDomainsSuccess() {
+ List expected = Arrays.asList("example.com", "test.com");
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/groups/valid/domains"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse> resp = client.listValidDomains();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void listValidDomainsFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/groups/valid/domains"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse> resp = client.listValidDomains();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getRecordSetCountSuccess() {
+ GetRecordSetCountRequest request = new GetRecordSetCountRequest(zoneId);
+ int expectedCount = recordSetList.size();
+ GetRecordSetCountResponse expected = new GetRecordSetCountResponse(expectedCount);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/" + zoneId + "/recordsetcount"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.getRecordSetCount(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(client.gson.toJson(expected), client.gson.toJson(resp.getValue()));
+ }
+
+ @Test
+ public void getRecordSetCountFailure() {
+ GetRecordSetCountRequest request = new GetRecordSetCountRequest(zoneId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/" + zoneId + "/recordsetcount"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getRecordSetCount(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getRecordSetChangeHistorySuccess_WithAllParams() {
+ String fqdn = recordSetName + "." + testZone1.getName() + ".";
+ String startFrom = listRecordSetsResponse.getStartFrom();
+ GetRecordSetChangeHistoryRequest request =
+ new GetRecordSetChangeHistoryRequest(zoneId, fqdn, RecordType.A.name(), startFrom, 100);
+
+ GetRecordSetChangeHistoryResponse expected =
+ new GetRecordSetChangeHistoryResponse(recordSetChangeList);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlPathEqualTo("/recordsetchange/history"))
+ .withQueryParam("zoneId", equalTo(zoneId))
+ .withQueryParam("fqdn", equalTo(fqdn))
+ .withQueryParam("recordType", equalTo(RecordType.A.name()))
+ .withQueryParam("maxItems", equalTo(String.valueOf(100)))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp =
+ client.getRecordSetChangeHistory(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(client.gson.toJson(expected), client.gson.toJson(resp.getValue()));
+ }
+
+ @Test
+ public void getRecordSetChangeHistoryFailure_Generic() {
+ GetRecordSetChangeHistoryRequest request =
+ new GetRecordSetChangeHistoryRequest(zoneId, null, null, null, null);
+
+ wireMockServer.stubFor(
+ get(urlPathEqualTo("/recordsetchange/history"))
+ .withQueryParam("zoneId", equalTo(zoneId))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp =
+ client.getRecordSetChangeHistory(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getFailedRecordSetChangesSuccess() {
+ GetFailedRecordSetChangesRequest request = new GetFailedRecordSetChangesRequest(zoneId);
+ int expectedFailureCount = recordSetChangeList.size();
+ GetFailedRecordSetChangesResponse expected =
+ new GetFailedRecordSetChangesResponse(expectedFailureCount);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/health/zones/" + zoneId + "/recordsetchangesfailure"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp =
+ client.getFailedRecordSetChanges(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getFailedRecordSetChangesFailure_Generic() {
+ GetFailedRecordSetChangesRequest request = new GetFailedRecordSetChangesRequest(zoneId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/health/zones/" + zoneId + "/recordsetchangesfailure"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp =
+ client.getFailedRecordSetChanges(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getZoneDetailsSuccess() {
+ GetZoneDetailsRequest request = new GetZoneDetailsRequest(zoneId);
+ GetZoneDetailsResponse expected = new GetZoneDetailsResponse(testZone1, ZoneAccessLevel.Read);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/" + zoneId + "/details"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.getZoneDetails(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(client.gson.toJson(expected), client.gson.toJson(resp.getValue()));
+ }
+
+ @Test
+ public void getZoneDetailsFailure() {
+ GetZoneDetailsRequest request = new GetZoneDetailsRequest(zoneId);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/" + zoneId + "/details"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getZoneDetails(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getZonesBackendIdsSuccess() {
+ List expected = Collections.singletonList(testZone1.getBackendId());
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/backendids"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse> resp = client.getZonesBackendIds();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getZonesBackendIdsFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/zones/backendids"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse> resp = client.getZonesBackendIds();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getFailedZoneChangesSuccess() {
+ GetFailedZoneChangesRequest request = new GetFailedZoneChangesRequest();
+ int expectedFailureCount = zones.size();
+ GetFailedZoneChangesResponse expected = new GetFailedZoneChangesResponse(expectedFailureCount);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/health/zonechangesfailure"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.getFailedZoneChanges(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getFailedZoneChangesFailure() {
+ GetFailedZoneChangesRequest request = new GetFailedZoneChangesRequest();
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/health/zonechangesfailure"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getFailedZoneChanges(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void addZoneAclRuleSuccess() {
+ ACLRule rule = testZoneAcl1.getRules().iterator().next();
+ AddZoneAclRuleRequest request = new AddZoneAclRuleRequest(zoneId, rule);
+ AddZoneAclRuleResponse expected = new AddZoneAclRuleResponse(rule);
+ String ruleJson = client.gson.toJson(rule);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/zones/" + zoneId + "/acl/rules"))
+ .withRequestBody(equalToJson(ruleJson))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.addZoneAclRule(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void addZoneAclRuleFailure() {
+ ACLRule rule = testZoneAcl1.getRules().iterator().next();
+ AddZoneAclRuleRequest request = new AddZoneAclRuleRequest(zoneId, rule);
+ String ruleJson = client.gson.toJson(rule);
+
+ wireMockServer.stubFor(
+ put(urlEqualTo("/zones/" + zoneId + "/acl/rules"))
+ .withRequestBody(equalToJson(ruleJson))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.addZoneAclRule(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void deleteZoneAclRuleSuccess() {
+ ACLRule rule = testZoneAcl1.getRules().iterator().next();
+ DeleteZoneAclRuleRequest request = new DeleteZoneAclRuleRequest(zoneId, rule);
+ DeleteZoneAclRuleResponse expected = new DeleteZoneAclRuleResponse(true, rule);
+
+ String ruleJson = client.gson.toJson(rule);
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ delete(urlEqualTo("/zones/" + zoneId + "/acl/rules"))
+ .withRequestBody(equalToJson(ruleJson))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.deleteZoneAclRule(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void deleteZoneAclRuleFailure() {
+ ACLRule rule = testZoneAcl1.getRules().iterator().next();
+ DeleteZoneAclRuleRequest request = new DeleteZoneAclRuleRequest(zoneId, rule);
+ String ruleJson = client.gson.toJson(rule);
+
+ wireMockServer.stubFor(
+ delete(urlEqualTo("/zones/" + zoneId + "/acl/rules"))
+ .withRequestBody(equalToJson(ruleJson))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.deleteZoneAclRule(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getPingSuccess() {
+ String expected = "pong";
+ wireMockServer.stubFor(
+ get(urlEqualTo("/ping"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "text/plain")
+ .withBody(expected)));
+
+ VinylDNSResponse resp = client.getPing();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getPingFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/ping"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "text/plain")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getPing();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getColorSuccess() {
+ String expected = "blue";
+ wireMockServer.stubFor(
+ get(urlEqualTo("/color"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "text/plain")
+ .withBody(expected)));
+
+ VinylDNSResponse resp = client.getColor();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getColorFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/color"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "text/plain")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getColor();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getPrometheusMetricsSuccess() {
+ String metrics = "# HELP vinyldns_up 1 if up\n# TYPE vinyldns_up gauge\nvinyldns_up 1\n";
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/prometheus"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "text/plain")
+ .withBody(metrics)));
+
+ VinylDNSResponse resp = client.getPrometheusMetrics();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(metrics, resp.getValue());
+ }
+
+ @Test
+ public void getPrometheusMetricsFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/metrics/prometheus"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "text/plain")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getPrometheusMetrics();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getHealthSuccess() {
+ String expected = "OK";
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/health"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "text/plain")
+ .withBody(expected)));
+
+ VinylDNSResponse resp = client.getHealth();
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getHealthFailure() {
+ wireMockServer.stubFor(
+ get(urlEqualTo("/health"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "text/plain")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getHealth();
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void getStatusSuccess() {
+ GetStatusRequest request = new GetStatusRequest();
+ Instant fixed = Instant.parse("2026-01-16T13:11:06Z");
+ StatusResponse expected = new StatusResponse(true, fixed, "Service healthy");
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/status"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.getStatus(request);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void getStatusFailure() {
+ GetStatusRequest request = new GetStatusRequest();
+
+ wireMockServer.stubFor(
+ get(urlEqualTo("/status"))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.getStatus(request);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void updateStatusSuccess_processingEnabledTrue() {
+
+ UpdateStatusRequest requestObj = new UpdateStatusRequest(true, "Healthy");
+ Instant fixed = Instant.parse("2026-01-16T13:11:12Z");
+
+ StatusResponse expected = new StatusResponse(true, fixed, "Processing enabled");
+ String responseJson = client.gson.toJson(expected);
+
+ wireMockServer.stubFor(
+ post(urlPathEqualTo("/status"))
+ .withQueryParam("processingDisabled", equalTo("false"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(responseJson)));
+
+ VinylDNSResponse resp = client.updateStatus(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void updateStatusFailure_processingEnabledFalse() {
+ UpdateStatusRequest requestObj =
+ new UpdateStatusRequest(
+ false, "Temporarily unavailable for maintenance"); // processingEnabled = false
+
+ wireMockServer.stubFor(
+ post(urlPathEqualTo("/status"))
+ .withQueryParam("processingDisabled", equalTo("true")) // !false == true
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("server error")));
+
+ VinylDNSResponse resp = client.updateStatus(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void requestTransfer_success() {
+ stubGetRecordSetSuccess();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RecordSetUpdateResponse expected =
+ new RecordSetUpdateResponse(
+ recordSetId,
+ zoneId,
+ ownerGroupId,
+ OwnershipTransferStatus.Requested,
+ "Ownership transfer requested");
+
+ stubPutRecordSetReturning(expected);
+
+ VinylDNSResponse resp = client.requestTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void approveTransfer_success() {
+ stubGetRecordSetSuccess();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RecordSetUpdateResponse expected =
+ new RecordSetUpdateResponse(
+ recordSetId,
+ zoneId,
+ ownerGroupId,
+ OwnershipTransferStatus.ManuallyApproved,
+ "Ownership transfer approved");
+
+ stubPutRecordSetReturning(expected);
+
+ VinylDNSResponse resp = client.approveTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void rejectTransfer_success() {
+ stubGetRecordSetSuccess();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RecordSetUpdateResponse expected =
+ new RecordSetUpdateResponse(
+ recordSetId,
+ zoneId,
+ ownerGroupId,
+ OwnershipTransferStatus.ManuallyRejected,
+ "Ownership transfer rejected");
+
+ stubPutRecordSetReturning(expected);
+
+ VinylDNSResponse resp = client.rejectTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void cancelTransfer_success() {
+ stubGetRecordSetSuccess();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RecordSetUpdateResponse expected =
+ new RecordSetUpdateResponse(
+ recordSetId,
+ zoneId,
+ ownerGroupId,
+ OwnershipTransferStatus.Cancelled,
+ "Ownership transfer cancelled");
+
+ stubPutRecordSetReturning(expected);
+
+ VinylDNSResponse resp = client.cancelTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Success);
+ assertEquals(200, resp.getStatusCode());
+ assertEquals(expected, resp.getValue());
+ }
+
+ @Test
+ public void requestTransfer_recordSetNotFound_throws() {
+ stubGetRecordSetNotFound();
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RuntimeException ex =
+ expectThrows(RuntimeException.class, () -> client.requestTransfer(requestObj));
+
+ assertEquals(ex.getMessage(), "Failed to fetch RecordSet before transfer");
+ }
+
+ @Test
+ public void approveTransfer_recordSetNotFound_throws() {
+ stubGetRecordSetNotFound();
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RuntimeException ex =
+ expectThrows(RuntimeException.class, () -> client.approveTransfer(requestObj));
+
+ assertEquals(ex.getMessage(), "Failed to fetch RecordSet before transfer");
+ }
+
+ @Test
+ public void rejectTransfer_recordSetNotFound_throws() {
+ stubGetRecordSetNotFound();
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RuntimeException ex =
+ expectThrows(RuntimeException.class, () -> client.rejectTransfer(requestObj));
+
+ assertEquals(ex.getMessage(), "Failed to fetch RecordSet before transfer");
+ }
+
+ @Test
+ public void cancelTransfer_recordSetNotFound_throws() {
+ stubGetRecordSetNotFound();
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ RuntimeException ex =
+ expectThrows(RuntimeException.class, () -> client.cancelTransfer(requestObj));
+
+ assertEquals(ex.getMessage(), "Failed to fetch RecordSet before transfer");
+ }
+
+ @Test
+ public void approveTransfer_badRequest() {
+ stubGetRecordSetSuccess();
+ stubPutRecordSetBadRequest();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ VinylDNSResponse resp = client.approveTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(400, resp.getStatusCode());
+ assertEquals("Invalid ownership transfer request", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void rejectTransfer_forbidden() {
+ stubGetRecordSetSuccess();
+ stubPutRecordSetForbidden();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ VinylDNSResponse resp = client.rejectTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(403, resp.getStatusCode());
+ assertEquals("User is not authorized to perform this action", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void cancelTransfer_conflict() {
+ stubGetRecordSetSuccess();
+ stubPutRecordSetConflict();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ VinylDNSResponse resp = client.cancelTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(409, resp.getStatusCode());
+ assertEquals("Ownership transfer is not in a valid state", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ @Test
+ public void requestTransfer_serverError() {
+ stubGetRecordSetSuccess();
+ stubPutRecordSetServerError();
+
+ RecordSetOwnershipTransferRequest requestObj = baseTransferRequest();
+
+ VinylDNSResponse resp = client.requestTransfer(requestObj);
+
+ assertTrue(resp instanceof ResponseMarker.Failure);
+ assertEquals(500, resp.getStatusCode());
+ assertEquals("Internal server error", resp.getMessageBody());
+ assertNull(resp.getValue());
+ }
+
+ private String rsId = "recordSetId";
+ private String zoneId = "zoneId";
+ private ZoneConnection testZoneConnection1 =
+ new ZoneConnection("name", "keyName", "key", "server");
+ private ZoneACL testZoneAcl1 =
+ new ZoneACL(
+ Collections.singleton(
+ new ACLRule(
+ ZoneAccessLevel.Read,
+ "description",
+ "displayname",
+ "userId",
+ "groupId",
+ "recordMask",
+ Collections.singleton(RecordType.A))));
+ private Zone testZone1 =
+ new Zone(
+ "id",
+ "name",
+ "some@company.com",
+ ZoneStatus.Active,
+ new DateTime(),
+ new DateTime(),
+ testZoneConnection1,
+ null,
+ true,
+ testZoneAcl1,
+ "group",
+ null,
+ true,
+ "somebackId");
+ private List zones = Collections.singletonList(testZone1);
+ private ListZonesResponse listZonesResponse =
+ new ListZonesResponse(zones, "startFrom", "nextId", 100, "nameFilter");
+
+ private String recordSetId = "recordSetId";
+ private String recordSetName = "recordSetName";
+ private String ownerGroupId = "ownerGroupId";
+ private String requestedOwnerGroupId = "requestedOwnerGroupId";
+ private List recordDataList = Collections.singletonList(new AData("192.168.1.1"));
+ private RecordSet recordSet =
+ new RecordSet(
+ zoneId,
+ recordSetName,
+ RecordType.A,
+ 100,
+ recordDataList,
+ recordSetId,
+ ownerGroupId,
+ RecordSetStatus.Active,
+ new DateTime(),
+ new DateTime());
+ private RecordSet recordSetNoOwner =
+ new RecordSet(
+ zoneId,
+ recordSetName,
+ RecordType.A,
+ 100,
+ recordDataList,
+ recordSetId,
+ null,
+ RecordSetStatus.Active,
+ new DateTime(),
+ new DateTime());
+ private RecordSet recordSetUpdate =
+ new RecordSet(
+ zoneId,
+ "recordSetNameUpdated",
+ RecordType.A,
+ 38400,
+ recordDataList,
+ recordSetId,
+ ownerGroupId,
+ RecordSetStatus.Active,
+ new DateTime(),
+ new DateTime());
+ private List recordSetList = Collections.singletonList(recordSet);
+
+ private String rsPath() {
+ return "/zones/" + zoneId + "/recordsets/" + recordSetId;
+ }
+
+ private void stubGetRecordSetSuccess() {
+ GetRecordSetResponse getResp = new GetRecordSetResponse(recordSet);
+ wireMockServer.stubFor(
+ get(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(client.gson.toJson(getResp))));
+ }
+
+ private void stubPutRecordSetReturning(RecordSetUpdateResponse expected) {
+ wireMockServer.stubFor(
+ put(urlEqualTo(rsPath()))
+ .withHeader("Content-Type", containing("application/json"))
+ .willReturn(
+ aResponse()
+ .withStatus(200)
+ .withHeader("Content-Type", "application/json")
+ .withBody(client.gson.toJson(expected))));
+ }
+
+ private RecordSetOwnershipTransferRequest baseTransferRequest() {
+ return RecordSetOwnershipTransferRequest.of(
+ zoneId, recordSetId, ownerGroupId, requestedOwnerGroupId);
+ }
+
+ private void stubGetRecordSetNotFound() {
+ wireMockServer.stubFor(
+ get(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(404)
+ .withHeader("Content-Type", "application/json")
+ .withBody("RecordSet not found")));
+ }
+
+ private void stubPutRecordSetBadRequest() {
+ wireMockServer.stubFor(
+ put(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(400)
+ .withHeader("Content-Type", "application/json")
+ .withBody("Invalid ownership transfer request")));
+ }
+
+ private void stubPutRecordSetForbidden() {
+ wireMockServer.stubFor(
+ put(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(403)
+ .withHeader("Content-Type", "application/json")
+ .withBody("User is not authorized to perform this action")));
+ }
+
+ private void stubPutRecordSetConflict() {
+ wireMockServer.stubFor(
+ put(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(409)
+ .withHeader("Content-Type", "application/json")
+ .withBody("Ownership transfer is not in a valid state")));
+ }
+
+ private void stubPutRecordSetServerError() {
+ wireMockServer.stubFor(
+ put(urlEqualTo(rsPath()))
+ .willReturn(
+ aResponse()
+ .withStatus(500)
+ .withHeader("Content-Type", "application/json")
+ .withBody("Internal server error")));
+ }
private ListRecordSetsResponse listRecordSetsResponse =
new ListRecordSetsResponse(recordSetList, "startFrom", "nextId", 22, "nameFilter");
@@ -1741,13 +2869,13 @@ public void listRecordSetGlobalFailure() {
new ListRecordSetChangesResponse(zoneId, recordSetChangeList, "", "startFrom", 1);
private SearchRecordSetsResponse searchRecordSetsResponse =
- new SearchRecordSetsResponse(
- Collections.EMPTY_LIST,
- "startFrom",
- "nextId",
- 55,
- "recordNameFilter",
- Collections.EMPTY_LIST,
- "recordOwnerGroupFilter",
- "nameSort");
+ new SearchRecordSetsResponse(
+ Collections.EMPTY_LIST,
+ "startFrom",
+ "nextId",
+ 55,
+ "recordNameFilter",
+ Collections.EMPTY_LIST,
+ "recordOwnerGroupFilter",
+ "nameSort");
}