Skip to content

Commit

Permalink
tools/unitctl: implement application subcommand
Browse files Browse the repository at this point in the history
* application subcommand UI schema
* application subcommand handler
* additions to unit-client-rs to expose application API
* elaborate on OpenAPI error handling
* adds wasm and wasi app schemas to OpenAPI Schema
* updates tools/unitctl OpenAPI library
* many linter fixes
* README.md updates

Signed-off-by: Ava Hahn <a.hahn@f5.com>
  • Loading branch information
avahahn committed Jun 18, 2024
1 parent d96d583 commit e0c15ae
Show file tree
Hide file tree
Showing 15 changed files with 335 additions and 137 deletions.
85 changes: 84 additions & 1 deletion docs/unit-openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4730,6 +4730,9 @@ components:
isolation:
rootfs: "/www/"

wasiapp:
type: "wasm-wasi-component"

# /config/listeners
configListeners:
summary: "Multiple listeners"
Expand Down Expand Up @@ -5304,6 +5307,8 @@ components:
- $ref: "#/components/schemas/configApplicationPHP"
- $ref: "#/components/schemas/configApplicationPython"
- $ref: "#/components/schemas/configApplicationRuby"
- $ref: "#/components/schemas/configApplicationWasm"
- $ref: "#/components/schemas/configApplicationWasi"

discriminator:
propertyName: type
Expand All @@ -5314,6 +5319,8 @@ components:
php: "#/components/schemas/configApplicationPHP"
python: "#/components/schemas/configApplicationPython"
ruby: "#/components/schemas/configApplicationRuby"
wasm: "#/components/schemas/configApplicationWasm"
wasm-wasi-component: "#/components/schemas/configApplicationWasi"

# ABSTRACT BASE SCHEMA, NOT PRESENT IN THE CONFIGURATION; STORES COMMON OPTIONS
configApplicationCommon:
Expand All @@ -5326,7 +5333,7 @@ components:
type:
type: string
description: "Application type and language version."
enum: [external, java, perl, php, python, ruby]
enum: [external, java, perl, php, python, ruby, wasm, wasm-wasi-component]

environment:
type: object
Expand Down Expand Up @@ -5592,6 +5599,82 @@ components:
description: "Number of worker threads per app process."
default: 1

configApplicationWasm:
description: "WASM application on Unit."
allOf:
- $ref: "#/components/schemas/configApplicationCommon"
- type: object
required:
- module
- request_handler
- malloc_handler
- free_handler

properties:
module:
type: string
description: "Path to WebAssembly module."

request_handler:
type: string
description: "Name of request handling function."

malloc_handler:
type: string
description: "Name of memory allocator function."

free_handler:
type: string
description: "Name of memory free function."

access:
type: object
properties:
filesystem:
$ref: "#/components/schemas/stringArray"
description: "Host directories this application may have access to."

module_init_handler:
type: string
description: "Name of function called to initialize module."

module_end_handler:
type: string
description: "Name of function called to teardown module."

request_init_handler:
type: string
description: "Name of function called to initialize request."

request_end_handler:
type: string
description: "Name of function called to teardown request."

response_end_handler:
type: string
description: "Name of function called to teardown response."


configApplicationWasi:
description: "WASI application on Unit."
allOf:
- $ref: "#/components/schemas/configApplicationCommon"
- type: object
required:
- component

properties:
component:
type: string
description: "Path to wasm wasi component application."

This comment has been minimized.

Copy link
@ac000

ac000 Jun 18, 2024

Member

I guess this should hyphenated to match it's module name...


access:
type: object
properties:
filesystem:
$ref: "#/components/schemas/stringArray"
description: "Host directories this application may have access to."

configApplicationPHP:
description: "PHP application on Unit."
allOf:
Expand Down
4 changes: 2 additions & 2 deletions tools/unitctl/GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ CARGO ?= cargo
DOCKER ?= docker
DOCKER_BUILD_FLAGS ?= --load
CHECKSUM ?= sha256sum
OPENAPI_GENERATOR_VERSION ?= 6.6.0
OPENAPI_GENERATOR_VERSION ?= 7.6.0

# Define platform targets based off of the current host OS
# If running MacOS, then build for MacOS platform targets installed in rustup
Expand Down Expand Up @@ -137,7 +137,7 @@ openapi-clean: ## Clean up generated OpenAPI files
$Q find "$(CURDIR)/unit-openapi/src/apis" \
! -name 'error.rs' -type f -exec rm -f {} +
$Q $(info $(M) cleaning up generated OpenAPI models code)
$Q rm -rf "$(CURDIR)/unit-openapi/src/models/*"
$Q rm -rf "$(CURDIR)/unit-openapi/src/models"

