summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock2
-rw-r--r--angelsharkd/Cargo.toml3
-rw-r--r--angelsharkd/src/routes/extensions/mod.rs8
-rw-r--r--angelsharkd/src/routes/extensions/simple_busy/README.md50
-rw-r--r--angelsharkd/src/routes/extensions/simple_busy/mod.rs98
-rw-r--r--angelsharkd/src/routes/extensions/simple_deprov/README.md2
-rw-r--r--angelsharkd/src/routes/extensions/simple_deprov/mod.rs15
7 files changed, 173 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index cd177a2..2120e3f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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)],
})