diff --git a/components/sup/Cargo.lock b/components/sup/Cargo.lock index c591c8728b..fee9985d5d 100644 --- a/components/sup/Cargo.lock +++ b/components/sup/Cargo.lock @@ -19,7 +19,6 @@ dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", "regex 0.1.65 (registry+https://github.com/rust-lang/crates.io-index)", "router 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", - "rpassword 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "temp_utp 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", "tempdir 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -528,17 +527,6 @@ dependencies = [ "route-recognizer 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "rpassword" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", - "termios 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rustc-serialize" version = "0.3.19" @@ -623,14 +611,6 @@ dependencies = [ "rand 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "termios" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "threadpool" version = "1.0.0" diff --git a/components/sup/Cargo.toml b/components/sup/Cargo.toml index 17e7b51b02..90905bbaab 100644 --- a/components/sup/Cargo.toml +++ b/components/sup/Cargo.toml @@ -29,7 +29,6 @@ iron = "*" router = "*" time = "*" temp_utp = "*" -rpassword = "*" rand = "*" threadpool = "*" urlencoded = "*" diff --git a/components/sup/src/config.rs b/components/sup/src/config.rs index 2786358e8b..d8d1315b9c 100644 --- a/components/sup/src/config.rs +++ b/components/sup/src/config.rs @@ -83,10 +83,11 @@ pub struct Config { archive: String, bind: Vec, key: String, - password: Option, email: Option, expire_days: Option, - gossip_listen: String, + gossip_listen_ip: String, + gossip_listen_port: u16, + sidecar_listen: String, userkey: Option, servicekey: Option, infile: Option, @@ -150,17 +151,6 @@ impl Config { &self.key } - /// Set the password - pub fn set_password(&mut self, password: String) -> &mut Config { - self.password = Some(password); - self - } - - /// Return the password - pub fn password(&self) -> &Option { - &self.password - } - /// Set the email address pub fn set_email(&mut self, email: String) -> &mut Config { self.email = Some(email); @@ -281,12 +271,30 @@ impl Config { &self.topology } - pub fn gossip_listen(&self) -> &str { - &self.gossip_listen + pub fn gossip_listen_ip(&self) -> &str { + &self.gossip_listen_ip + } + + pub fn set_gossip_listen_ip(&mut self, ip: String) -> &mut Config { + self.gossip_listen_ip = ip; + self + } + + pub fn gossip_listen_port(&self) -> u16 { + self.gossip_listen_port + } + + pub fn set_gossip_listen_port(&mut self, port: u16) -> &mut Config { + self.gossip_listen_port = port; + self + } + + pub fn sidecar_listen(&self) -> &str { + &self.sidecar_listen } - pub fn set_gossip_listen(&mut self, gl: String) -> &mut Config { - self.gossip_listen = gl; + pub fn set_sidecar_listen(&mut self, sl: String) -> &mut Config { + self.sidecar_listen = sl; self } diff --git a/components/sup/src/gossip/server.rs b/components/sup/src/gossip/server.rs index 018df0fc09..8d6f62b702 100644 --- a/components/sup/src/gossip/server.rs +++ b/components/sup/src/gossip/server.rs @@ -70,7 +70,8 @@ pub struct Server { impl Server { /// Creates a new Server. Creates our own entry in the census and membership lists, and writes /// a rumor that this server is alive. - pub fn new(listen: String, + pub fn new(listen_ip: String, + listen_port: u16, permanent: bool, ring_key: Option, service: String, @@ -79,12 +80,13 @@ impl Server { exposes: Option>, port: Option) -> Server { - let hostname = util::sys::hostname().unwrap_or(String::from("unknown")); - let ip = util::sys::ip().unwrap_or(String::from("127.0.0.1")); - let peer_listen = format!("{}:{}", ip, GOSSIP_DEFAULT_PORT); + let hostname = util::sys::hostname().unwrap_or(String::from("unknown")); + let listen = format!("{}:{}", listen_ip, listen_port); + let peer_listen = listen.clone(); let peer_listen2 = peer_listen.clone(); - let member = Member::new(hostname, ip, peer_listen2, permanent); + + let member = Member::new(hostname, listen_ip, peer_listen2, permanent); let service_group = format!("{}.{}", service, group); let mut ce = CensusEntry::new(service.clone(), group.clone(), member.id.clone()); diff --git a/components/sup/src/lib.rs b/components/sup/src/lib.rs index a6059956f1..b5f8c702f5 100644 --- a/components/sup/src/lib.rs +++ b/components/sup/src/lib.rs @@ -55,7 +55,6 @@ extern crate time; extern crate wonder; extern crate uuid; extern crate utp; -extern crate rpassword; extern crate rand; extern crate threadpool; extern crate urlencoded; diff --git a/components/sup/src/main.rs b/components/sup/src/main.rs index 379bdb7121..05487d197a 100644 --- a/components/sup/src/main.rs +++ b/components/sup/src/main.rs @@ -35,6 +35,8 @@ use sup::config::{Command, Config, UpdateStrategy}; use sup::error::{Error, Result, SupError}; use sup::command::*; use sup::topology::Topology; +use sup::util::parse_ip_port_with_defaults; +use sup::util::sys::ip; /// Our output key static LOGKEY: &'static str = "MN"; @@ -44,7 +46,9 @@ const VERSION: &'static str = include_str!(concat!(env!("OUT_DIR"), "/VERSION")) /// CLI defaults static DEFAULT_GROUP: &'static str = "default"; -static DEFAULT_GOSSIP_LISTEN: &'static str = "0.0.0.0:9634"; +static DEFAULT_SIDECAR_LISTEN_IP_PORT: &'static str = "0.0.0.0:9631"; + +const DEFAULT_GOSSIP_LISTEN_PORT: u16 = 9634; static RING_ENVVAR: &'static str = "HAB_RING"; static RING_KEY_ENVVAR: &'static str = "HAB_RING_KEY"; @@ -68,9 +72,6 @@ fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) if let Some(key) = sub_args.value_of("key") { config.set_key(key.to_string()); } - if let Some(password) = sub_args.value_of("password") { - config.set_password(password.to_string()); - } if let Some(email) = sub_args.value_of("email") { config.set_email(email.to_string()); } @@ -119,8 +120,19 @@ fn config_from_args(args: &ArgMatches, subcommand: &str, sub_args: &ArgMatches) .to_string_lossy() .as_ref()) .to_string()); - config.set_gossip_listen(sub_args.value_of("listen-peer") - .unwrap_or(DEFAULT_GOSSIP_LISTEN) + + let default_gossip_ip = try!(ip()); + let (gossip_ip, gossip_port) = try!(parse_ip_port_with_defaults( + sub_args.value_of("listen-peer"), + &default_gossip_ip, + DEFAULT_GOSSIP_LISTEN_PORT)); + + debug!("Gossip IP = {}", &gossip_ip); + debug!("Gossip Port = {}", &gossip_port); + config.set_gossip_listen_ip(gossip_ip); + config.set_gossip_listen_port(gossip_port); + config.set_sidecar_listen(sub_args.value_of("listen-sidecar") + .unwrap_or(DEFAULT_SIDECAR_LISTEN_IP_PORT) .to_string()); let gossip_peers = match sub_args.values_of("peer") { Some(gp) => gp.map(|s| s.to_string()).collect(), @@ -246,7 +258,11 @@ fn main() { .arg(Arg::with_name("listen-peer") .long("listen-peer") .value_name("ip:port") - .help("The listen address [default: 0.0.0.0:9634]")) + .help("The listen address [default: ip_with_default_route:9634]")) + .arg(Arg::with_name("listen-sidecar") + .long("listen-sidecar") + .value_name("ip:port") + .help("The sidecar listen address [default: 0.0.0.0:9631]")) .arg(Arg::with_name("permanent-peer") .short("I") .long("permanent-peer") diff --git a/components/sup/src/sidecar.rs b/components/sup/src/sidecar.rs index 5bbef12be2..6c967ea752 100644 --- a/components/sup/src/sidecar.rs +++ b/components/sup/src/sidecar.rs @@ -36,20 +36,21 @@ use census::{CensusList, CensusEntry, CensusEntryId, Census}; use election::{Election, ElectionList}; use supervisor::Supervisor; -static LOGKEY: &'static str = "SC"; +static LOGKEY: &'static str = "SI"; const GET_HEALTH: &'static str = "/health"; const GET_CONFIG: &'static str = "/config"; const GET_STATUS: &'static str = "/status"; const GET_GOSSIP: &'static str = "/gossip"; const GET_CENSUS: &'static str = "/census"; const GET_ELECTION: &'static str = "/election"; -const LISTEN_ADDR: &'static str = "0.0.0.0:9631"; pub type SidecarActor = wonder::actor::Actor; pub struct Sidecar; pub struct SidecarState { + /// The IP:Port where the sidecar listens + pub listen: String, /// The package this sidecar is helping out pub package: Arc>, /// The configuration of the supervised service @@ -70,7 +71,8 @@ pub enum SidecarMessage { } impl SidecarState { - pub fn new(package: Arc>, + pub fn new(listen: String, + package: Arc>, config: Arc>, member_list: Arc>, rumor_list: Arc>, @@ -81,6 +83,7 @@ impl SidecarState { gossip_file_list: Arc>) -> Self { SidecarState { + listen: listen, package: package, config: config, member_list: member_list, @@ -96,7 +99,8 @@ impl SidecarState { impl Sidecar { /// Start the sidecar. - pub fn start(package: Arc>, + pub fn start(listen: String, + package: Arc>, config: Arc>, member_list: Arc>, rumor_list: Arc>, @@ -106,7 +110,8 @@ impl Sidecar { supervisor: Arc>, gossip_file_list: Arc>) -> SidecarActor { - let state = SidecarState::new(package, + let state = SidecarState::new(listen, + package, config, member_list, rumor_list, @@ -164,7 +169,7 @@ impl GenServer for Sidecar { let el = state.election_list.clone(); router.get(GET_ELECTION, move |r: &mut Request| election(&el, r)); - match Iron::new(router).http(LISTEN_ADDR) { + match Iron::new(router).http(state.listen.as_str()) { Ok(_) => HandleResult::NoReply(None), Err(_) => { HandleResult::Stop(StopReason::Fatal("couldn't start router".to_string()), None) diff --git a/components/sup/src/topology/mod.rs b/components/sup/src/topology/mod.rs index 8e44a43a80..f03da326e9 100644 --- a/components/sup/src/topology/mod.rs +++ b/components/sup/src/topology/mod.rs @@ -147,7 +147,8 @@ impl<'a> Worker<'a> { None => None, }; - let gossip_server = gossip::server::Server::new(String::from(config.gossip_listen()), + let gossip_server = gossip::server::Server::new(String::from(config.gossip_listen_ip()), + config.gossip_listen_port(), config.gossip_permanent(), ring_key, package_name.clone(), @@ -195,7 +196,8 @@ impl<'a> Worker<'a> { member_list: gossip_server.member_list.clone(), gossip_server: gossip_server, service_config: service_config_lock, - sidecar_actor: sidecar::Sidecar::start(pkg_lock_1, + sidecar_actor: sidecar::Sidecar::start(config.sidecar_listen().to_string(), + pkg_lock_1, service_config_lock_1, sidecar_ml, sidecar_rl, diff --git a/components/sup/src/util/mod.rs b/components/sup/src/util/mod.rs index fe3e07c052..a730519a2e 100644 --- a/components/sup/src/util/mod.rs +++ b/components/sup/src/util/mod.rs @@ -10,8 +10,15 @@ pub mod path; pub mod sys; pub mod signals; +use std::net::Ipv4Addr; +use std::net::SocketAddrV4; +use std::str::FromStr; + use time; +use error::{Error, Result}; +static LOGKEY: &'static str = "UT"; + /// Gives us a time to stop for in seconds. pub fn stop_time(duration: i64) -> time::Timespec { let current_time = time::now_utc().to_timespec(); @@ -19,3 +26,56 @@ pub fn stop_time(duration: i64) -> time::Timespec { let stop_time = current_time + wait_duration; stop_time } + +/// This function takes a string as an option. +/// - If you haven't sent a string, then we'll return (default_ip, default_port). +/// - If you sent Some(some_ip_without_port), we'll return (your IP, default_port). +/// - If you sent Some(some_ip_with_port), we'll just hand that back (your IP, your port). +pub fn parse_ip_port_with_defaults(s: Option<&str>, + default_ip: &str, + default_port: u16) + -> Result<(String, u16)> { + if let None = s { + // return the default IP:Port combo + return Ok((default_ip.to_string(), default_port)); + } + + let s = s.unwrap(); + + // is it an IP + Port combo? + match SocketAddrV4::from_str(s) { + Ok(sa) => return Ok((sa.ip().to_string(), sa.port())), + Err(_) => (), + } + + // is it just an IP? if so, then append the default gossip port + if Ipv4Addr::from_str(s).is_ok() { + return Ok((s.to_string(), default_port)); + } + + return Err(sup_error!(Error::IPFailed)); +} + +#[cfg(test)] +mod tests { + use super::parse_ip_port_with_defaults; + + #[test] + fn parse_ip_port_with_defaults_test() { + let default_ip = "192.168.1.11"; + let default_port = 1234; + // no ip/port passed in, use default ip:port + assert!(("192.168.1.11".to_string(), 1234) == + parse_ip_port_with_defaults(None, default_ip, default_port).unwrap()); + // only IP passed in + assert!(("192.168.1.99".to_string(), 1234) == + parse_ip_port_with_defaults(Some("192.168.1.99"), default_ip, default_port) + .unwrap()); + // pass in IP and port + assert!(("192.168.1.99".to_string(), 5678) == + parse_ip_port_with_defaults(Some("192.168.1.99:5678"), default_ip, default_port) + .unwrap()); + // pass in something unparseable + assert!(parse_ip_port_with_defaults(Some("foo"), default_ip, default_port).is_err()); + } +} diff --git a/components/sup/src/util/sys.rs b/components/sup/src/util/sys.rs index f779f7329a..daffff0c3c 100644 --- a/components/sup/src/util/sys.rs +++ b/components/sup/src/util/sys.rs @@ -8,7 +8,7 @@ use error::{Error, Result}; use std::process::Command; -static LOGKEY: &'static str = "US"; +static LOGKEY: &'static str = "SY"; pub fn ip() -> Result { debug!("Shelling out to determine IP address"); diff --git a/components/sup/tests/bldr_build/mod.rs b/components/sup/tests/bldr_build/mod.rs index 0cbdf74f0c..e98dcaf7c3 100644 --- a/components/sup/tests/bldr_build/mod.rs +++ b/components/sup/tests/bldr_build/mod.rs @@ -9,7 +9,6 @@ use regex::Regex; use hcore::fs; use util; -use setup; #[test] fn builds_a_service() {