Skip to content

Commit 54746e3

Browse files
committed
chore(dns): address breaking changes
Signed-off-by: katelyn martin <kate@buoyant.io>
1 parent 36af455 commit 54746e3

1 file changed

Lines changed: 34 additions & 28 deletions

File tree

linkerd/dns/src/lib.rs

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,14 @@ struct InvalidSrv(rdata::SRV);
4141

4242
#[derive(Debug, Error)]
4343
#[error("failed to resolve A record: {0}")]
44-
struct ARecordError(#[from] hickory_resolver::ResolveError);
44+
struct ARecordError(#[from] hickory_resolver::net::NetError);
4545

4646
#[derive(Debug, Error)]
4747
enum SrvRecordError {
4848
#[error("{0}")]
4949
Invalid(#[from] InvalidSrv),
5050
#[error("failed to resolve SRV record: {0}")]
51-
Resolve(#[from] hickory_resolver::ResolveError),
51+
Resolve(#[from] hickory_resolver::net::NetError),
5252
}
5353

5454
#[derive(Debug, Error)]
@@ -67,32 +67,30 @@ impl Resolver {
6767
///
6868
/// Either a new `Resolver` or an error if the system configuration
6969
/// could not be parsed.
70-
///
71-
/// TODO: This should be infallible like it is in the `domain` crate.
72-
pub fn from_system_config_with<C: ConfigureResolver>(c: &C) -> std::io::Result<Self> {
70+
pub fn from_system_config_with<C: ConfigureResolver>(
71+
c: &C,
72+
) -> Result<Self, hickory_resolver::net::NetError> {
7373
let (config, mut opts) = system_conf::read_system_conf()?;
7474
c.configure_resolver(&mut opts);
7575
trace!("DNS config: {:?}", &config);
7676
trace!("DNS opts: {:?}", &opts);
77-
Ok(Self::new(config, opts))
77+
Self::new(config, opts)
7878
}
7979

80-
pub fn new(config: ResolverConfig, mut opts: ResolverOpts) -> Self {
80+
pub fn new(
81+
config: ResolverConfig,
82+
mut opts: ResolverOpts,
83+
) -> Result<Self, hickory_resolver::net::NetError> {
8184
// Disable Hickory-resolver's caching.
8285
opts.cache_size = 0;
8386
// This function is synchronous, but needs to be called within the Tokio
8487
// 0.2 runtime context, since it gets a handle.
85-
let provider = hickory_resolver::name_server::TokioConnectionProvider::default();
86-
let mut builder = hickory_resolver::Resolver::builder_with_config(config, provider);
87-
*builder.options_mut() = opts;
88-
let dns = builder.build();
89-
/* TODO(kate): this can be used if/when hickory-dns/hickory-dns#2877 is released.
88+
let provider = hickory_resolver::net::runtime::TokioRuntimeProvider::default();
9089
let dns = hickory_resolver::Resolver::builder_with_config(config, provider)
9190
.with_options(opts)
92-
.build();
93-
*/
91+
.build()?;
9492

95-
Resolver { dns, metrics: None }
93+
Ok(Resolver { dns, metrics: None })
9694
}
9795

9896
/// Installs a counter tracking the number of A/AAAA records resolved.
@@ -150,18 +148,26 @@ impl Resolver {
150148
Ok((ips, valid_until))
151149
}
152150

151+
#[allow(unused, unreachable_code, reason = "XXX(kate)")]
153152
async fn resolve_srv(
154153
&self,
155154
name: NameRef<'_>,
156155
) -> Result<(Vec<net::SocketAddr>, Instant), SrvRecordError> {
157156
debug!(%name, "Resolving a SRV record");
158157
let srv = self.dns.srv_lookup(name.as_str()).await?;
159158

160-
let valid_until = Instant::from_std(srv.as_lookup().valid_until());
159+
let valid_until = Instant::from_std(srv.valid_until());
161160
let addrs = srv
162-
.into_iter()
161+
.answers()
162+
.iter()
163+
.map(|record| &record.data)
164+
.filter_map(|rdata| match rdata {
165+
hickory_resolver::proto::rr::RData::SRV(srv) => Some(srv),
166+
_ => None,
167+
})
163168
.map(Self::srv_to_socket_addr)
164169
.collect::<Result<_, InvalidSrv>>()?;
170+
165171
debug!(ttl = ?valid_until - Instant::now(), ?addrs);
166172

167173
Ok((addrs, valid_until))
@@ -174,19 +180,19 @@ impl Resolver {
174180
// instead of dots/colons. We can alternatively do another lookup
175181
// on the pod's DNS but it seems unnecessary since the pod's
176182
// ip is in the target of the SRV record.
177-
fn srv_to_socket_addr(srv: rdata::SRV) -> Result<net::SocketAddr, InvalidSrv> {
178-
if let Some(first_label) = srv.target().iter().next() {
183+
fn srv_to_socket_addr(srv: &rdata::SRV) -> Result<net::SocketAddr, InvalidSrv> {
184+
if let Some(first_label) = srv.target.iter().next() {
179185
if let Ok(utf8) = std::str::from_utf8(first_label) {
180186
let mut res = utf8.replace('-', ".").parse::<std::net::IpAddr>();
181187
if res.is_err() {
182188
res = utf8.replace('-', ":").parse::<std::net::IpAddr>();
183189
}
184190
if let Ok(ip) = res {
185-
return Ok(net::SocketAddr::new(ip, srv.port()));
191+
return Ok(net::SocketAddr::new(ip, srv.port));
186192
}
187193
}
188194
}
189-
Err(InvalidSrv(srv))
195+
Err(InvalidSrv(srv.clone()))
190196
}
191197
}
192198

@@ -223,13 +229,13 @@ impl ResolveError {
223229
/// Returns the negative TTL [`time::Duration`] of a [`hickory_resolver::ResolveError`].
224230
///
225231
/// This function will defensively enforce a minimum negative TTL.
226-
fn negative_ttl_of(error: &hickory_resolver::ResolveError) -> Option<time::Duration> {
227-
use hickory_resolver::proto::{ProtoError, ProtoErrorKind};
232+
fn negative_ttl_of(error: &hickory_resolver::net::NetError) -> Option<time::Duration> {
233+
use hickory_resolver::net::{DnsError, NetError, NoRecords};
228234

229-
let Some(ProtoErrorKind::NoRecordsFound {
235+
let NetError::Dns(DnsError::NoRecordsFound(NoRecords {
230236
negative_ttl: Some(ttl_secs),
231237
..
232-
}) = error.proto().map(ProtoError::kind)
238+
})) = error
233239
else {
234240
return None;
235241
};
@@ -373,7 +379,7 @@ mod tests {
373379
let name = "foobar.linkerd-dst-headless.linkerd.svc.cluster.local.";
374380
let target = domain::Name::from_str(name).unwrap();
375381
let srv = rdata::SRV::new(1, 1, 8086, target);
376-
assert!(Resolver::srv_to_socket_addr(srv).is_err());
382+
assert!(Resolver::srv_to_socket_addr(&srv).is_err());
377383
}
378384

379385
#[test]
@@ -399,15 +405,15 @@ mod tests {
399405
] {
400406
let target = domain::Name::from_str(case.input).unwrap();
401407
let srv = rdata::SRV::new(1, 1, 8086, target);
402-
let socket = Resolver::srv_to_socket_addr(srv).unwrap();
408+
let socket = Resolver::srv_to_socket_addr(&srv).unwrap();
403409
assert_eq!(socket.ip(), net::IpAddr::from_str(case.output).unwrap());
404410
}
405411
}
406412

407413
#[test]
408414
fn srv_record_reports_cause_correctly() {
409415
let srv = "foobar.linkerd-dst-headless.linkerd.svc.cluster.local."
410-
.parse::<hickory_resolver::Name>()
416+
.parse::<domain::Name>()
411417
.map(|name| rdata::SRV::new(1, 1, 8086, name))
412418
.expect("a valid domain name");
413419

0 commit comments

Comments
 (0)