diff --git a/README.md b/README.md index 40b47db..41f33ad 100644 --- a/README.md +++ b/README.md @@ -200,6 +200,109 @@ cfDnsClient.recordDeleteTypeIfExists(zone, "api", RecordType.A); System.out.println("Deletion attempt completed."); ``` +### Batch Operations + +Process multiple DNS record operations (POST, PUT, PATCH, DELETE) in a single batch request. + +- **Parameters**: + - `ZoneEntity zone` - The target zone. + - `List postRecords` - Records to create (nullable). + - `List putRecords` - Records to fully replace (nullable). + - `List patchRecords` - Records to partially update (nullable). + - `List deleteRecords` - Records to delete (nullable). +- **Returns**: A `BatchEntry` object containing the processed records. + +#### Batch Create (POST) + +```java +List newRecords = Arrays.asList( + RecordEntity.build("api." + zone.getName(), RecordType.A, 60, "192.168.1.10"), + RecordEntity.build("cdn." + zone.getName(), RecordType.A, 60, "192.168.1.11"), + RecordEntity.build("mail." + zone.getName(), RecordType.A, 60, "192.168.1.12") +); +BatchEntry result = cfDnsClient.recordBatch(zone, newRecords, null, null, null); +System.out. + +println("Created "+result.getPosts(). + +size() +" records."); +``` + +#### Batch Update (PATCH) + +```java +// Fetch existing records and modify them +List recordsToUpdate = Arrays.asList( + cfDnsClient.sldInfo(zone, "api", RecordType.A), + cfDnsClient.sldInfo(zone, "cdn", RecordType.A) + ); +recordsToUpdate. + +forEach(record ->record. + +setContent("192.168.2.10")); + +BatchEntry result = cfDnsClient.recordBatch(zone, null, null, recordsToUpdate, null); +System.out. + +println("Updated "+result.getPatches(). + +size() +" records."); +``` + +#### Batch Replace (PUT) + +```java +// Fetch existing records and fully replace them +List recordsToReplace = Arrays.asList( + cfDnsClient.sldInfo(zone, "api", RecordType.A), + cfDnsClient.sldInfo(zone, "cdn", RecordType.A) + ); +recordsToReplace. + +get(0). + +setContent("192.168.3.10"); +recordsToReplace. + +get(0). + +setTtl(120); + +BatchEntry result = cfDnsClient.recordBatch(zone, null, recordsToReplace, null, null); +System.out. + +println("Replaced "+result.getPuts(). + +size() +" records."); +``` + +#### Batch Delete + +```java +List recordsToDelete = Arrays.asList( + cfDnsClient.sldInfo(zone, "api", RecordType.A), + cfDnsClient.sldInfo(zone, "mail", RecordType.A) +); +BatchEntry result = cfDnsClient.recordBatch(zone, null, null, null, recordsToDelete); +System.out. + +println("Deleted records."); +``` + +#### Combined Batch Operations + +```java +// You can combine multiple operations in a single batch request +BatchEntry result = cfDnsClient.recordBatch( + zone, + newRecords, // POST + putRecords, // PUT + patchRecords, // PATCH + deleteRecords // DELETE + ); +``` + --- ### Notes on Error Handling diff --git a/src/main/java/codes/thischwa/cf/CfDnsClient.java b/src/main/java/codes/thischwa/cf/CfDnsClient.java index 5e551c0..be60193 100644 --- a/src/main/java/codes/thischwa/cf/CfDnsClient.java +++ b/src/main/java/codes/thischwa/cf/CfDnsClient.java @@ -272,7 +272,7 @@ public class CfDnsClient extends CfBasicHttpClient { if (changed) { log.debug("Record {} of the type [{}] successful deleted.", rec.getName(), rec.getType()); } else { - log.warn("Record {} of the type {} was not deleted.", rec.getName(), rec.getType()); + log.warn("Record {} of the type [{}] was not deleted.", rec.getName(), rec.getType()); } return changed; } diff --git a/src/test/java/codes/thischwa/cf/CfClientTest.java b/src/test/java/codes/thischwa/cf/CfClientTest.java index b14cc6d..12f4a96 100644 --- a/src/test/java/codes/thischwa/cf/CfClientTest.java +++ b/src/test/java/codes/thischwa/cf/CfClientTest.java @@ -35,13 +35,41 @@ public class CfClientTest { assumeTrue(API_KEY != null && !API_KEY.isBlank(), "API_KEY not set; skipping pen tests"); } + @Test + void testAddHost() throws Exception { + ZoneEntity zone = client.zoneInfo(ZONE_STR); + RecordEntity record = RecordEntity.build(SLD_STR, RecordType.A, TTL, "127.0.0.1"); + RecordEntity createdRecord = client.recordCreate(zone, record); + assertNotNull(createdRecord.getId()); + assertEquals(SLD_STR, createdRecord.getName()); + assertEquals(RecordType.A.getType(), createdRecord.getType()); + assertEquals(TTL, createdRecord.getTtl()); + assertEquals("127.0.0.1", createdRecord.getContent()); + assertNotNull(createdRecord.getCreatedOn()); + + client.recordDeleteTypeIfExists(zone, SLD_STR, RecordType.A); + assertThrows(CloudflareNotFoundException.class, + () -> client.sldInfo(zone, SLD_STR, RecordType.A)); + + record = RecordEntity.build(SLD_STR + "." + ZONE_STR, RecordType.A, TTL, "127.1.0.1"); + createdRecord = client.recordCreate(zone, record); + assertNotNull(createdRecord.getId()); + assertEquals(SLD_STR, createdRecord.getName()); + assertEquals(RecordType.A.getType(), createdRecord.getType()); + assertEquals(TTL, createdRecord.getTtl()); + assertEquals("127.1.0.1", createdRecord.getContent()); + assertNotNull(createdRecord.getCreatedOn()); + + client.recordDeleteTypeIfExists(zone, SLD_STR, RecordType.A); + } + @Test void testZoneListAnlFailedSldList() throws Exception { List zList = client.zoneListAll(); assertEquals(1, zList.size()); assertThrows(CloudflareNotFoundException.class, - () -> client.sldListAll(zList.get(0), "not-existing")); + () -> client.sldListAll(zList.get(0), "not-existing")); } @Test