diff --git a/src/main/java/codes/thischwa/cf/CfDnsClient.java b/src/main/java/codes/thischwa/cf/CfDnsClient.java index 61f52df..51c1d94 100644 --- a/src/main/java/codes/thischwa/cf/CfDnsClient.java +++ b/src/main/java/codes/thischwa/cf/CfDnsClient.java @@ -13,7 +13,10 @@ import codes.thischwa.cf.model.RecordType; import codes.thischwa.cf.model.ZoneEntity; import codes.thischwa.cf.model.ZoneMultipleResponse; import java.util.ArrayList; +import java.util.HashMap; import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.Nullable; @@ -110,6 +113,21 @@ public class CfDnsClient extends CfBasicHttpClient { return sld + "." + zone.getName(); } + /** + * Groups a list of DNS records by their fully qualified domain name (FQDN). + * + * @param records A list of {@link RecordEntity} objects to be grouped by FQDN. + * @return A map where the key is the FQDN (name field) and the value is a list of {@link RecordEntity} + * objects that share that FQDN. + */ + public static Map> groupRecordsByFqdn(List records) { + if (records == null) { + return new HashMap<>(); + } + return records.stream() + .collect(Collectors.groupingBy(RecordEntity::getName)); + } + /** * Provides fluent API access to operations on a specific zone. * This method returns a ZoneOperations interface that allows chaining operations @@ -202,7 +220,9 @@ public class CfDnsClient extends CfBasicHttpClient { String endpoint = buildEndpointWithTypeFilters(CfRequest.RECORD_INFO_NAME.buildPath(zone.getId(), fqdn), types); RecordMultipleResponse resp = getRequest(endpoint, RecordMultipleResponse.class); checkResponse(resp, false); - return resp.getResult(); + List recs = resp.getResult(); + recs.forEach(rec -> rec.setZoneId(zone.getId())); + return recs; } /** @@ -307,7 +327,9 @@ public class CfDnsClient extends CfBasicHttpClient { RecordSingleResponse resp = postRequest(endpoint, rec, RecordSingleResponse.class); checkResponse(resp); log.info("Record {} of type {} successful created.", rec.getSld(), rec.getType()); - return resp.getResult(); + RecordEntity record = resp.getResult(); + record.setZoneId(zone.getId()); + return record; } /** diff --git a/src/test/java/codes/thischwa/cf/CfClientTest.java b/src/test/java/codes/thischwa/cf/CfClientTest.java index 4228166..81498ec 100644 --- a/src/test/java/codes/thischwa/cf/CfClientTest.java +++ b/src/test/java/codes/thischwa/cf/CfClientTest.java @@ -11,7 +11,9 @@ 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.List; +import java.util.Map; import java.util.Objects; import lombok.extern.slf4j.Slf4j; import org.junit.jupiter.api.BeforeAll; @@ -118,8 +120,10 @@ public class CfClientTest { createdRe1 = client.recordCreate(z, RecordEntity.build(domain, RecordType.A, TTL, "130.0.0.3")); assertNotNull(createdRe1.getId()); + assertEquals(randomSld+ "." + ZONE_STR, createdRe1.getName()); assertEquals(randomSld, createdRe1.getSld()); assertEquals(RecordType.A.getType(), createdRe1.getType()); + assertEquals(z.getId(), createdRe1.getZoneId()); assertEquals(TTL, createdRe1.getTtl()); assertEquals("130.0.0.3", createdRe1.getContent()); assertNotNull(createdRe1.getCreatedOn()); @@ -137,6 +141,7 @@ public class CfClientTest { List aaaaRecords = client.recordList(z, randomSld, RecordType.AAAA); assertEquals(1, aaaaRecords.size()); r = aaaaRecords.get(0); + assertEquals(z.getId(), r.getZoneId()); assertEquals("2a0a:4cc0:c0:2e4::1", r.getContent()); assertEquals(RecordType.AAAA.getType(), r.getType()); @@ -144,6 +149,7 @@ public class CfClientTest { List rList = client.recordList(z, randomSld); assertEquals(2, rList.size()); for (RecordEntity re : rList) { + assertEquals(z.getId(), re.getZoneId()); if (Objects.equals(re.getType(), RecordType.A.getType())) { assertEquals("130.0.0.3", re.getContent()); } else if (Objects.equals(re.getType(), RecordType.AAAA.getType())) { @@ -196,10 +202,7 @@ public class CfClientTest { } finally { // cleanup in case of failures during test try { - client.recordDeleteTypeIfExists(z, randomSld, RecordType.AAAA); - } catch (Exception e) { /* ignore */ } - try { - client.recordDeleteTypeIfExists(z, randomSld, RecordType.A); + client.recordDeleteTypeIfExists(z, randomSld, RecordType.A, RecordType.AAAA); } catch (Exception e) { /* ignore */ } } } @@ -400,4 +403,39 @@ public class CfClientTest { } } + @Test + void testGroupRecordsByFqdn_withValidRecords() { + // Arrange + RecordEntity rec1 = RecordEntity.build("1", "example.com.", "A", 300, "192.168.1.1"); + RecordEntity rec2 = RecordEntity.build("2", "example.com.", "AAAA", 300, "::1"); + RecordEntity rec3 = RecordEntity.build("3", "sub.example.com.", "CNAME", 300, "example.com."); + List records = Arrays.asList(rec1, rec2, rec3); + + // Act + Map> groupedRecords = CfDnsClient.groupRecordsByFqdn(records); + + // Assert + assertNotNull(groupedRecords, "Resulting map should not be null."); + assertEquals(2, groupedRecords.size(), "The grouping should result in 2 FQDN keys."); + assertEquals(2, groupedRecords.get("example.com.").size(), "The key 'example.com.' should have 2 records."); + assertEquals(1, groupedRecords.get("sub.example.com.").size(), "The key 'sub.example.com.' should have 1 record."); + } + + @Test + void testGroupRecordsByFqdn_withMultipleRecordsSameFqdn() { + // Arrange + RecordEntity rec1 = RecordEntity.build("1", "example.com.", "A", 300, "192.168.1.1"); + RecordEntity rec2 = RecordEntity.build("2", "example.com.", "AAAA", 300, "::1"); + List records = Arrays.asList(rec1, rec2); + + // Act + Map> groupedRecords = CfDnsClient.groupRecordsByFqdn(records); + + // Assert + assertNotNull(groupedRecords, "Resulting map should not be null."); + assertEquals(1, groupedRecords.size(), "The grouping should result in 1 FQDN key."); + assertEquals(2, groupedRecords.get("example.com.").size(), "The key 'example.com.' should have 2 records."); + } + + }