diff --git a/modules/api/functional_test/live_tests/batch/create_batch_change_test.py b/modules/api/functional_test/live_tests/batch/create_batch_change_test.py index 9f1b089b7..6fea365a9 100644 --- a/modules/api/functional_test/live_tests/batch/create_batch_change_test.py +++ b/modules/api/functional_test/live_tests/batch/create_batch_change_test.py @@ -1773,7 +1773,7 @@ def test_aaaa_recordtype_update_delete_checks(shared_zone_test_context): rs_delete_name = generate_record_name() rs_delete_fqdn = rs_delete_name + ".ok." - rs_delete_ok = get_recordset_json(ok_zone, rs_delete_name, "AAAA", [{"address": "1:2:3:4:5:6:7:8"}], 200) + rs_delete_ok = get_recordset_json(ok_zone, rs_delete_name, "AAAA", [{"address": "1::4:5:6:7:8"}], 200) rs_update_name = generate_record_name() rs_update_fqdn = rs_update_name + ".ok." @@ -1792,7 +1792,7 @@ def test_aaaa_recordtype_update_delete_checks(shared_zone_test_context): "comments": "this is optional", "changes": [ # valid changes - get_change_A_AAAA_json(rs_delete_fqdn, record_type="AAAA", change_type="DeleteRecordSet"), + get_change_A_AAAA_json(rs_delete_fqdn, record_type="AAAA", change_type="DeleteRecordSet", address="1:0::4:5:6:7:8"), get_change_A_AAAA_json(rs_update_fqdn, record_type="AAAA", ttl=300, address="1:2:3:4:5:6:7:8"), get_change_A_AAAA_json(rs_update_fqdn, record_type="AAAA", change_type="DeleteRecordSet"), diff --git a/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchChangeValidations.scala b/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchChangeValidations.scala index fdf2c4c88..d2d1ee740 100644 --- a/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchChangeValidations.scala +++ b/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchChangeValidations.scala @@ -16,6 +16,8 @@ package vinyldns.api.domain.batch +import java.net.InetAddress + import cats.data._ import cats.implicits._ import vinyldns.api.VinylDNSConfig @@ -295,6 +297,17 @@ class BatchChangeValidations( else ().validNel + def matchRecordData(existingRecordSetData: List[RecordData], recordData: RecordData): Boolean = + existingRecordSetData.exists { rd => + (rd, recordData) match { + case (AAAAData(rdAddress), AAAAData(proposedAddress)) => + InetAddress.getByName(proposedAddress).getHostName == InetAddress + .getByName(rdAddress) + .getHostName + case _ => rd == recordData + } + } + def ensureRecordExists( change: ChangeForValidation, groupedChanges: ChangeForValidationMap @@ -308,7 +321,7 @@ class BatchChangeValidations( ) if !groupedChanges .getExistingRecordSet(change.recordKey) - .exists(_.records.contains(recordData)) => + .exists(rs => matchRecordData(rs.records, recordData)) => DeleteRecordDataDoesNotExist(inputName, recordData).invalidNel case _ => ().validNel diff --git a/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchTransformations.scala b/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchTransformations.scala index f531e6cdb..b5fa5edf3 100644 --- a/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchTransformations.scala +++ b/modules/api/src/main/scala/vinyldns/api/domain/batch/BatchTransformations.scala @@ -16,6 +16,7 @@ package vinyldns.api.domain.batch +import java.net.InetAddress import java.util.UUID import vinyldns.api.VinylDNSConfig @@ -24,7 +25,7 @@ import vinyldns.api.domain.batch.BatchChangeInterfaces.ValidatedBatch import vinyldns.api.domain.batch.BatchTransformations.LogicalChangeType.LogicalChangeType import vinyldns.api.domain.dns.DnsConversions.getIPv6FullReverseName import vinyldns.core.domain.batch._ -import vinyldns.core.domain.record.{RecordData, RecordSet, RecordSetChange} +import vinyldns.core.domain.record.{AAAAData, RecordData, RecordSet, RecordSetChange} import vinyldns.core.domain.record.RecordType._ import vinyldns.core.domain.zone.Zone import vinyldns.core.domain.record.RecordType.RecordType @@ -182,6 +183,14 @@ object BatchTransformations { } object ValidationChanges { + def matchRecordData(existingRecord: RecordData, recordData: String): Boolean = + existingRecord match { + case AAAAData(address) => + InetAddress.getByName(address).getHostName == + InetAddress.getByName(recordData).getHostName + case _ => false + } + def apply( changes: List[ChangeForValidation], existingRecordSet: Option[RecordSet] @@ -197,6 +206,12 @@ object BatchTransformations { // existing DNS entries in the event of DeleteRecordSet val deleteChangeSet = changes .collect { + case DeleteRRSetChangeForValidation( + _, + _, + DeleteRRSetChangeInput(_, AAAA, Some(AAAAData(address))) + ) => + existingRecords.filter(r => matchRecordData(r, address)) case DeleteRRSetChangeForValidation( _, _, diff --git a/modules/api/src/test/scala/vinyldns/api/domain/batch/BatchChangeValidationsSpec.scala b/modules/api/src/test/scala/vinyldns/api/domain/batch/BatchChangeValidationsSpec.scala index b8ccd5f7e..94dd113e2 100644 --- a/modules/api/src/test/scala/vinyldns/api/domain/batch/BatchChangeValidationsSpec.scala +++ b/modules/api/src/test/scala/vinyldns/api/domain/batch/BatchChangeValidationsSpec.scala @@ -138,6 +138,12 @@ class BatchChangeValidationsSpec DeleteRRSetChangeInput("shared-update", RecordType.AAAA) ) + private val deleteSingleRecordChange = DeleteRRSetChangeForValidation( + sharedZone, + "shared-update", + DeleteRRSetChangeInput("shared-update", RecordType.AAAA, Some(AAAAData("1:0::1"))) + ) + private val deletePrivateChange = DeleteRRSetChangeForValidation( okZone, "private-delete", @@ -2279,7 +2285,7 @@ class BatchChangeValidationsSpec ChangeForValidationMap( List( updateSharedAddChange.validNel, - updateSharedDeleteChange.validNel, + deleteSingleRecordChange.validNel, deleteSharedChange.validNel, updatePrivateAddChange.validNel, updatePrivateDeleteChange.validNel,