include $(CURDIR)/build/package.mk
include $(CURDIR)/build/container.mk
Expand Down
26 changes: 23 additions & 3 deletions tools/unitctl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ their own makefile targets. Alternatively, all available binary targets can be
built with `make all`. See the below example for illustration:

```
[ava@calliope cli]$ make list-targets
$ make list-targets
x86_64-unknown-linux-gnu
[ava@calliope cli]$ make x86_64-unknown-linux-gnu
$ make x86_64-unknown-linux-gnu
▶ building unitctl with flags [--quiet --release --bin unitctl --target x86_64-unknown-linux-gnu]
[ava@calliope cli]$ file ./target/x86_64-unknown-linux-gnu/release/unitctl
$ file ./target/x86_64-unknown-linux-gnu/release/unitctl
./target/x86_64-unknown-linux-gnu/release/unitctl: ELF 64-bit LSB pie executable,
x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2,
BuildID[sha1]=ef4b094ffd549b39a8cb27a7ba2cc0dbad87a3bc, for GNU/Linux 4.4.0,
Expand Down Expand Up @@ -91,6 +91,26 @@ To the subcommand `unitctl instances new` the user must provide three things:

After deployment the user will have one Unit container running on the host network.

### Lists active applications and provides means to restart them
Listing applications:
```
$ unitctl app list
{
"wasm": {
"type": "wasm-wasi-component",
"component": "/www/wasmapp-proxy-component.wasm"
}
}
```

Restarting an application:
```
$ unitctl app reload wasm
{
"success": "Ok"
}
```

### Lists active listeners from running Unit processes
```
unitctl listeners
Expand Down
2 changes: 0 additions & 2 deletions tools/unitctl/unit-client-rs/src/control_socket_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ impl ControlSocketScheme {
}
}


impl Display for ControlSocket {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Expand Down Expand Up @@ -312,7 +311,6 @@ impl ControlSocket {
}
}


#[cfg(test)]
mod tests {
use rand::distributions::{Alphanumeric, DistString};
Expand Down
48 changes: 45 additions & 3 deletions tools/unitctl/unit-client-rs/src/unit_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@ use serde::{Deserialize, Serialize};

use crate::control_socket_address::ControlSocket;
use unit_openapi::apis::configuration::Configuration;
use unit_openapi::apis::{Error as OpenAPIError, StatusApi};
use unit_openapi::apis::{ListenersApi, ListenersApiClient, StatusApiClient};
use unit_openapi::models::{ConfigListener, Status};
use unit_openapi::apis::{
ApplicationsApi, ApplicationsApiClient, AppsApi, AppsApiClient, Error as OpenAPIError, ListenersApi,
ListenersApiClient, StatusApi, StatusApiClient,
};
use unit_openapi::models::{ConfigApplication, ConfigListener, Status};

const USER_AGENT: &str = concat!("UNIT CLI/", env!("CARGO_PKG_VERSION"), "/rust");

Expand Down Expand Up @@ -276,6 +278,46 @@ impl UnitClient {
})
}

pub fn applications_api(&self) -> Box<dyn ApplicationsApi + 'static> {
new_openapi_client!(self, ApplicationsApiClient, ApplicationsApi)
}

pub async fn applications(&self) -> Result<HashMap<String, ConfigApplication>, Box<UnitClientError>> {
self.applications_api().get_applications().await.or_else(|err| {
if let OpenAPIError::Hyper(hyper_error) = err {
Err(Box::new(UnitClientError::new(
hyper_error,
self.control_socket.to_string(),
"/applications".to_string(),
)))
} else {
Err(Box::new(UnitClientError::OpenAPIError { source: err }))
}
})
}

pub async fn per_application_api(&self) -> Box<dyn AppsApi + 'static> {
new_openapi_client!(self, AppsApiClient, AppsApi)
}

pub async fn restart_application(&self, name: &String) -> Result<HashMap<String, String>, Box<UnitClientError>> {
self.per_application_api()
.await
.get_app_restart(name.as_str())
.await
.or_else(|err| {
if let OpenAPIError::Hyper(hyper_error) = err {
Err(Box::new(UnitClientError::new(
hyper_error,
self.control_socket.to_string(),
format!("/control/applications/{}/restart", name),
)))
} else {
Err(Box::new(UnitClientError::OpenAPIError { source: err }))
}
})
}

pub async fn is_running(&self) -> bool {
self.status().await.is_ok()
}
Expand Down
Loading

0 comments on commit e0c15ae

Please sign in to comment.