diff options
Diffstat (limited to 'angelsharkd/src/routes/extensions/simple_deprov')
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_deprov/README.md | 61 | ||||
-rw-r--r-- | angelsharkd/src/routes/extensions/simple_deprov/mod.rs | 70 |
2 files changed, 131 insertions, 0 deletions
diff --git a/angelsharkd/src/routes/extensions/simple_deprov/README.md b/angelsharkd/src/routes/extensions/simple_deprov/README.md new file mode 100644 index 0000000..4900075 --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_deprov/README.md @@ -0,0 +1,61 @@ +# Daemon Extension `simple_deprov` + +This extension implements excruciatingly simple extension de-provisioning. For +example, if an agent was provisioned with a `station-user` and an +`agent-loginid`, you can submit those extensions, their type, and the ACM they +were provision on. They relevant commands to remove those objects will be +executed in parallel, and any errors encountered will be returned. + +## Getting Started + +To enable this feature, compile `angelsharkd` with the `simple_deprov` flag: + +```sh +cargo build --bin angelsharkd --features simple_deprov ... +``` + +## `POST /extensions/deprov` Remove Objects + +The request type is TODO: + +```json +POST /extensions/deprov +[ + { + "station-user": { + "acm": "01", + "ext": "17571230000" + } + }, + { + "agent-loginid": { + "acm": "01", + "ext": "17571240000" + } + } +] +``` + +If all of the deprov commands were successful, the response is an empty array. + +```json +200 OK +[] +``` + +If there were errors running the relevant deprov commands (such as when an +extension does not exist), they are included in the resulting array. + +```json +200 OK +[ + "ACM lab: 1 00000000 309e Extension exists but assigned to a different object", + "ACM lab: 1 00000000 2ed5 Extension assigned as remote extension on the uniform-dialplan form", + "ACM lab: 1 00000000 2ed5 Extension assigned as remote extension on the uniform-dialplan form" +] +``` + +## Logging + +The `deprov` endpoint always returns successfully. Any errors encountered during +the command execution are logged as `ERROR`. diff --git a/angelsharkd/src/routes/extensions/simple_deprov/mod.rs b/angelsharkd/src/routes/extensions/simple_deprov/mod.rs new file mode 100644 index 0000000..fc734f3 --- /dev/null +++ b/angelsharkd/src/routes/extensions/simple_deprov/mod.rs @@ -0,0 +1,70 @@ +use libangelshark::{AcmRunner, Message, ParallelIterator}; +use log::error; +use serde::Deserialize; +use std::convert::Infallible; +use warp::{ + body::{content_length_limit, json}, + post, reply, Filter, Rejection, Reply, +}; + +const SIXTEEN_K: u64 = 1024 * 16; + +/// Returns a warp filter to handle HTTP POSTs for deprovisioning stations, agents, etc. +pub fn filter(runner: AcmRunner) -> impl Filter<Extract = impl Reply, Error = Rejection> + Clone { + warp::path("deprov") + .and(post()) + .and(content_length_limit(SIXTEEN_K)) + .and(json()) + .and_then(move |entries| remove_entries(entries, runner.to_owned())) +} + +/// Queues removal commands for [Entries] on an [AcmRunner]. Gathers any errors encountered and returns those. +async fn remove_entries(entries: Entries, mut runner: AcmRunner) -> Result<impl Reply, Infallible> { + // Construct OSSI messages to carry out removals. + for entry in entries { + match entry { + Entry::StationUser { acm, 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!("remove agent-loginID {}", ext)), + ); + } + } + } + + // Gather any errors encountered and format them for the client response. + let errors: Vec<String> = runner + .run_cached() + .map(|(acm, output)| match output { + Ok(messages) => messages + .into_iter() + .filter_map(|message| Some(format!("ACM {}: {}", acm.clone(), message.error?))) + .collect(), + Err(error) => vec![format!("ACM {}: {}", acm, error)], + }) + .flatten() + .collect(); + + // Log errors for tracking. + for error in &errors { + error!("{}", error); + } + + Ok(reply::json(&errors)) +} + +/// Collection of [Entry]. +type Entries = Vec<Entry>; + +/// Very basic [Deserialize] target for deprov inputs. Going from stringly typed to strongly typed. +#[derive(Debug, Deserialize)] +enum Entry { + #[serde(rename(deserialize = "station-user"))] + StationUser { acm: String, ext: String }, + #[serde(rename(deserialize = "agent-loginid"))] + AgentLoginId { acm: String, ext: String }, +} |