diff options
author | Adam Carpenter <adam.carpenter@adp.com> | 2022-01-17 15:02:00 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-01-17 15:02:00 -0500 |
commit | 6e307700a5203f5b9fcc741f693fcacc7757414d (patch) | |
tree | fe7781e07a74e05a82ea3c1e19c389337fe8ac8c | |
parent | d3e1b697fec543e0197f1c549164c210504dde3b (diff) | |
parent | 579980ca75dfbc27639259c773dfc5fe1ec9e32a (diff) | |
download | altruistic-angelshark-master.tar.xz altruistic-angelshark-master.zip |
feat: support station busyout/release toggling via extension
-rw-r--r-- | Cargo.lock | 2 | ||||
-rw-r--r-- | angelsharkd/Cargo.toml | 3 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/mod.rs | 8 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_busy/README.md | 50 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_busy/mod.rs | 98 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_deprov/README.md | 2 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_deprov/mod.rs | 15 |
7 files changed, 173 insertions, 5 deletions
@@ -24,7 +24,7 @@ dependencies = [ [[package]] name = "angelsharkd" -version = "0.2.1" +version = "0.2.2" dependencies = [ "anyhow", "env_logger", diff --git a/angelsharkd/Cargo.toml b/angelsharkd/Cargo.toml index 0bb1294..62ffebb 100644 --- a/angelsharkd/Cargo.toml +++ b/angelsharkd/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "angelsharkd" -version = "0.2.1" +version = "0.2.2" edition = "2021" authors = ["Adam T. Carpenter <adam.carpenter@adp.com>"] description = "A HTTP interface into one or more Communication Managers" @@ -8,6 +8,7 @@ description = "A HTTP interface into one or more Communication Managers" [features] simple_search = [] simple_deprov = [] +simple_busy = [] [dependencies.libangelshark] path = "../libangelshark" diff --git a/angelsharkd/src/routes/extensions/mod.rs b/angelsharkd/src/routes/extensions/mod.rs index 54053af..a775880 100644 --- a/angelsharkd/src/routes/extensions/mod.rs +++ b/angelsharkd/src/routes/extensions/mod.rs @@ -1,6 +1,8 @@ use crate::config::Config; use warp::{path, Filter, Rejection, Reply}; +#[cfg(feature = "simple_busy")] +mod simple_busy; #[cfg(feature = "simple_deprov")] mod simple_deprov; #[cfg(feature = "simple_search")] @@ -26,6 +28,12 @@ pub fn filter(config: &Config) -> impl Filter<Extract = impl Reply, Error = Reje #[cfg(feature = "simple_deprov")] let filters = filters.or(simple_deprov::filter(config.runner.clone())); + #[cfg(feature = "simple_busy")] + let filters = filters + .or(simple_busy::busy_filter(config.runner.to_owned())) + .or(simple_busy::release_filter(config.runner.to_owned())) + .or(simple_busy::toggle_filter(config.runner.to_owned())); + path("extensions").and(filters) } diff --git a/angelsharkd/src/routes/extensions/simple_busy/README.md b/angelsharkd/src/routes/extensions/simple_busy/README.md new file mode 100644 index 0000000..dd9ba2c --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_busy/README.md @@ -0,0 +1,50 @@ +# Daemon Extension `simple_busy` + +This extension implements simple extension busyout and release toggling. + +## Getting Started + +To enable this feature, compile `angelsharkd` with the `simple_busy` flag: + +```sh +cargo build --bin angelsharkd --features simple_busy ... +``` + +## `POST /extensions/service/busyout` Busy-out a station + +The request consists of one or more entries including the ACM and extension to +be operated on. + +```json +POST /extensions/service/toggle +[ + { + "acm": "01", + "ext": "17571230000" + } +] +``` + +The response is a typical `angelsharkd` OSSI reponse. + +```json +[ + { + "acm": "01", + "command": "busyout station 17571230000", + "error": "", + "fields": ["0001ff00", "0002ff00", "0005ff00", "0003ff00", "0004ff00"], + "datas": [["S075157", "DIG-IP-S", "17571230000", "ABORT", "1010"]] + } +] +``` + +## `POST /extensions/service/release` Release a station + +This endpoint works identically to the busyout endpoint, but the response will +indicate whether the station was released. + +## `POST /extensions/service/toggle` Busyout and then immediately release a station + +This endpoint runs two OSSI commands for busyout-ing and releasing the given +stations, respectively. diff --git a/angelsharkd/src/routes/extensions/simple_busy/mod.rs b/angelsharkd/src/routes/extensions/simple_busy/mod.rs new file mode 100644 index 0000000..23f05fd --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_busy/mod.rs @@ -0,0 +1,98 @@ +use crate::routes::dtos::{Error, Response}; +use libangelshark::{AcmRunner, Message, ParallelIterator}; +use log::error; +use serde::Deserialize; +use warp::{ + body::{content_length_limit, json}, + hyper::StatusCode, + path, post, reply, Filter, Rejection, Reply, +}; + +const SIXTEEN_K: u64 = 1024 * 16; + +pub fn busy_filter( + runner: AcmRunner, +) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { + post() + .and(path!("service" / "busyout" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "busyout", runner.to_owned())) +} + +pub fn release_filter( + runner: AcmRunner, +) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { + post() + .and(path!("service" / "release" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "release", runner.to_owned())) +} + +pub fn toggle_filter( + runner: AcmRunner, +) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { + post() + .and(path!("service" / "toggle" / ..)) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .map(move |entries| queue_and_run(entries, "toggle", runner.to_owned())) +} + +fn queue_and_run(entries: Entries, command: &str, mut runner: AcmRunner) -> impl Reply { + for entry in entries.into_iter() { + if command == "toggle" { + runner.queue_input( + &entry.acm, + &Message::new(&format!("busyout station {}", entry.ext)), + ); + runner.queue_input( + &entry.acm, + &Message::new(&format!("release station {}", entry.ext)), + ); + } else { + runner.queue_input( + &entry.acm, + &Message::new(&format!("{} station {}", command, entry.ext)), + ); + } + } + + // generate output on runner + let output: Result<Vec<Vec<_>>, _> = runner + .run() + .map(|(name, output)| -> Result<Vec<Response>, anyhow::Error> { + Ok(output? + .into_iter() + .filter_map(move |msg| { + (msg.command != "logoff").then(|| Response::from((name.to_owned(), msg))) + }) + .collect()) + }) + .collect(); + + // handle errors and package output as json + match output { + Err(e) => { + error!("busyout-release extension: {}", e); + reply::with_status( + reply::json(&Error { + reason: e.to_string(), + }), + StatusCode::INTERNAL_SERVER_ERROR, + ) + } + Ok(r) => reply::with_status( + reply::json(&r.into_iter().flatten().collect::<Vec<_>>()), + StatusCode::OK, + ), + } +} + +type Entries = Vec<Entry>; +#[derive(Debug, Deserialize)] +struct Entry { + acm: String, + ext: String, +} diff --git a/angelsharkd/src/routes/extensions/simple_deprov/README.md b/angelsharkd/src/routes/extensions/simple_deprov/README.md index 4900075..f7a3fe2 100644 --- a/angelsharkd/src/routes/extensions/simple_deprov/README.md +++ b/angelsharkd/src/routes/extensions/simple_deprov/README.md @@ -16,7 +16,7 @@ cargo build --bin angelsharkd --features simple_deprov ... ## `POST /extensions/deprov` Remove Objects -The request type is TODO: +The request type is as follows: ```json POST /extensions/deprov diff --git a/angelsharkd/src/routes/extensions/simple_deprov/mod.rs b/angelsharkd/src/routes/extensions/simple_deprov/mod.rs index fc734f3..77bde55 100644 --- a/angelsharkd/src/routes/extensions/simple_deprov/mod.rs +++ b/angelsharkd/src/routes/extensions/simple_deprov/mod.rs @@ -1,5 +1,5 @@ use libangelshark::{AcmRunner, Message, ParallelIterator}; -use log::error; +use log::{error, info}; use serde::Deserialize; use std::convert::Infallible; use warp::{ @@ -24,10 +24,12 @@ async fn remove_entries(entries: Entries, mut runner: AcmRunner) -> Result<impl for entry in entries { match entry { Entry::StationUser { acm, ext } => { + runner.queue_input(&acm, &Message::new(&format!("list station {}", ext))); runner.queue_input(&acm, &Message::new(&format!("clear amw all {}", ext))); runner.queue_input(&acm, &Message::new(&format!("remove station {}", ext))); } Entry::AgentLoginId { acm, ext } => { + runner.queue_input(&acm, &Message::new(&format!("list agent-loginID {}", ext))); runner.queue_input( &acm, &Message::new(&format!("remove agent-loginID {}", ext)), @@ -42,7 +44,16 @@ async fn remove_entries(entries: Entries, mut runner: AcmRunner) -> Result<impl .map(|(acm, output)| match output { Ok(messages) => messages .into_iter() - .filter_map(|message| Some(format!("ACM {}: {}", acm.clone(), message.error?))) + .filter_map(|message| { + if let Some(data) = message + .datas + .and_then(|d| Some(format!("{acm}\t{}", d.get(0)?.join("\t")))) + { + // if there was data (such as in lists), print it out + info!("{data}"); + } + Some(format!("ACM {}: {}", acm.clone(), message.error?)) + }) .collect(), Err(error) => vec![format!("ACM {}: {}", acm, error)], }) |