Skip to content

Commit

Permalink
Merge pull request #7 from adpllc/dev
Browse files Browse the repository at this point in the history
feat: support station busyout/release toggling via extension
  • Loading branch information
Adam Carpenter authored Jan 17, 2022
2 parents d3e1b69 + 579980c commit 6e30770
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 5 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion angelsharkd/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
[package]
name = "angelsharkd"
version = "0.2.1"
version = "0.2.2"
edition = "2021"
authors = ["Adam T. Carpenter <[email protected]>"]
description = "A HTTP interface into one or more Communication Managers"

[features]
simple_search = []
simple_deprov = []
simple_busy = []

[dependencies.libangelshark]
path = "../libangelshark"
Expand Down
8 changes: 8 additions & 0 deletions angelsharkd/src/routes/extensions/mod.rs
Original file line number Diff line number Diff line change
@@ -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")]
Expand All @@ -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)
}

Expand Down
50 changes: 50 additions & 0 deletions angelsharkd/src/routes/extensions/simple_busy/README.md
Original file line number Diff line number Diff line change
@@ -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.
98 changes: 98 additions & 0 deletions angelsharkd/src/routes/extensions/simple_busy/mod.rs
Original file line number Diff line number Diff line change
@@ -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,
}
2 changes: 1 addition & 1 deletion angelsharkd/src/routes/extensions/simple_deprov/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
15 changes: 13 additions & 2 deletions angelsharkd/src/routes/extensions/simple_deprov/mod.rs
Original file line number Diff line number Diff line change
@@ -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::{
Expand All @@ -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)),
Expand All @@ -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)],
})
Expand Down

0 comments on commit 6e30770

Please sign in to comment.