Skip to content

Commit

Permalink
Add FQDN to EventCore Metadata
Browse files Browse the repository at this point in the history
From the [`hostname` man page](https://www.systutorials.com/docs/linux/man/1-hostname/):
>The FQDN (Fully Qualified Domain Name) of the system is the
name that the resolver(3) returns for the host name, such as,
**ursula.example.com**.  It is usually the hostname followed by the
DNS domain name (the part  after the first dot).  You can check
the FQDN using `hostname --fqdn` or the domain name using
`dnsdomainname`.

As the man page says it, the FQDN is the combination of the
Hostname and the Domain Name. But technically speaking:
>The FQDN is the name getaddrinfo(3) returns for the
host name returned by gethostname(2). The DNS domain name
is the part after the first dot.

This change is adding two new `core::os::net` functions:
- `lookup_fqdn(hostname)`: returns a vector of fqdn that resolves
the provided hostname.
- `fqdn()`: returns the FQDN (fully qualified domain name) of the
running machine.

These functions are leveraging the [dns-lookup crate](https://docs.rs/dns-lookup/1.0.0/dns_lookup/index.html) that implements
the C function called `getaddrinfo()` that we technically need to get
FQDN of the running machine.

Habitat already have a function that returns the hostname of the
machine[ called `hostname()`](https://github.com/habitat-sh/habitat/blob/master/components/core/src/os/net/windows.rs#L22), we are leveraging that function inside
the new `fqdn()` one.

I have created an issue #6531 to explore the possibility of refactoring the
existing `hostname()` function in favor of `dns_lookup::lookup_host()`

Signed-off-by: Salim Afiune <afiune@chef.io>
  • Loading branch information
Salim Afiune authored and christophermaier committed May 17, 2019
1 parent ab059a6 commit 87a92a7
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 6 deletions.
12 changes: 12 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions components/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ cc = "*"
[dependencies]
base64 = "*"
dirs = "*"
dns-lookup = "*"
errno = "*"
hex = "*"
lazy_static = "*"
Expand Down
58 changes: 58 additions & 0 deletions components/core/src/os/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,61 @@ mod imp;
mod imp;

pub use self::imp::*;

use std::io;

/// Returns the fqdn from the provided hostname.
pub fn lookup_fqdn(hostname: &str) -> io::Result<String> {
#[cfg(not(windows))]
let flags = libc::AI_CANONNAME;

#[cfg(windows)]
let flags = winapi::shared::ws2def::AI_CANONNAME;

let hints = dns_lookup::AddrInfoHints { flags,
..dns_lookup::AddrInfoHints::default() };

// If 'hints.flags' includes the AI_CANONNAME flag, then the ai_canonname
// field of the first of the addrinfo structures in the returned list is set
// to point to the official name of the host.
if let Some(first_result) = dns_lookup::getaddrinfo(Some(hostname), None, Some(hints))?.next() {
match first_result {
Ok(f) => Ok(f.canonname.expect("Some(canonname) if requested")),
Err(e) => {
debug!("lookup_fqdn() was unable to lookup the machine fqdn. {:?}",
e);
Ok(hostname.to_string())
}
}
} else {
Ok(hostname.to_string())
}
}

/// Returns the fully qualified domain name of the running machine.
pub fn fqdn() -> Option<String> {
let result = dns_lookup::get_hostname().and_then(|hostname| lookup_fqdn(&hostname));
if let Err(ref e) = result {
debug!("fqdn() was unable to lookup the machine fqdn. {:?}", e);
}
result.ok()
}

#[cfg(not(windows))]
#[test]
fn test_fqdn_lookup() {
let fqdn = lookup_fqdn("localhost");
assert!(fqdn.is_ok());
assert_eq!(fqdn.unwrap(),
String::from("localhost"),
"the fqdn of localhost should be localhost");
}

#[cfg(not(windows))]
#[test]
fn test_fqdn_lookup_err() {
let fqdn = lookup_fqdn("");
assert!(fqdn.is_err(), "Should be an Err()");
assert_eq!(format!("{}", fqdn.unwrap_err()),
"failed to lookup address information: Name or service not known");
}
1 change: 1 addition & 0 deletions components/sup/protocols/event.proto
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ message EventMetadata {
string application = 4;
string environment = 5;
map<string, string> meta = 6;
string fqdn = 7;
}

message ServiceMetadata {
Expand Down
12 changes: 7 additions & 5 deletions components/sup/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,18 +140,20 @@ pub struct EventCore {
/// The unique identifier of the Supervisor sending the event.
supervisor_id: String,
ip_address: SocketAddr,
fqdn: String,
application: String,
environment: String,
meta: EventStreamMetadata,
}

impl EventCore {
pub fn new(config: &EventStreamConfig, sys: &Sys) -> Self {
pub fn new(config: &EventStreamConfig, sys: &Sys, fqdn: String) -> Self {
EventCore { supervisor_id: sys.member_id.clone(),
ip_address: sys.gossip_listen(),
environment: config.environment.clone(),
application: config.application.clone(),
meta: config.meta.clone(), }
ip_address: sys.gossip_listen(),
fqdn,
environment: config.environment.clone(),
application: config.application.clone(),
meta: config.meta.clone() }
}
}

Expand Down
1 change: 1 addition & 0 deletions components/sup/src/event/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ impl EventCore {
// occurred_at will be set to Some when the event is published.
EventMetadata { supervisor_id: self.supervisor_id.clone(),
ip_address: self.ip_address.to_string(),
fqdn: self.fqdn.clone(),
application: self.application.clone(),
environment: self.environment.clone(),
occurred_at: None,
Expand Down
7 changes: 6 additions & 1 deletion components/sup/src/manager/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,12 @@ impl Manager {
let es_config =
cfg.event_stream_config
.expect("Config should be present if the EventStream feature is enabled");
let ec = EventCore::new(&es_config, &sys);

// Collect the FQDN of the running machine
let fqdn = habitat_core::os::net::fqdn().unwrap_or_else(|| sys.hostname.clone());
outputln!("Event FQDN {}", fqdn);

let ec = EventCore::new(&es_config, &sys, fqdn);
// unwrap won't fail here; if there were an issue, from_env()
// would have already propagated an error up the stack.
event::init_stream(es_config, ec)?;
Expand Down

0 comments on commit 87a92a7

Please sign in to comment.