From 0eaca55e95a9b0f73f29e7c9222bf63665933286 Mon Sep 17 00:00:00 2001 From: Thilo Schwarz Date: Thu, 25 Dec 2025 20:43:31 +0100 Subject: [PATCH] issue #5 - Update `pom.xml` version to `0.2.0-beta.1-SNAPSHOT`, enhance logging, and refine DNS batch record processing method. --- pom.xml | 2 +- .../codes/thischwa/cf/CfBasicHttpClient.java | 2 +- .../java/codes/thischwa/cf/CfDnsClient.java | 44 +++++++++++++------ .../codes/thischwa/cf/model/RecordEntity.java | 17 +++++++ .../java/codes/thischwa/cf/CfClientTest.java | 23 ++++++++-- src/test/resources/logback-test.xml | 21 ++++----- 6 files changed, 80 insertions(+), 29 deletions(-) diff --git a/pom.xml b/pom.xml index 045c2e0..86d8858 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ codes.thischwa cloudflaredns - 0.1.1-SNAPSHOT + 0.2.0-beta.1-SNAPSHOT CloudflareDNS-java 2025 jar diff --git a/src/main/java/codes/thischwa/cf/CfBasicHttpClient.java b/src/main/java/codes/thischwa/cf/CfBasicHttpClient.java index 21f8c6e..28b3ab6 100644 --- a/src/main/java/codes/thischwa/cf/CfBasicHttpClient.java +++ b/src/main/java/codes/thischwa/cf/CfBasicHttpClient.java @@ -152,7 +152,7 @@ abstract class CfBasicHttpClient { throws CloudflareApiException { try { String jsonPayload = objectMapper.writeValueAsString(requestPayload); - log.debug("Request payload: {}", jsonPayload); + log.trace("Request methode [{}] payload: {}", request.getMethod(), jsonPayload); request.setEntity(new StringEntity(jsonPayload, ContentType.APPLICATION_JSON)); } catch (JsonProcessingException e) { diff --git a/src/main/java/codes/thischwa/cf/CfDnsClient.java b/src/main/java/codes/thischwa/cf/CfDnsClient.java index 5ec2a21..5e551c0 100644 --- a/src/main/java/codes/thischwa/cf/CfDnsClient.java +++ b/src/main/java/codes/thischwa/cf/CfDnsClient.java @@ -339,21 +339,20 @@ public class CfDnsClient extends CfBasicHttpClient { } /** - * Records a batch of DNS record operations, including creating, updating, and deleting records - * within a specific zone. This method processes the provided put, patch, and delete operations - * into a clean format before sending a batch request to the Cloudflare API. + * Processes a batch of DNS record operations (POST, PUT, PATCH, DELETE) for a specified zone. + * This method builds and cleans the input records, sends the batch request to the Cloudflare API, + * and returns a result containing processed batch entries. * - * @param zone the zone entity representing the DNS zone where the changes will be applied - * @param ttl the time-to-live (TTL) value assigned to the new records being added - * @param postRecords a list of records to be created; each record must contain the necessary - * attributes for creation - * @param patchRecords a list of records to be updated; only specific attributes (e.g., content) - * will be modified - * @param deleteRecords a list of records to be deleted; each record must contain name, type, and content - * @throws CloudflareApiException if there is an error while communicating with the Cloudflare API + * @param zone The zone entity to which the records belong. + * @param postRecords A list of DNS records to be created (POST). This parameter is nullable. + * @param putRecords A list of DNS records to be fully replaced (PUT). This parameter is nullable. + * @param patchRecords A list of DNS records to be partially updated (PATCH). This parameter is nullable. + * @param deleteRecords A list of DNS records to be deleted (DELETE). This parameter is nullable. + * @return The resulting {@link BatchEntry} containing the processed records after the batch operation. + * @throws CloudflareApiException If an error occurs while communicating with the Cloudflare API. */ - public void recordBatch(ZoneEntity zone, int ttl, @Nullable List postRecords, - @Nullable List patchRecords, @Nullable List deleteRecords) + public BatchEntry recordBatch(ZoneEntity zone, @Nullable List postRecords, @Nullable List putRecords, + @Nullable List patchRecords, @Nullable List deleteRecords) throws CloudflareApiException { BatchEntry batchEntry = new BatchEntry(); // build 'clean' record entries @@ -363,6 +362,12 @@ public class CfDnsClient extends CfBasicHttpClient { rec -> cleanedPosts.add(RecordEntity.build(rec.getId(), rec.getName(), rec.getType(), rec.getTtl(), rec.getContent()))); batchEntry.setPosts(cleanedPosts); } + if (putRecords != null) { + List cleanedPuts = new ArrayList<>(); + putRecords.forEach( + rec -> cleanedPuts.add(RecordEntity.build(rec.getId(), rec.getName(), rec.getType(), rec.getTtl(), rec.getContent()))); + batchEntry.setPuts(cleanedPuts); + } if (patchRecords != null) { List cleanedPatches = new ArrayList<>(); patchRecords.forEach(rec -> cleanedPatches.add(RecordEntity.build(rec.getId(), rec.getContent()))); @@ -378,6 +383,19 @@ public class CfDnsClient extends CfBasicHttpClient { String endpoint = CfRequest.RECORD_BATCH.buildPath(zone.getId()); BatchResponse resp = postRequest(endpoint, batchEntry, BatchResponse.class); checkResponse(resp); + + // set zone id + BatchEntry result = resp.getResult(); + if (result.getPosts() != null) { + result.getPosts().forEach(rec -> rec.setZoneId(zone.getId())); + } + if (result.getPuts() != null) { + result.getPuts().forEach(rec -> rec.setZoneId(zone.getId())); + } + if (result.getPatches() != null) { + result.getPatches().forEach(rec -> rec.setZoneId(zone.getId())); + } + return result; } private void checkResponse(AbstractResponse resp) throws CloudflareApiException { diff --git a/src/main/java/codes/thischwa/cf/model/RecordEntity.java b/src/main/java/codes/thischwa/cf/model/RecordEntity.java index 3787f7d..d506606 100644 --- a/src/main/java/codes/thischwa/cf/model/RecordEntity.java +++ b/src/main/java/codes/thischwa/cf/model/RecordEntity.java @@ -53,6 +53,23 @@ public class RecordEntity extends AbstractEntity { super(); } + /** + * Retrieves the name of the DNS record. + * If the name contains a dot ('.'), only the substring before the first dot is returned. + * + * @return the name of the DNS record, potentially truncated before the first dot, + * or the full name if no dot is present. + */ + public String getName() { + if (name != null) { + int pos = name.indexOf('.'); + if (pos > 0) { + return name.substring(0, pos); + } + } + return name; + } + /** * Builds and returns a {@link RecordEntity} instance with the specified attributes. * diff --git a/src/test/java/codes/thischwa/cf/CfClientTest.java b/src/test/java/codes/thischwa/cf/CfClientTest.java index da25559..c12f973 100644 --- a/src/test/java/codes/thischwa/cf/CfClientTest.java +++ b/src/test/java/codes/thischwa/cf/CfClientTest.java @@ -6,6 +6,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assumptions.assumeTrue; +import codes.thischwa.cf.model.BatchEntry; import codes.thischwa.cf.model.RecordEntity; import codes.thischwa.cf.model.RecordType; import codes.thischwa.cf.model.ZoneEntity; @@ -157,6 +158,7 @@ public class CfClientTest { String sld1 = SLD_STR + "-1"; String sld2 = SLD_STR + "-2"; String sld3 = SLD_STR + "-3"; + String sld4 = SLD_STR + "-4"; RecordEntity r1 = RecordEntity.build(sld1, RecordType.A, TTL, "130.0.0.1"); RecordEntity r2 = RecordEntity.build(sld2, RecordType.A, TTL, "130.0.0.2"); RecordEntity r3 = RecordEntity.build(sld3, RecordType.A, TTL, "130.0.0.3"); @@ -167,8 +169,15 @@ public class CfClientTest { client.recordDeleteTypeIfExists(z, sld3, RecordType.A); try { - // test put - client.recordBatch(z, 30, List.of(r1, r2, r3), null, null); + // test pos + BatchEntry batchEntry = client.recordBatch(z, List.of(r1, r2, r3), null, null, null); + assertEquals(3, batchEntry.getPosts().size()); + RecordEntity batchedRec = batchEntry.getPosts().get(0); + assertNotNull(batchedRec.getId()); + assertEquals(r1.getName(), batchedRec.getName()); + assertEquals(r1.getType(), batchedRec.getType()); + assertNotNull(batchedRec.getCreatedOn()); + RecordEntity testRec = client.sldInfo(z, sld1, RecordType.A); assertEquals("130.0.0.1", testRec.getContent()); testRec = client.sldInfo(z, sld2, RecordType.A); @@ -179,14 +188,20 @@ public class CfClientTest { // test patch r1 = client.sldInfo(z, sld1, RecordType.A); r1.setContent("130.1.0.1"); - client.recordBatch(z, 30, null, List.of(r1), null); + client.recordBatch(z, null, null, List.of(r1), null); testRec = client.sldInfo(z, sld1, RecordType.A); assertEquals("130.1.0.1", testRec.getContent()); // test delete - client.recordBatch(z, 30, null, null, List.of(r1)); + client.recordBatch(z, null, null, null, List.of(r1)); assertThrows(CloudflareNotFoundException.class, () -> client.sldInfo(z, sld1, RecordType.A)); + + // test put + r1 = RecordEntity.build(sld4, RecordType.A, TTL, "130.1.0.2"); + client.recordBatch(z, List.of(r1), null, null, null); + testRec = client.sldInfo(z, sld4, RecordType.A); + assertEquals("130.1.0.2", testRec.getContent()); } finally { client.recordDeleteTypeIfExists(z, sld1, RecordType.A); client.recordDeleteTypeIfExists(z, sld2, RecordType.A); diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml index 64aef5d..42dc8c6 100644 --- a/src/test/resources/logback-test.xml +++ b/src/test/resources/logback-test.xml @@ -1,16 +1,17 @@ - - - %d{HH:mm:ss.SSS} [%t] %-5level %logger{50} - %msg%n - - + + + %d{HH:mm:ss.SSS} [%t] %-5level %logger{50} - %msg%n + + - + + - - - + + + \ No newline at end of file