Skip to content

Commit 9b5a810

Browse files
committed
Update spin up to use new spin-trigger semantics
Signed-off-by: Lann Martin <[email protected]>
1 parent 1b69243 commit 9b5a810

File tree

1 file changed

+37
-39
lines changed

1 file changed

+37
-39
lines changed

src/commands/up.rs

+37-39
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use anyhow::{bail, Context, Result};
88
use clap::{CommandFactory, Parser};
99
use spin_loader::bindle::BindleConnectionInfo;
1010
use spin_manifest::ApplicationTrigger;
11+
use spin_trigger::cli::{SPIN_LOCKED_URL, SPIN_WORKING_DIR};
1112
use tempfile::TempDir;
1213

1314
use crate::opts::*;
@@ -77,21 +78,23 @@ pub struct UpCommand {
7778
)]
7879
pub insecure: bool,
7980

81+
/// Pass an environment variable (key=value) to all components of the application.
82+
#[clap(short = 'e', long = "env", parse(try_from_str = parse_env_var))]
83+
pub env: Vec<(String, String)>,
84+
8085
/// Temporary directory for the static assets of the components.
8186
#[clap(long = "temp")]
8287
pub tmp: Option<PathBuf>,
8388

84-
/// Set the static assets of the components in the temporary directory as writable.
85-
#[clap(long = "allow-transient-write")]
86-
pub allow_transient_write: bool,
87-
8889
/// All other args, to be passed through to the trigger
8990
#[clap(hide = true)]
9091
pub trigger_args: Vec<OsString>,
9192
}
9293

9394
impl UpCommand {
9495
pub async fn run(self) -> Result<()> {
96+
// For displaying help, first print `spin up`'s own usage text, then
97+
// attempt to load an app and print trigger-type-specific usage.
9598
let help = self.help;
9699
if help {
97100
Self::command()
@@ -117,49 +120,43 @@ impl UpCommand {
117120
};
118121
let working_dir = working_dir_holder.path();
119122

120-
let app = match (&self.app, &self.bindle) {
123+
let mut app = match (&self.app, &self.bindle) {
121124
(app, None) => {
122125
let manifest_file = app
123126
.as_deref()
124127
.unwrap_or_else(|| DEFAULT_MANIFEST_FILE.as_ref());
125128
let bindle_connection = self.bindle_connection();
126-
spin_loader::from_file(
127-
manifest_file,
128-
working_dir,
129-
&bindle_connection,
130-
self.allow_transient_write,
131-
)
132-
.await?
129+
spin_loader::from_file(manifest_file, working_dir, &bindle_connection).await?
133130
}
134131
(None, Some(bindle)) => match &self.server {
135-
Some(server) => {
136-
spin_loader::from_bindle(
137-
bindle,
138-
server,
139-
working_dir,
140-
self.allow_transient_write,
141-
)
142-
.await?
143-
}
132+
Some(server) => spin_loader::from_bindle(bindle, server, working_dir).await?,
144133
_ => bail!("Loading from a bindle requires a Bindle server URL"),
145134
},
146135
(Some(_), Some(_)) => bail!("Specify only one of app file or bindle ID"),
147136
};
148137

149-
let manifest_url = match app.info.origin {
150-
spin_manifest::ApplicationOrigin::File(path) => {
151-
format!("file:{}", path.canonicalize()?.to_string_lossy())
152-
}
153-
spin_manifest::ApplicationOrigin::Bindle { id, server } => {
154-
format!("bindle+{}?id={}", server, id)
138+
// Apply --env to component environments
139+
if !self.env.is_empty() {
140+
for component in app.components.iter_mut() {
141+
component.wasm.environment.extend(self.env.iter().cloned());
155142
}
156-
};
143+
}
157144

158145
let trigger_type = match app.info.trigger {
159146
ApplicationTrigger::Http(_) => "http",
160147
ApplicationTrigger::Redis(_) => "redis",
161148
};
162149

150+
// Build and write app lock file
151+
let locked_app = spin_trigger::locked::build_locked_app(app, working_dir)?;
152+
let locked_path = working_dir.join("spin.lock");
153+
let locked_app_contents =
154+
serde_json::to_vec_pretty(&locked_app).context("failed to serialize locked app")?;
155+
std::fs::write(&locked_path, locked_app_contents)
156+
.with_context(|| format!("failed to write {:?}", locked_path))?;
157+
let locked_url = format!("file://{}", locked_path.to_string_lossy());
158+
159+
// For `spin up --help`, we just want the executor to dump its own argument usage info
163160
let trigger_args = if self.help {
164161
vec![OsString::from("--help-args-only")]
165162
} else {
@@ -170,24 +167,16 @@ impl UpCommand {
170167
// via hard-link. I think it should be fine as long as we aren't `setuid`ing this binary.
171168
let mut cmd = std::process::Command::new(std::env::current_exe().unwrap());
172169
cmd.arg("trigger")
173-
.env("SPIN_WORKING_DIR", working_dir)
174-
.env("SPIN_MANIFEST_URL", manifest_url)
175-
.env("SPIN_TRIGGER_TYPE", trigger_type)
176-
.env(
177-
"SPIN_ALLOW_TRANSIENT_WRITE",
178-
self.allow_transient_write.to_string(),
179-
)
170+
.env(SPIN_WORKING_DIR, working_dir)
171+
.env(SPIN_LOCKED_URL, locked_url)
180172
.arg(trigger_type)
181173
.args(trigger_args);
182174

183-
if let Some(bindle_server) = self.server {
184-
cmd.env(BINDLE_URL_ENV, bindle_server);
185-
}
186-
187175
tracing::trace!("Running trigger executor: {:?}", cmd);
188176

189177
let mut child = cmd.spawn().context("Failed to execute trigger")?;
190178

179+
// Terminate trigger executor if `spin up` itself receives a termination signal
191180
#[cfg(not(windows))]
192181
{
193182
// https://github.com/nix-rust/nix/issues/656
@@ -232,3 +221,12 @@ impl WorkingDirectory {
232221
}
233222
}
234223
}
224+
225+
// Parse the environment variables passed in `key=value` pairs.
226+
fn parse_env_var(s: &str) -> Result<(String, String)> {
227+
let parts: Vec<_> = s.splitn(2, '=').collect();
228+
if parts.len() != 2 {
229+
bail!("Environment variable must be of the form `key=value`");
230+
}
231+
Ok((parts[0].to_owned(), parts[1].to_owned()))
232+
}

0 commit comments

Comments
 (0)