diff --git a/components/common/src/types/mod.rs b/components/common/src/types/mod.rs index 860c0dc7e64..155ddf265e5 100644 --- a/components/common/src/types/mod.rs +++ b/components/common/src/types/mod.rs @@ -132,9 +132,7 @@ impl AutomateAuthToken { /// of a token. #[allow(clippy::needless_pass_by_value)] // Signature required by CLAP pub fn validate(value: String) -> result::Result<(), String> { - value.parse::() - .map(|_| ()) - .map_err(|_| "This should be impossible".to_string()) + value.parse::().map(|_| ()).map_err(|e| e.to_string()) } /// Create an instance of `AutomateAuthToken` from validated diff --git a/components/hab/src/cli.rs b/components/hab/src/cli.rs index 5c927e33783..9e05bfa14d2 100644 --- a/components/hab/src/cli.rs +++ b/components/hab/src/cli.rs @@ -1201,23 +1201,40 @@ fn maybe_add_event_stream_options(mut app: App<'static, 'static>, .required(true) .takes_value(true) .validator(non_empty)); - app = app.arg(Arg::with_name(AutomateAuthToken::ARG_NAME).help("An authentication token for \ - streaming events to an \ - Automate server.") - .long("event-stream-token") - .required(true) - .takes_value(true) - .validator(AutomateAuthToken::validate) - .env(AutomateAuthToken::ENVVAR)); - app = - app.arg(Arg::with_name(EventStreamMetadata::ARG_NAME).help("An arbitrary key-value pair \ - to add to each event \ - generated by this Supervisor") - .long("event-meta") - .takes_value(true) - .multiple(true) - .validator(EventStreamMetadata::validate) - .required(false)); + app = app.arg(Arg::with_name("EVENT_STREAM_URL").help("The event stream connection \ + string (host:port) used by this \ + Supervisor to send events to a \ + messaging server.") + .long("event-stream-url") + .required(true) + .takes_value(true) + .validator(non_empty)); + app = app.arg( + Arg::with_name(AutomateAuthToken::ARG_NAME) + .help( + "An authentication token for \ + streaming events to an \ + messaging server.", + ) + .long("event-stream-token") + .required(true) + .takes_value(true) + .validator(AutomateAuthToken::validate) + .env(AutomateAuthToken::ENVVAR), + ); + app = app.arg( + Arg::with_name(EventStreamMetadata::ARG_NAME) + .help( + "An arbitrary key-value pair \ + to add to each event \ + generated by this Supervisor", + ) + .long("event-meta") + .takes_value(true) + .multiple(true) + .validator(EventStreamMetadata::validate) + .required(false), + ); } app @@ -1430,7 +1447,7 @@ mod tests { } #[test] - fn run_requries_app_and_env_and_token() { + fn run_requires_app_and_env_and_token_and_url() { let matches = sub_sup_run(event_stream_enabled()).get_matches_from_safe(vec!["run"]); assert!(matches.is_err()); assert_eq!(matches.unwrap_err().kind, @@ -1444,12 +1461,14 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_ok()); } #[test] - fn app_and_env_and_token_options_require_event_stream_feature() { + fn app_and_env_and_token_and_url_options_require_event_stream_feature() { let matches = sub_sup_run(no_feature_flags()).get_matches_from_safe(vec![ "run", "--event-stream-application", @@ -1458,6 +1477,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1475,6 +1496,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1493,6 +1516,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1508,6 +1533,8 @@ mod tests { "--event-stream-environment", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1526,6 +1553,8 @@ mod tests { "", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1544,6 +1573,8 @@ mod tests { "MY_TOKEN", "--event-stream-environment", "MY_ENV", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); @@ -1567,6 +1598,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_ok()); let matches = matches.unwrap(); @@ -1587,6 +1620,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); assert_eq!(matches.unwrap_err().kind, clap::ErrorKind::EmptyValue); @@ -1604,6 +1639,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); assert_eq!(matches.unwrap_err().kind, clap::ErrorKind::ValueValidation); @@ -1621,6 +1658,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); assert_eq!(matches.unwrap_err().kind, clap::ErrorKind::ValueValidation); @@ -1638,6 +1677,8 @@ mod tests { "MY_ENV", "--event-stream-token", "MY_TOKEN", + "--event-stream-url", + "127.0.0.1:4222", ]); assert!(matches.is_err()); assert_eq!(matches.unwrap_err().kind, clap::ErrorKind::ValueValidation); @@ -1651,6 +1692,8 @@ mod tests { "MY_APP", "--event-stream-environment", "MY_ENV", + "--event-stream-url", + "127.0.0.1:4222", "--event-stream-token", ]); assert!(matches.is_err()); @@ -1670,6 +1713,44 @@ mod tests { "MY_ENV", "--event-stream-token", "", + "--event-stream-url", + "127.0.0.1:4222", + ]); + assert!(matches.is_err()); + let error = matches.unwrap_err(); + assert_eq!(error.kind, clap::ErrorKind::ValueValidation); + } + + #[test] + fn url_option_must_take_a_value() { + let matches = sub_sup_run(event_stream_enabled()).get_matches_from_safe(vec![ + "run", + "--event-stream-application", + "MY_APP", + "--event-stream-environment", + "MY_ENV", + "--event-stream-token", + "MY_TOKEN", + "--event-stream-url", + ]); + assert!(matches.is_err()); + let error = matches.unwrap_err(); + assert_eq!(error.kind, clap::ErrorKind::EmptyValue); + assert_eq!(error.info, Some(vec!["EVENT_STREAM_URL".to_string()])); + } + + #[test] + fn url_option_cannot_be_empty() { + let matches = sub_sup_run(event_stream_enabled()).get_matches_from_safe(vec![ + "run", + "--event-stream-application", + "MY_APP", + "--event-stream-environment", + "MY_ENV", + "--event-stream-token", + "MY_TOKEN", + "--event-stream-url", + "", ]); assert!(matches.is_err()); let error = matches.unwrap_err(); diff --git a/components/sup/src/event.rs b/components/sup/src/event.rs index cfa9acb1d27..4bd9cb2528b 100644 --- a/components/sup/src/event.rs +++ b/components/sup/src/event.rs @@ -73,7 +73,7 @@ lazy_static! { /// static reference for access later. pub fn init_stream(config: EventStreamConfig, event_core: EventCore) { INIT.call_once(|| { - let conn_info = EventConnectionInfo::new(config.token); + let conn_info = EventConnectionInfo::new(config.token, config.url); let event_stream = init_nats_stream(conn_info).expect("Could not start NATS thread"); EVENT_STREAM.set(event_stream); EVENT_CORE.set(event_core); @@ -88,6 +88,7 @@ pub struct EventStreamConfig { application: String, meta: EventStreamMetadata, token: AutomateAuthToken, + url: String, } impl EventStreamConfig { @@ -100,7 +101,10 @@ impl EventStreamConfig { .map(str::to_string) .expect("Required option for EventStream feature"), meta: EventStreamMetadata::from_matches(m)?, - token: AutomateAuthToken::from_matches(m)?, }) + token: AutomateAuthToken::from_matches(m)?, + url: m.value_of("EVENT_STREAM_URL") + .map(str::to_string) + .expect("Required option for EventStream feature"), }) } } @@ -117,10 +121,10 @@ pub struct EventConnectionInfo { } impl EventConnectionInfo { - pub fn new(auth_token: AutomateAuthToken) -> Self { + pub fn new(auth_token: AutomateAuthToken, cluster_uri: String) -> Self { EventConnectionInfo { name: String::from("habitat"), verbose: true, - cluster_uri: String::from("10.0.0.174:4222"), + cluster_uri, cluster_id: String::from("event-service"), auth_token } }