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"); }