Skip to content

Commit 91e00cc

Browse files
committed
Create spin-trigger-new crate
This will replace spin-trigger in a future commit. Signed-off-by: Lann Martin <lann.martin@fermyon.com>
1 parent c225bee commit 91e00cc

File tree

9 files changed

+928
-3
lines changed

9 files changed

+928
-3
lines changed

Cargo.lock

Lines changed: 40 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ members = [
8383
"crates/templates",
8484
"crates/testing",
8585
"crates/trigger",
86+
"crates/trigger-new",
8687
"examples/spin-timer",
8788
"sdk/rust",
8889
"sdk/rust/macro"

crates/manifest/src/lib.rs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@
22
33
#![deny(missing_docs)]
44

5-
use indexmap::IndexMap;
6-
use serde::{Deserialize, Serialize};
75
use std::{
86
collections::HashMap,
97
fmt::{Debug, Formatter},
108
path::PathBuf,
119
};
1210

11+
use indexmap::IndexMap;
12+
use serde::{Deserialize, Serialize};
13+
1314
/// A trigger error.
1415
#[derive(Debug, thiserror::Error)]
1516
pub enum Error {
@@ -222,6 +223,15 @@ impl AllowedHttpHost {
222223
}
223224
}
224225

226+
impl From<AllowedHttpHost> for String {
227+
fn from(allowed: AllowedHttpHost) -> Self {
228+
match allowed.port {
229+
Some(port) => format!("{}:{}", allowed.domain, port),
230+
None => allowed.domain,
231+
}
232+
}
233+
}
234+
225235
/// WebAssembly configuration.
226236
#[derive(Clone, Debug, Default)]
227237
pub struct WasmConfig {

crates/trigger-new/Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "spin-trigger-new"
3+
version = "0.2.0"
4+
edition = "2021"
5+
authors = ["Fermyon Engineering <engineering@fermyon.com>"]
6+
7+
[dependencies]
8+
anyhow = "1.0"
9+
async-trait = "0.1"
10+
clap = { version = "3.1.15", features = ["derive", "env"] }
11+
ctrlc = { version = "3.2", features = ["termination"] }
12+
dirs = "4"
13+
futures = "0.3"
14+
outbound-http = { path = "../outbound-http" }
15+
outbound-redis = { path = "../outbound-redis" }
16+
outbound-pg = { path = "../outbound-pg" }
17+
sanitize-filename = "0.4"
18+
serde = "1.0"
19+
serde_json = "1.0"
20+
spin-app = { path = "../app" }
21+
spin-config = { path = "../config" }
22+
spin-core = { path = "../core" }
23+
spin-loader = { path = "../loader" }
24+
spin-manifest = { path = "../manifest" }
25+
tracing = { version = "0.1", features = [ "log" ] }
26+
url = "2"
27+
wasmtime = "0.39.1"
28+
29+
[dev-dependencies]
30+
tempfile = "3.3.0"
31+
toml = "0.5"
32+
tokio = { version = "1.0", features = ["rt", "macros"] }

crates/trigger-new/src/cli.rs

Lines changed: 156 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
use std::path::PathBuf;
2+
3+
use anyhow::{Context, Result};
4+
use clap::{Args, IntoApp, Parser};
5+
use serde::de::DeserializeOwned;
6+
7+
use crate::{stdio::FollowComponents, loader::TriggerLoader};
8+
use crate::{TriggerExecutor, TriggerExecutorBuilder};
9+
10+
pub const APP_LOG_DIR: &str = "APP_LOG_DIR";
11+
pub const DISABLE_WASMTIME_CACHE: &str = "DISABLE_WASMTIME_CACHE";
12+
pub const FOLLOW_LOG_OPT: &str = "FOLLOW_ID";
13+
pub const WASMTIME_CACHE_FILE: &str = "WASMTIME_CACHE_FILE";
14+
15+
// Set by `spin up`
16+
pub const SPIN_LOCKED_URL: &str = "SPIN_LOCKED_URL";
17+
pub const SPIN_WORKING_DIR: &str = "SPIN_WORKING_DIR";
18+
19+
/// A command that runs a TriggerExecutor.
20+
#[derive(Parser, Debug)]
21+
#[clap(next_help_heading = "TRIGGER OPTIONS")]
22+
pub struct TriggerExecutorCommand<Executor: TriggerExecutor>
23+
where
24+
Executor::RunConfig: Args,
25+
{
26+
/// Log directory for the stdout and stderr of components.
27+
#[clap(
28+
name = APP_LOG_DIR,
29+
short = 'L',
30+
long = "log-dir",
31+
)]
32+
pub log: Option<PathBuf>,
33+
34+
/// Disable Wasmtime cache.
35+
#[clap(
36+
name = DISABLE_WASMTIME_CACHE,
37+
long = "disable-cache",
38+
env = DISABLE_WASMTIME_CACHE,
39+
conflicts_with = WASMTIME_CACHE_FILE,
40+
takes_value = false,
41+
)]
42+
pub disable_cache: bool,
43+
44+
/// Wasmtime cache configuration file.
45+
#[clap(
46+
name = WASMTIME_CACHE_FILE,
47+
long = "cache",
48+
env = WASMTIME_CACHE_FILE,
49+
conflicts_with = DISABLE_WASMTIME_CACHE,
50+
)]
51+
pub cache: Option<PathBuf>,
52+
53+
/// Print output for given component(s) to stdout/stderr
54+
#[clap(
55+
name = FOLLOW_LOG_OPT,
56+
long = "follow",
57+
multiple_occurrences = true,
58+
)]
59+
pub follow_components: Vec<String>,
60+
61+
/// Print all component output to stdout/stderr
62+
#[clap(
63+
long = "follow-all",
64+
conflicts_with = FOLLOW_LOG_OPT,
65+
)]
66+
pub follow_all_components: bool,
67+
68+
/// Set the static assets of the components in the temporary directory as writable.
69+
#[clap(long = "allow-transient-write")]
70+
pub allow_transient_write: bool,
71+
72+
#[clap(flatten)]
73+
pub run_config: Executor::RunConfig,
74+
75+
#[clap(long = "help-args-only", hide = true)]
76+
pub help_args_only: bool,
77+
}
78+
79+
/// An empty implementation of clap::Args to be used as TriggerExecutor::RunConfig
80+
/// for executors that do not need additional CLI args.
81+
#[derive(Args)]
82+
pub struct NoArgs;
83+
84+
impl<Executor: TriggerExecutor> TriggerExecutorCommand<Executor>
85+
where
86+
Executor::RunConfig: Args,
87+
Executor::TriggerConfig: DeserializeOwned,
88+
{
89+
/// Create a new TriggerExecutorBuilder from this TriggerExecutorCommand.
90+
pub async fn run(self) -> Result<()> {
91+
if self.help_args_only {
92+
Self::command()
93+
.disable_help_flag(true)
94+
.help_template("{all-args}")
95+
.print_long_help()?;
96+
return Ok(());
97+
}
98+
99+
// Required env vars
100+
let working_dir = std::env::var(SPIN_WORKING_DIR).context(SPIN_WORKING_DIR)?;
101+
let locked_url = std::env::var(SPIN_LOCKED_URL).context(SPIN_LOCKED_URL)?;
102+
103+
let loader = TriggerLoader::new(working_dir, self.allow_transient_write);
104+
105+
let executor: Executor = {
106+
let mut builder = TriggerExecutorBuilder::new(loader);
107+
self.update_wasmtime_config(builder.wasmtime_config_mut())?;
108+
builder.follow_components(self.follow_components());
109+
if let Some(log_dir) = self.log {
110+
builder.log_dir(log_dir);
111+
}
112+
builder.build(locked_url).await?
113+
};
114+
115+
let run_fut = executor.run(self.run_config);
116+
117+
let (abortable, abort_handle) = futures::future::abortable(run_fut);
118+
ctrlc::set_handler(move || abort_handle.abort())?;
119+
match abortable.await {
120+
Ok(Ok(())) => {
121+
tracing::info!("Trigger executor shut down: exiting");
122+
Ok(())
123+
}
124+
Ok(Err(err)) => {
125+
tracing::error!("Trigger executor failed: {:?}", err);
126+
Err(err)
127+
}
128+
Err(_aborted) => {
129+
tracing::info!("User requested shutdown: exiting");
130+
Ok(())
131+
}
132+
}
133+
}
134+
135+
pub fn follow_components(&self) -> FollowComponents {
136+
if self.follow_all_components {
137+
FollowComponents::All
138+
} else if self.follow_components.is_empty() {
139+
FollowComponents::None
140+
} else {
141+
let followed = self.follow_components.clone().into_iter().collect();
142+
FollowComponents::Named(followed)
143+
}
144+
}
145+
146+
fn update_wasmtime_config(&self, config: &mut spin_core::wasmtime::Config) -> Result<()> {
147+
// Apply --cache / --disable-cache
148+
if !self.disable_cache {
149+
match &self.cache {
150+
Some(p) => config.cache_config_load(p)?,
151+
None => config.cache_config_load_default()?,
152+
};
153+
}
154+
Ok(())
155+
}
156+
}

0 commit comments

Comments
 (0)