Added DNS Records for Zone actions

This commit is contained in:
2024-11-11 10:23:19 +01:00
parent e561ad8ee7
commit 815c9e3e9d
38 changed files with 5581 additions and 69 deletions

View File

@@ -0,0 +1,600 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using AMWD.Net.Api.Cloudflare.Zones.Internals.Requests;
namespace AMWD.Net.Api.Cloudflare.Zones
{
/// <summary>
/// Extends the <see cref="ICloudflareClient"/> with methods for working with zones.
/// </summary>
public static class DnsRecordsExtensions
{
private static readonly IReadOnlyCollection<DnsRecordType> _dataComponentTypes = [
DnsRecordType.Caa,
DnsRecordType.Cert,
DnsRecordType.DnsKey,
DnsRecordType.Ds,
DnsRecordType.Https,
DnsRecordType.Loc,
DnsRecordType.NaPtr,
DnsRecordType.SMimeA,
DnsRecordType.Srv,
DnsRecordType.SshFp,
DnsRecordType.SvcB,
DnsRecordType.TlsA,
DnsRecordType.Uri,
];
private static readonly IReadOnlyCollection<DnsRecordType> _priorityTypes = [
DnsRecordType.Mx,
DnsRecordType.Srv,
DnsRecordType.Uri,
];
/// <summary>
/// List, search, sort, and filter a zones' DNS records.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="zoneId">The zone ID.</param>
/// <param name="options">Filter options (optional).</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<IReadOnlyList<DnsRecord>>> ListDnsRecords(this ICloudflareClient client, string zoneId, ListDnsRecordsFilter? options = null, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.GetAsync<IReadOnlyList<DnsRecord>>($"zones/{zoneId}/dns_records", options, cancellationToken);
}
/// <summary>
/// Create a new DNS record for a zone.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
/// <item>NS records cannot exist on the same name as any other record type.</item>
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
/// </list>
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="request">The request information.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<DnsRecord>> CreateDnsRecord(this ICloudflareClient client, CreateDnsRecordRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
var req = ValidateDnsRecordRequest(request);
return client.PostAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records", req, cancellationToken: cancellationToken);
}
/// <summary>
/// Send a Batch of DNS Record API calls to be executed together.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>
/// Although Cloudflare will execute the batched operations in a single database transaction,
/// Cloudflare's distributed KV store must treat each record change as a single key-value pair.
/// This means that the propagation of changes is not atomic.
/// See <see href="https://developers.cloudflare.com/dns/manage-dns-records/how-to/batch-record-changes/">the documentation</see> for more information.
/// </item>
/// <item>
/// The operations you specify within the batch request body are always executed in the following order
/// <list type="number">
/// <item>Deletes (delete)</item>
/// <item>Updates (patch)</item>
/// <item>Overwrites (put)</item>
/// <item>Creates (post)</item>
/// </list>
/// </item>
/// </list>
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="request">The request information.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<BatchDnsRecordsResult>> BatchDnsRecords(this ICloudflareClient client, BatchDnsRecordsRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
// Validate Deletes
var deletes = new List<InternalDnsRecordId>();
foreach (string recordId in request.DnsRecordIdsToDelete)
{
recordId.ValidateCloudflareId();
deletes.Add(new InternalDnsRecordId { Id = recordId });
}
// Validate Updates
var updates = new List<InternalBatchUpdateRequest>();
foreach (var update in request.DnsRecordsToUpdate)
{
update.Id.ValidateCloudflareId();
if (update.ZoneId != request.ZoneId)
throw new ArgumentException($"The ZoneId of the update request ({update.ZoneId}) does not match the ZoneId of the batch request ({request.ZoneId}).");
var baseReq = ValidateDnsRecordRequest(update);
updates.Add(new InternalBatchUpdateRequest(update.Id, baseReq));
}
// Validate Overwrites
var overwrites = new List<InternalBatchUpdateRequest>();
foreach (var overwrite in request.DnsRecordsToOverwrite)
{
overwrite.Id.ValidateCloudflareId();
if (overwrite.ZoneId != request.ZoneId)
throw new ArgumentException($"The ZoneId of the overwrite request ({overwrite.ZoneId}) does not match the ZoneId of the batch request ({request.ZoneId}).");
var baseReq = ValidateDnsRecordRequest(overwrite);
overwrites.Add(new InternalBatchUpdateRequest(overwrite.Id, baseReq));
}
// Validate Creates
var creates = new List<InternalDnsRecordRequest>();
foreach (var create in request.DnsRecordsToCreate)
creates.Add(ValidateDnsRecordRequest(create));
var req = new InternalBatchRequest();
if (deletes.Count > 0)
req.Deletes = deletes;
if (updates.Count > 0)
req.Patches = updates;
if (overwrites.Count > 0)
req.Puts = overwrites;
if (creates.Count > 0)
req.Posts = creates;
return client.PostAsync<BatchDnsRecordsResult, InternalBatchRequest>($"zones/{request.ZoneId}/dns_records/batch", req, cancellationToken: cancellationToken);
}
/// <summary>
/// You can export your <see href="https://en.wikipedia.org/wiki/Zone_file">BIND config</see> through this endpoint.
/// </summary>
/// <remarks>
/// See <see href="https://developers.cloudflare.com/dns/manage-dns-records/how-to/import-and-export/">the documentation</see> for more information.
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="zoneId">The zone ID.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<string>> ExportDnsRecords(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.GetAsync<string>($"zones/{zoneId}/dns_records/export", cancellationToken: cancellationToken);
}
/// <summary>
/// You can upload your BIND config through this endpoint.
/// </summary>
/// <remarks>
/// See the documentation for more information.
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="request">The request information.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<ImportDnsRecordsResult>> ImportDnsRecords(this ICloudflareClient client, ImportDnsRecordsRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
if (string.IsNullOrWhiteSpace(request.File))
throw new ArgumentNullException(nameof(request.File));
var req = new MultipartFormDataContent();
if (request.Proxied.HasValue)
req.Add(new StringContent(request.Proxied.Value.ToString().ToLowerInvariant()), "proxied");
byte[] content = File.Exists(request.File)
? File.ReadAllBytes(request.File)
: Encoding.UTF8.GetBytes(request.File);
req.Add(new ByteArrayContent(content), "file");
return client.PostAsync<ImportDnsRecordsResult, MultipartFormDataContent>($"zones/{request.ZoneId}/dns_records/import", req, cancellationToken: cancellationToken);
}
/// <summary>
/// Scan for common DNS records on your domain and automatically add them to your zone.
/// <br/>
/// Useful if you haven't updated your nameservers yet.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="zoneId">The zone ID.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<ImportDnsRecordsResult>> ScanDnsRecords(this ICloudflareClient client, string zoneId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
return client.PostAsync<ImportDnsRecordsResult, object>($"zones/{zoneId}/dns_records/scan", null, cancellationToken: cancellationToken);
}
/// <summary>
/// Deletes a DNS record.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="zoneId">The zone ID.</param>
/// <param name="dnsRecordId">The record ID.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<IdResponse>> DeleteDnsRecord(this ICloudflareClient client, string zoneId, string dnsRecordId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
dnsRecordId.ValidateCloudflareId();
return client.DeleteAsync<IdResponse>($"zones/{zoneId}/dns_records/{dnsRecordId}", cancellationToken: cancellationToken);
}
/// <summary>
/// Returns details for a DNS record.
/// </summary>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="zoneId">The zone ID.</param>
/// <param name="dnsRecordId">The record ID.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<DnsRecord>> DnsRecordDetails(this ICloudflareClient client, string zoneId, string dnsRecordId, CancellationToken cancellationToken = default)
{
zoneId.ValidateCloudflareId();
dnsRecordId.ValidateCloudflareId();
return client.GetAsync<DnsRecord>($"zones/{zoneId}/dns_records/{dnsRecordId}", cancellationToken: cancellationToken);
}
/// <summary>
/// Update an existing DNS record.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
/// <item>NS records cannot exist on the same name as any other record type.</item>
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
/// </list>
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="request">The request information.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<DnsRecord>> UpdateDnsRecord(this ICloudflareClient client, UpdateDnsRecordRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
request.Id.ValidateCloudflareId();
var req = ValidateDnsRecordRequest(request);
return client.PatchAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records/{request.Id}", req, cancellationToken: cancellationToken);
}
/// <summary>
/// Overwrite an existing DNS record.
/// </summary>
/// <remarks>
/// <list type="bullet">
/// <item>A/AAAA records cannot exist on the same name as CNAME records.</item>
/// <item>NS records cannot exist on the same name as any other record type.</item>
/// <item>Domain names are always represented in Punycode, even if Unicode characters were used when creating the record.</item>
/// </list>
/// </remarks>
/// <param name="client">The <see cref="ICloudflareClient"/>.</param>
/// <param name="request">The request information.</param>
/// <param name="cancellationToken">A cancellation token used to propagate notification that this operation should be canceled.</param>
public static Task<CloudflareResponse<DnsRecord>> OverwriteDnsRecord(this ICloudflareClient client, OverwriteDnsRecordRequest request, CancellationToken cancellationToken = default)
{
request.ZoneId.ValidateCloudflareId();
request.Id.ValidateCloudflareId();
var req = ValidateDnsRecordRequest(request);
return client.PutAsync<DnsRecord, InternalDnsRecordRequest>($"zones/{request.ZoneId}/dns_records/{request.Id}", req, cancellationToken: cancellationToken);
}
private static InternalDnsRecordRequest ValidateDnsRecordRequest(CreateDnsRecordRequest request)
{
if (string.IsNullOrWhiteSpace(request.Name))
throw new ArgumentNullException(nameof(request.Name));
if (!Enum.IsDefined(typeof(DnsRecordType), request.Type))
throw new ArgumentOutOfRangeException(nameof(request.Type), request.Type, "Value must be one of the 'ZoneDnsRecordType' enum values.");
var req = new InternalDnsRecordRequest(request.Type, request.Name)
{
Comment = request.Comment?.Trim(),
Proxied = request.Proxied,
Tags = request.Tags?.Where(t => !string.IsNullOrWhiteSpace(t)).ToList()
};
if (!_dataComponentTypes.Contains(request.Type) && string.IsNullOrWhiteSpace(request.Content))
throw new ArgumentNullException(nameof(request.Content));
else
req.Content = request.Content?.Trim();
if (request.Type == DnsRecordType.Cname && request.Settings != null && request.Settings is DnsRecord.CnameSettings cnameSettings)
req.Settings = new DnsRecord.CnameSettings(cnameSettings.FlattenCname);
if (_dataComponentTypes.Contains(request.Type) && request.Data == null)
throw new ArgumentNullException(nameof(request.Data));
if (_priorityTypes.Contains(request.Type))
{
if (!request.Priority.HasValue)
throw new ArgumentNullException(nameof(request.Priority));
req.Priority = request.Priority.Value;
}
if (request.Ttl.HasValue)
{
if (request.Ttl == 1)
{
req.Ttl = 1;
}
else if (request.Ttl < 30 || 86400 < request.Ttl)
{
throw new ArgumentOutOfRangeException(nameof(request.Ttl), request.Ttl, "Value must be between 60 (Enterprise: 30) and 86400.");
}
else
{
req.Ttl = request.Ttl;
}
}
switch (request.Type)
{
case DnsRecordType.Caa:
if (request.Data is DnsRecord.CaaData caaData)
{
if (string.IsNullOrWhiteSpace(caaData.Tag))
throw new ArgumentNullException(nameof(caaData.Tag));
if (string.IsNullOrWhiteSpace(caaData.Value))
throw new ArgumentNullException(nameof(caaData.Value));
req.Data = new DnsRecord.CaaData(caaData.Flags, caaData.Tag, caaData.Value);
}
else
{
throw new ArgumentException("Value must be of type 'CaaData'.", nameof(request.Data));
}
break;
case DnsRecordType.Cert:
if (request.Data is DnsRecord.CertData certData)
{
if (string.IsNullOrWhiteSpace(certData.Certificate))
throw new ArgumentNullException(nameof(certData.Certificate));
req.Data = new DnsRecord.CertData(certData.Algorithm, certData.Certificate, certData.KeyTag, certData.Type);
}
else
{
throw new ArgumentException("Value must be of type 'CertData'.", nameof(request.Data));
}
break;
case DnsRecordType.DnsKey:
if (request.Data is DnsRecord.DnsKeyData dnsKeyData)
{
if (string.IsNullOrWhiteSpace(dnsKeyData.PublicKey))
throw new ArgumentNullException(nameof(dnsKeyData.PublicKey));
req.Data = new DnsRecord.DnsKeyData(dnsKeyData.Algorithm, dnsKeyData.Flags, dnsKeyData.Protocol, dnsKeyData.PublicKey);
}
else
{
throw new ArgumentException("Value must be of type 'DnsKeyData'.", nameof(request.Data));
}
break;
case DnsRecordType.Ds:
if (request.Data is DnsRecord.DsData dsData)
{
if (string.IsNullOrWhiteSpace(dsData.Digest))
throw new ArgumentNullException(nameof(dsData.Digest));
req.Data = new DnsRecord.DsData(dsData.Algorithm, dsData.Digest, dsData.DigestType, dsData.KeyTag);
}
else
{
throw new ArgumentException("Value must be of type 'DsData'.", nameof(request.Data));
}
break;
case DnsRecordType.Https:
if (request.Data is DnsRecord.HttpsData httpsData)
{
if (string.IsNullOrWhiteSpace(httpsData.Target))
throw new ArgumentNullException(nameof(httpsData.Target));
if (string.IsNullOrWhiteSpace(httpsData.Value))
throw new ArgumentNullException(nameof(httpsData.Value));
req.Data = new DnsRecord.HttpsData(httpsData.Priority, httpsData.Target, httpsData.Value);
}
else
{
throw new ArgumentException("Value must be of type 'HttpsData'.", nameof(request.Data));
}
break;
case DnsRecordType.Loc:
if (request.Data is DnsRecord.LocData locData)
{
if (locData.LatitudeDegrees < 0 || 90 < locData.LatitudeDegrees)
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeDegrees), locData.LatitudeDegrees, "Value must be between 0 and 90.");
if (locData.LatitudeMinutes < 0 || 59 < locData.LatitudeMinutes)
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeMinutes), locData.LatitudeMinutes, "Value must be between 0 and 59.");
if (locData.LatitudeSeconds < 0 || 59.999 < locData.LatitudeSeconds)
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeSeconds), locData.LatitudeSeconds, "Value must be between 0 and 59.999.");
if (!Enum.IsDefined(typeof(DnsRecord.LatitudeDirection), locData.LatitudeDirection))
throw new ArgumentOutOfRangeException(nameof(locData.LatitudeDirection), locData.LatitudeDirection, "Value must be one of the 'ZoneDnsRecord.LatitudeDirection' enum values.");
if (locData.LongitudeDegrees < 0 || 180 < locData.LongitudeDegrees)
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeDegrees), locData.LongitudeDegrees, "Value must be between 0 and 180.");
if (locData.LongitudeMinutes < 0 || 59 < locData.LongitudeMinutes)
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeMinutes), locData.LongitudeMinutes, "Value must be between 0 and 59.");
if (locData.LongitudeSeconds < 0 || 59.999 < locData.LongitudeSeconds)
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeSeconds), locData.LongitudeSeconds, "Value must be between 0 and 59.999.");
if (!Enum.IsDefined(typeof(DnsRecord.LongitudeDirection), locData.LongitudeDirection))
throw new ArgumentOutOfRangeException(nameof(locData.LongitudeDirection), locData.LongitudeDirection, "Value must be one of the 'ZoneDnsRecord.LongitudeDirection' enum values.");
if (locData.Altitude < -100_000 || 42_849_672.95 < locData.Altitude)
throw new ArgumentOutOfRangeException(nameof(locData.Altitude), locData.Altitude, "Value must be between -100,000.00 and 42,849,672.95.");
if (locData.Size < 0 || 90_000_000 < locData.Size)
throw new ArgumentOutOfRangeException(nameof(locData.Size), locData.Size, "Value must be between 0 and 90,000,000.");
if (locData.PrecisionHorizontal < 0 || 90_000_000 < locData.PrecisionHorizontal)
throw new ArgumentOutOfRangeException(nameof(locData.PrecisionHorizontal), locData.PrecisionHorizontal, "Value must be between 0 and 90,000,000.");
if (locData.PrecisionVertical < 0 || 90_000_000 < locData.PrecisionVertical)
throw new ArgumentOutOfRangeException(nameof(locData.PrecisionVertical), locData.PrecisionVertical, "Value must be between 0 and 90,000,000.");
req.Data = new DnsRecord.LocData(
latitudeDegrees: locData.LatitudeDegrees,
latitudeMinutes: locData.LatitudeMinutes,
latitudeSeconds: Math.Floor(locData.LatitudeSeconds * 1000) / 1000, // Truncate to 3 decimal places
latitudeDirection: locData.LatitudeDirection,
longitudeDegrees: locData.LongitudeDegrees,
longitudeMinutes: locData.LongitudeMinutes,
longitudeSeconds: Math.Floor(locData.LongitudeSeconds * 1000) / 1000, // Truncate to 3 decimal places
longitudeDirection: locData.LongitudeDirection,
altitude: Math.Floor(locData.Altitude * 100) / 100, // Truncate to 2 decimal places
size: locData.Size,
precisionHorizontal: locData.PrecisionHorizontal,
precisionVertical: locData.PrecisionVertical
);
}
else
{
throw new ArgumentException("Value must be of type 'LocData'.", nameof(request.Data));
}
break;
case DnsRecordType.NaPtr:
if (request.Data is DnsRecord.NaPtrData naPtrData)
{
if (string.IsNullOrWhiteSpace(naPtrData.Flags))
throw new ArgumentNullException(nameof(naPtrData.Flags));
if (string.IsNullOrWhiteSpace(naPtrData.Regex))
throw new ArgumentNullException(nameof(naPtrData.Regex));
if (string.IsNullOrWhiteSpace(naPtrData.Replacement))
throw new ArgumentNullException(nameof(naPtrData.Replacement));
if (string.IsNullOrWhiteSpace(naPtrData.Service))
throw new ArgumentNullException(nameof(naPtrData.Service));
req.Data = new DnsRecord.NaPtrData(
naPtrData.Flags,
naPtrData.Order,
naPtrData.Preference,
naPtrData.Regex,
naPtrData.Replacement,
naPtrData.Service
);
}
else
{
throw new ArgumentException("Value must be of type 'NaPtrData'.", nameof(request.Data));
}
break;
case DnsRecordType.SMimeA:
if (request.Data is DnsRecord.SMimeAData sMimeAData)
{
if (string.IsNullOrWhiteSpace(sMimeAData.Certificate))
throw new ArgumentNullException(nameof(sMimeAData.Certificate));
req.Data = new DnsRecord.SMimeAData(sMimeAData.Certificate, sMimeAData.MatchingType, sMimeAData.Selector, sMimeAData.Usage);
}
else
{
throw new ArgumentException("Value must be of type 'SMimeAData'.", nameof(request.Data));
}
break;
case DnsRecordType.Srv:
if (request.Data is DnsRecord.SrvData srvData)
{
if (string.IsNullOrWhiteSpace(srvData.Target))
throw new ArgumentNullException(nameof(srvData.Target));
req.Data = new DnsRecord.SrvData(srvData.Port, srvData.Priority, srvData.Target, srvData.Weight);
}
else
{
throw new ArgumentException("Value must be of type 'SrvData'.", nameof(request.Data));
}
break;
case DnsRecordType.SshFp:
if (request.Data is DnsRecord.SshFpData sshFpData)
{
if (string.IsNullOrWhiteSpace(sshFpData.Fingerprint))
throw new ArgumentNullException(nameof(sshFpData.Fingerprint));
req.Data = new DnsRecord.SshFpData(sshFpData.Algorithm, sshFpData.Fingerprint, sshFpData.Type);
}
else
{
throw new ArgumentException("Value must be of type 'SshFpData'.", nameof(request.Data));
}
break;
case DnsRecordType.SvcB:
if (request.Data is DnsRecord.SvcBData svcBData)
{
if (string.IsNullOrWhiteSpace(svcBData.Target))
throw new ArgumentNullException(nameof(svcBData.Target));
if (string.IsNullOrWhiteSpace(svcBData.Value))
throw new ArgumentNullException(nameof(svcBData.Value));
req.Data = new DnsRecord.SvcBData(svcBData.Priority, svcBData.Target, svcBData.Value);
}
else
{
throw new ArgumentException("Value must be of type 'SvcBData'.", nameof(request.Data));
}
break;
case DnsRecordType.TlsA:
if (request.Data is DnsRecord.TlsAData tlsAData)
{
if (string.IsNullOrWhiteSpace(tlsAData.Certificate))
throw new ArgumentNullException(nameof(tlsAData.Certificate));
req.Data = new DnsRecord.TlsAData(tlsAData.Certificate, tlsAData.MatchingType, tlsAData.Selector, tlsAData.Usage);
}
else
{
throw new ArgumentException("Value must be of type 'TlsAData'.", nameof(request.Data));
}
break;
case DnsRecordType.Uri:
if (request.Data is DnsRecord.UriData uriData)
{
if (string.IsNullOrWhiteSpace(uriData.Target))
throw new ArgumentNullException(nameof(uriData.Target));
req.Data = new DnsRecord.UriData(uriData.Target, uriData.Weight);
}
else
{
throw new ArgumentException("Value must be of type 'UriData'.", nameof(request.Data));
}
break;
}
return req;
}
}
}