issue #15 Add paging support in recordList API, update tests, and streamline query parameter names.
This commit is contained in:
@@ -116,7 +116,7 @@ public class CfDnsClient extends CfBasicHttpClient {
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides fluent API access to operations on a specific zone.
|
||||
* Provides fluent API access to operations in a specific zone.
|
||||
* This method returns a ZoneOperations interface that allows chaining operations
|
||||
* on DNS records within the specified zone.
|
||||
*
|
||||
@@ -177,6 +177,33 @@ public class CfDnsClient extends CfBasicHttpClient {
|
||||
return response.getResult().get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of DNS records for a specified zone, with optional paging support.
|
||||
*
|
||||
* @param zone The zone entity containing information about the target zone.
|
||||
* @return A list of RecordEntity objects representing the DNS records of the specified zone.
|
||||
* @throws CloudflareApiException If an error occurs during the API request or response processing.
|
||||
*/
|
||||
public List<RecordEntity> recordList(ZoneEntity zone) throws CloudflareApiException {
|
||||
return recordList(zone, (PagingRequest) null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of DNS records for a specified zone, with optional paging support.
|
||||
*
|
||||
* @param zone The zone entity containing information about the target zone.
|
||||
* @param pagingRequest The paging request containing parameters such as page size and number.
|
||||
* @return A list of RecordEntity objects representing the DNS records of the specified zone.
|
||||
* @throws CloudflareApiException If an error occurs during the API request or response processing.
|
||||
*/
|
||||
public List<RecordEntity> recordList(ZoneEntity zone, @Nullable PagingRequest pagingRequest) throws CloudflareApiException {
|
||||
PagingRequest pr = pagingRequest == null ? PagingRequest.defaultPaging() : pagingRequest;
|
||||
String endpoint = pr.addQueryString(CfRequest.RECORD_LIST.buildPath(zone.getId()));
|
||||
RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class);
|
||||
checkResponse(resp);
|
||||
return resp.getResult();
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves DNS records for the specified second-level domain (SLD) within a zone.
|
||||
*
|
||||
@@ -203,35 +230,17 @@ public class CfDnsClient extends CfBasicHttpClient {
|
||||
*/
|
||||
public List<RecordEntity> recordList(ZoneEntity zone, String sld, @Nullable RecordType... types)
|
||||
throws CloudflareApiException {
|
||||
PagingRequest pagingRequest = PagingRequest.defaultPaging();
|
||||
List<RecordEntity> recs = recordList(zone, sld, pagingRequest);
|
||||
return filterAndSetZoneRecords(zone, types, recs);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Retrieves all getRecord entities for a specific second-level domain (SLD) within a given DNS
|
||||
* zone using the provided paging request parameters.
|
||||
*
|
||||
* @param zone The DNS zone entity for which the SLD records are to be fetched.
|
||||
* @param sld The second-level domain name for which the records are retrieved.
|
||||
* @param pagingRequest The paging request.
|
||||
* @return A list of {@code RecordEntity} associated with the desired SLD.
|
||||
* @throws CloudflareApiException If an error occurs while interacting with the Cloudflare API.
|
||||
*/
|
||||
public List<RecordEntity> recordList(ZoneEntity zone, String sld, PagingRequest pagingRequest)
|
||||
throws CloudflareApiException {
|
||||
String fqdn = buildFqdn(zone, sld);
|
||||
String endpoint =
|
||||
pagingRequest.addQueryString(CfRequest.RECORD_INFO_NAME.buildPath(zone.getId(), fqdn));
|
||||
String endpoint = CfRequest.RECORD_LIST_NAME.buildPath(zone.getId(), fqdn);
|
||||
RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class);
|
||||
checkResponse(resp);
|
||||
return resp.getResult();
|
||||
checkResponse(resp, false);
|
||||
List<RecordEntity> recs = resp.getResult();
|
||||
return filterAndSetZoneRecords(zone, types, recs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a list of all DNS records for a given zone.
|
||||
* Optionally filters by one or more DNS getRecord types.
|
||||
* Optionally, filters by one or more DNS getRecord types.
|
||||
*
|
||||
* @param zone The zone entity containing information about the domain zone.
|
||||
* @param types Optional parameter specifying one or more DNS getRecord types to filter the results.
|
||||
@@ -438,7 +447,7 @@ public class CfDnsClient extends CfBasicHttpClient {
|
||||
Set<RecordType> allowedTypes = new HashSet<>(Arrays.asList(types));
|
||||
filtered = recs.stream()
|
||||
.filter(rec -> allowedTypes.contains(RecordType.valueOf(rec.getType())))
|
||||
.collect(Collectors.toList());;
|
||||
.collect(Collectors.toList());
|
||||
} else {
|
||||
filtered = new ArrayList<>(recs);
|
||||
}
|
||||
|
||||
@@ -26,25 +26,24 @@ public enum CfRequest {
|
||||
* needs to be provided to construct the complete path.
|
||||
*/
|
||||
RECORD_LIST("/zones/%s/dns_records"),
|
||||
/**
|
||||
* Represents the API endpoint path for retrieving information about a DNS getRecord within a
|
||||
* specific DNS zone by its name. The endpoint path includes placeholders for the zone identifier
|
||||
* and the getRecord name, which need to be provided to construct the complete path.
|
||||
*/
|
||||
RECORD_LIST_NAME("/zones/%s/dns_records?name=%s"),
|
||||
/**
|
||||
* Represents the API endpoint path for creating a new DNS getRecord within a specific DNS zone. The
|
||||
* endpoint path includes a placeholder for the zone identifier, which needs to be provided to
|
||||
* construct the complete path.
|
||||
*/
|
||||
RECORD_CREATE("/zones/%s/dns_records"),
|
||||
/**
|
||||
* Represents the API endpoint path for retrieving information about a DNS getRecord within a
|
||||
* specific DNS zone by its name. The endpoint path includes placeholders for the zone identifier
|
||||
* and the getRecord name, which need to be provided to construct the complete path.
|
||||
*/
|
||||
RECORD_INFO_NAME("/zones/%s/dns_records?name=%s"),
|
||||
/**
|
||||
* Represents the API endpoint path for updating an existing DNS getRecord within a specific DNS
|
||||
* zone. The endpoint path includes placeholders for the zone identifier and the getRecord
|
||||
* identifier, which need to be provided to construct the complete path.
|
||||
*/
|
||||
RECORD_UPDATE("/zones/%s/dns_records/%s"),
|
||||
|
||||
/**
|
||||
* Represents the API endpoint path for performing batch operations on DNS records within a specific zone.
|
||||
* The placeholder "%s" in the path is intended to be replaced by a zone identifier.
|
||||
|
||||
@@ -25,7 +25,7 @@ public class PagingRequest {
|
||||
* Default page size for retrieving all records in a single request.
|
||||
* Set to a very high value to effectively disable pagination when fetching all records.
|
||||
*/
|
||||
private static final int DEFAULT_ALL_RECORDS_PAGE_SIZE = 5_000_000;
|
||||
private static final int DEFAULT_ALL_RECORDS_PAGE_SIZE = 1000;
|
||||
|
||||
private int page;
|
||||
private int perPage;
|
||||
@@ -77,7 +77,7 @@ public class PagingRequest {
|
||||
}
|
||||
|
||||
private String queryString(boolean add) {
|
||||
String qs = "page=" + page + "&perPage=" + perPage;
|
||||
String qs = "page=" + page + "&per_page=" + perPage;
|
||||
return add ? "&" + qs : "?" + qs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,14 +9,18 @@ import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.junit.jupiter.api.Assumptions.assumeTrue;
|
||||
|
||||
import codes.thischwa.cf.model.BatchEntry;
|
||||
import codes.thischwa.cf.model.PagingRequest;
|
||||
import codes.thischwa.cf.model.RecordEntity;
|
||||
import codes.thischwa.cf.model.RecordType;
|
||||
import codes.thischwa.cf.model.ZoneEntity;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
@@ -91,6 +95,19 @@ public class CfClientTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void testZoneList() throws CloudflareApiException {
|
||||
List<ZoneEntity> zones = client.zoneList();
|
||||
assertNotNull(zones);
|
||||
assertFalse(zones.isEmpty());
|
||||
assertEquals(ZONE_STR, zones.get(0).getName());
|
||||
|
||||
zones = client.zoneList(PagingRequest.of(1, 100));
|
||||
assertNotNull(zones);
|
||||
assertFalse(zones.isEmpty());
|
||||
assertEquals(ZONE_STR, zones.get(0).getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testZoneListAnlFailedSldList() throws Exception {
|
||||
List<ZoneEntity> zList = client.zoneList();
|
||||
@@ -445,4 +462,68 @@ public class CfClientTest {
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
void testPaging() throws Exception {
|
||||
ZoneEntity zone = client.zoneGet(ZONE_STR);
|
||||
String pagingSld = "paging-" + System.currentTimeMillis();
|
||||
|
||||
try {
|
||||
int existingCount = 0;
|
||||
try {
|
||||
List<RecordEntity> allRecords = client.recordList(zone);
|
||||
existingCount = allRecords.size();
|
||||
} catch (CloudflareApiException e) {
|
||||
// ignore
|
||||
}
|
||||
|
||||
// Calculate how many records we need to create to reach at least 12 total A records
|
||||
// (to test paging with pageSize 5: page 1 = 5, page 2 = 5, page 3 = 2+)
|
||||
int targetCount = 12;
|
||||
int recordsToCreate = Math.max(0, targetCount - existingCount);
|
||||
|
||||
// Create additional A records if needed
|
||||
List<RecordEntity> createdRecords = new ArrayList<>();
|
||||
for (int i = 1; i <= recordsToCreate; i++) {
|
||||
RecordEntity record = RecordEntity.build(pagingSld, RecordType.A, TTL, "127.0.0." + i);
|
||||
RecordEntity created = client.recordCreate(zone, record);
|
||||
createdRecords.add(created);
|
||||
assertNotNull(created.getId());
|
||||
}
|
||||
|
||||
// Test paging with page size of 5
|
||||
PagingRequest page1Request = PagingRequest.of(1, 5);
|
||||
List<RecordEntity> page1Records = client.recordList(zone, page1Request);
|
||||
assertEquals(5, page1Records.size(), "First page should contain 5 records");
|
||||
|
||||
// 2nd page should also contain 5 records (if we have at least 12 total)
|
||||
PagingRequest page2Request = PagingRequest.of(2, 5);
|
||||
List<RecordEntity> page2Records = client.recordList(zone, page2Request);
|
||||
assertEquals(5, page2Records.size(), "Second page should contain at least 5 records");
|
||||
|
||||
// 3rd page should contain 2 records
|
||||
PagingRequest page3Request = PagingRequest.of(3, 5);
|
||||
List<RecordEntity> page3Records = client.recordList(zone, page3Request);
|
||||
assertEquals(2, page3Records.size(), "Third page should contain 2 records");
|
||||
|
||||
// Verify no overlap between pages
|
||||
List<String> page1Ids = page1Records.stream().map(RecordEntity::getId).toList();
|
||||
List<String> page2Ids = page2Records.stream().map(RecordEntity::getId).toList();
|
||||
List<String> page3Ids = page3Records.stream().map(RecordEntity::getId).toList();
|
||||
Set<String> generatedRecordIds = new HashSet<>(page1Ids);
|
||||
generatedRecordIds.addAll(page2Ids);
|
||||
generatedRecordIds.addAll(page3Ids);
|
||||
assertEquals(createdRecords.size(), generatedRecordIds.size());
|
||||
|
||||
// Verify our created records are in the zone
|
||||
List<RecordEntity> allRecords = client.recordList(zone);
|
||||
Set<String> allRecordIds = allRecords.stream().map(RecordEntity::getId).collect(Collectors.toSet());
|
||||
assertEquals(createdRecords.size(), allRecordIds.size());
|
||||
assertTrue(allRecordIds.containsAll(generatedRecordIds));
|
||||
} finally {
|
||||
try {
|
||||
client.recordDeleteTypeIfExists(zone, pagingSld, RecordType.A);
|
||||
} catch (Exception e) { /* ignore */ }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ public class CfRequestTest {
|
||||
|
||||
@Test
|
||||
public void testBuildRecordInfoName() {
|
||||
String result = CfRequest.RECORD_INFO_NAME.buildPath("zone123", "sub.domain.com");
|
||||
String result = CfRequest.RECORD_LIST_NAME.buildPath("zone123", "sub.domain.com");
|
||||
assertEquals("/zones/zone123/dns_records?name=sub.domain.com", result);
|
||||
}
|
||||
|
||||
@@ -45,7 +45,7 @@ public class CfRequestTest {
|
||||
|
||||
@Test
|
||||
public void testBuildRecordInfo() {
|
||||
String result = CfRequest.RECORD_INFO_NAME.buildPath("zone123", "sld.domain.com");
|
||||
String result = CfRequest.RECORD_LIST_NAME.buildPath("zone123", "sld.domain.com");
|
||||
assertEquals("/zones/zone123/dns_records?name=sld.domain.com", result);
|
||||
}
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@ public class PagingRequestTest {
|
||||
@Test
|
||||
void testBuildPath() {
|
||||
String result = PagingRequest.defaultPaging().addQueryString("/zones");
|
||||
assertEquals("/zones?page=1&perPage=5000000", result);
|
||||
assertEquals("/zones?page=1&per_page=1000", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBuildPathAdditional() {
|
||||
String result = new PagingRequest( 10, 100).addQueryString("/zones?foo=bar");
|
||||
assertEquals("/zones?foo=bar&page=10&perPage=100", result);
|
||||
assertEquals("/zones?foo=bar&page=10&per_page=100", result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<configuration>
|
||||
<configuration debug="true">
|
||||
|
||||
<appender name="current"
|
||||
class="ch.qos.logback.core.ConsoleAppender">
|
||||
|
||||
Reference in New Issue
Block a user