// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use error::{Error, Result};
use std::process::Command;

pub fn ip(path: Option<&str>) -> Result<String> {
    debug!("Shelling out to determine IP address");
    let mut cmd = Command::new("sh");
    cmd.arg("-c").arg("ip route get 8.8.8.8 | awk '{printf \"%s\", $NF; exit}'");
    if let Some(path) = path {
        cmd.env("PATH", path);
        debug!("Setting shell out PATH={}", path);
    }
    let output = try!(cmd.output());
    match output.status.success() {
        true => {
            debug!("IP address is {}", String::from_utf8_lossy(&output.stdout));
            let ip = try!(String::from_utf8(output.stdout));
            Ok(ip)
        }
        false => {
            debug!("IP address command returned: OUT: {} ERR: {}",
                   String::from_utf8_lossy(&output.stdout),
                   String::from_utf8_lossy(&output.stderr));
            Err(Error::NoOutboundAddr)
        }
    }
}

// Copyright:: Copyright (c) 2015-2016 The Habitat Maintainers
//
// The terms of the Evaluation Agreement (Habitat) between Chef Software Inc.
// and the party accessing this file ("Licensee") apply to Licensee's use of
// the Software until such time that the Software is made available under an
// open source license such as the Apache 2.0 License.

use error::{Error, Result};
use std::process::Command;

pub fn ip() -> Result<String> {
    debug!("Shelling out to determine IP address");
    let output = try!(Command::new("sh")
        .arg("-c")
        .arg("ip route get 8.8.8.8 | awk '{printf \"%s\", $NF; exit}'")
        .output());
    match output.status.success() {
        true => {
            debug!("IP address is {}", String::from_utf8_lossy(&output.stdout));
            let ip = try!(String::from_utf8(output.stdout));
            Ok(ip)
        }
        false => {
            debug!("IP address command returned: OUT: {} ERR: {}",
                   String::from_utf8_lossy(&output.stdout),
                   String::from_utf8_lossy(&output.stderr));
            Err(Error::NoOutboundAddr)
        }
    }
}

--- 
+++ 
@@ -8,12 +8,15 @@
 use error::{Error, Result};
 use std::process::Command;
 
-pub fn ip() -> Result<String> {
+pub fn ip(path: Option<&str>) -> Result<String> {
     debug!("Shelling out to determine IP address");
-    let output = try!(Command::new("sh")
-        .arg("-c")
-        .arg("ip route get 8.8.8.8 | awk '{printf \"%s\", $NF; exit}'")
-        .output());
+    let mut cmd = Command::new("sh");
+    cmd.arg("-c").arg("ip route get 8.8.8.8 | awk '{printf \"%s\", $NF; exit}'");
+    if let Some(path) = path {
+        cmd.env("PATH", path);
+        debug!("Setting shell out PATH={}", path);
+    }
+    let output = try!(cmd.output());
     match output.status.success() {
         true => {
             debug!("IP address is {}", String::from_utf8_lossy(&output.stdout));
[sup,core] Set optional PATH when shelling out for ip & hostname.

This fixes an issue we are seeing in the Supervisor when the default
bind address is being determined. In minimal environments (such as in a
Studio, in a Docker container, etc) the `ip` and `hostname` commands may
not be found in the `PATH` passed to `hap-sup` on start. The supervisor
does have a runtime dependency on `core/busybox-static` and that
package's `PATH` is added to the process' `PATH` just before the
supervised service is started. The issue here was that the command line
parsing/default logic happens way before the service package is
installed and started.

In an effort to keep things reasonably generic (as these are `util::sys`
functions), the `ip()` and `hostname()` functions optionally take a
`PATH` value as a `&str` which, if present, is set as the spawned
command's `PATH`. We set a `PATH` for the command line parsing call by
using the already-present `busybox_paths()` utility function, and we use
the existing `PATH` of the process for all other calls as they happen
after the `PATH`-setting logic has executed in `command::start`.

For example, running the following in the devshell will ensure that the
Ubuntu `iproute2` package's `/sbin/ip` and `/bin/ip` will *not* be found
or used:

```
> rm -f /sbin/ip /bin/ip

> hash -r

> command -v ip || echo 'all gone'
all gone

> env RUST_LOG=err,habitat_core::util::sys=debug hab-sup start core/redis
DEBUG:habitat_core::util::sys: Shelling out to determine IP address
DEBUG:habitat_core::util::sys: Setting shell out PATH=/hab/pkgs/core/busybox-static/1.24.2/20160427212720/bin
DEBUG:habitat_core::util::sys: IP address is 172.17.0.2
hab-sup(MN): Starting core/redis
DEBUG:habitat_core::util::sys: Shelling out to determine IP address
DEBUG:habitat_core::util::sys: IP address is 172.17.0.2
hab-sup(GS): Supervisor 172.17.0.2: 5e09deec-3a9b-4ccc-8a1f-d7c2d9f70266
hab-sup(GS): Census redis.default: da58e70a-53a6-4419-a627-ee1d3b6e78d7
hab-sup(GS): Starting inbound gossip listener
hab-sup(GS): Starting outbound gossip distributor
hab-sup(GS): Starting gossip failure detector
hab-sup(CN): Starting census health adjuster
DEBUG:habitat_core::util::sys: Shelling out to determine IP address
DEBUG:habitat_core::util::sys: IP address is 172.17.0.2
hab-sup(SC): Updated redis.config
hab-sup(TP): Restarting because the service config was updated via the census
redis(SV): Starting
-- snip --
```

Signed-off-by: Fletcher Nichol <fnichol@nichol.ca>

Pull request: #617
Approved by: fnichol
