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 /angelsharkd/src | |
| parent | d3e1b697fec543e0197f1c549164c210504dde3b (diff) | |
| parent | 579980ca75dfbc27639259c773dfc5fe1ec9e32a (diff) | |
| download | altruistic-angelshark-6e307700a5203f5b9fcc741f693fcacc7757414d.tar.xz altruistic-angelshark-6e307700a5203f5b9fcc741f693fcacc7757414d.zip | |
feat: support station busyout/release toggling via extension
Diffstat (limited to 'angelsharkd/src')
5 files changed, 170 insertions, 3 deletions
| 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)],          }) |