Skip to content

Commit 1b69243

Browse files
committed
Remove 'allow_transient_write' from spin-loader
This functionality is now handled in spin-core by mounting files with write capabilites disabled. Various tidying in the vicinity of removals. Signed-off-by: Lann Martin <[email protected]>
1 parent e526e69 commit 1b69243

File tree

7 files changed

+41
-142
lines changed

7 files changed

+41
-142
lines changed

crates/loader/src/assets.rs

-13
Original file line numberDiff line numberDiff line change
@@ -90,19 +90,6 @@ pub fn file_sha256_digest_string(path: impl AsRef<Path>) -> std::io::Result<Stri
9090
Ok(digest_string)
9191
}
9292

93-
/// Change file to writable or readonly
94-
pub(crate) async fn change_file_permission(
95-
path: impl AsRef<Path>,
96-
allow_transient_write: bool,
97-
) -> Result<()> {
98-
let mut perms = tokio::fs::metadata(&path).await?.permissions();
99-
perms.set_readonly(!allow_transient_write);
100-
tokio::fs::set_permissions(path, perms.clone())
101-
.await
102-
.with_context(|| anyhow!("Cannot set permission {:?}", perms.clone()))?;
103-
Ok(())
104-
}
105-
10693
#[cfg(test)]
10794
mod test {
10895
use super::*;

crates/loader/src/bindle/assets.rs

+14-42
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use tracing::log;
1212

1313
use crate::file_sha256_digest_string;
1414
use crate::{
15-
assets::{change_file_permission, create_dir, ensure_under},
15+
assets::{create_dir, ensure_under},
1616
bindle::utils::BindleReader,
1717
};
1818

@@ -22,15 +22,12 @@ pub(crate) async fn prepare_component(
2222
parcels: &[Label],
2323
base_dst: impl AsRef<Path>,
2424
component: &str,
25-
allow_transient_write: bool,
2625
) -> Result<DirectoryMount> {
2726
let copier = Copier {
2827
reader: reader.clone(),
2928
id: bindle_id.clone(),
3029
};
31-
copier
32-
.prepare(parcels, base_dst, component, allow_transient_write)
33-
.await
30+
copier.prepare(parcels, base_dst, component).await
3431
}
3532

3633
pub(crate) struct Copier {
@@ -44,7 +41,6 @@ impl Copier {
4441
parcels: &[Label],
4542
base_dst: impl AsRef<Path>,
4643
component: &str,
47-
allow_transient_write: bool,
4844
) -> Result<DirectoryMount> {
4945
log::info!(
5046
"Mounting files from '{}' to '{}'",
@@ -54,56 +50,34 @@ impl Copier {
5450

5551
let host = create_dir(&base_dst, component).await?;
5652
let guest = "/".to_string();
57-
self.copy_all(parcels, &host, allow_transient_write).await?;
53+
self.copy_all(parcels, &host).await?;
5854

5955
Ok(DirectoryMount { host, guest })
6056
}
6157

62-
async fn copy_all(
63-
&self,
64-
parcels: &[Label],
65-
dir: impl AsRef<Path>,
66-
allow_transient_write: bool,
67-
) -> Result<()> {
68-
match stream::iter(
69-
parcels
70-
.iter()
71-
.map(|p| self.copy(p, &dir, allow_transient_write)),
72-
)
73-
.buffer_unordered(crate::MAX_PARALLEL_ASSET_PROCESSING)
74-
.filter_map(|r| future::ready(r.err()))
75-
.map(|e| log::error!("{:?}", e))
76-
.count()
77-
.await
58+
async fn copy_all(&self, parcels: &[Label], dir: impl AsRef<Path>) -> Result<()> {
59+
match stream::iter(parcels.iter().map(|p| self.copy(p, &dir)))
60+
.buffer_unordered(crate::MAX_PARALLEL_ASSET_PROCESSING)
61+
.filter_map(|r| future::ready(r.err()))
62+
.map(|e| log::error!("{:?}", e))
63+
.count()
64+
.await
7865
{
7966
0 => Ok(()),
8067
n => bail!("Error copying assets: {} file(s) not copied", n),
8168
}
8269
}
8370

84-
async fn copy(
85-
&self,
86-
p: &Label,
87-
dir: impl AsRef<Path>,
88-
allow_transient_write: bool,
89-
) -> Result<()> {
71+
async fn copy(&self, p: &Label, dir: impl AsRef<Path>) -> Result<()> {
9072
let to = dir.as_ref().join(&p.name);
9173

9274
ensure_under(&dir, &to)?;
9375

9476
if to.exists() {
9577
match check_existing_file(to.clone(), p).await {
96-
Ok(true) => {
97-
change_file_permission(&to, allow_transient_write).await?;
98-
return Ok(());
99-
}
100-
Ok(false) => {
101-
// file exists but digest doesn't match, set it to writable first for further writing
102-
let perms = tokio::fs::metadata(&to).await?.permissions();
103-
if perms.readonly() {
104-
change_file_permission(&to, true).await?;
105-
}
106-
}
78+
// Copy already exists
79+
Ok(true) => return Ok(()),
80+
Ok(false) => (),
10781
Err(err) => tracing::error!("Error verifying existing parcel: {}", err),
10882
}
10983
}
@@ -144,8 +118,6 @@ impl Copier {
144118
})?;
145119
}
146120

147-
change_file_permission(&to, allow_transient_write).await?;
148-
149121
Ok(())
150122
}
151123
}

crates/loader/src/bindle/mod.rs

+7-23
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,11 @@ use std::path::Path;
1515
use anyhow::{anyhow, Context, Result};
1616
use bindle::Invoice;
1717
use futures::future;
18-
1918
use outbound_http::allowed_http_hosts::validate_allowed_http_hosts;
2019
use spin_manifest::{
2120
Application, ApplicationInformation, ApplicationOrigin, CoreComponent, ModuleSource,
2221
SpinVersion, WasmConfig,
2322
};
24-
use tracing::log;
2523

2624
use crate::bindle::{
2725
config::{RawAppManifest, RawComponentManifest},
@@ -35,19 +33,14 @@ pub use utils::SPIN_MANIFEST_MEDIA_TYPE;
3533
/// prepared application configuration consumable by a Spin execution context.
3634
/// If a directory is provided, use it as the base directory to expand the assets,
3735
/// otherwise create a new temporary directory.
38-
pub async fn from_bindle(
39-
id: &str,
40-
url: &str,
41-
base_dst: impl AsRef<Path>,
42-
allow_transient_write: bool,
43-
) -> Result<Application> {
36+
pub async fn from_bindle(id: &str, url: &str, base_dst: impl AsRef<Path>) -> Result<Application> {
4437
// TODO
4538
// Handle Bindle authentication.
4639
let connection_info = BindleConnectionInfo::new(url, false, None, None);
4740
let client = connection_info.client()?;
4841
let reader = BindleReader::remote(&client, &id.parse()?);
4942

50-
prepare(id, url, &reader, base_dst, allow_transient_write).await
43+
prepare(id, url, &reader, base_dst).await
5144
}
5245

5346
/// Converts a Bindle invoice into Spin configuration.
@@ -56,7 +49,6 @@ async fn prepare(
5649
url: &str,
5750
reader: &BindleReader,
5851
base_dst: impl AsRef<Path>,
59-
allow_transient_write: bool,
6052
) -> Result<Application> {
6153
// First, get the invoice from the Bindle server.
6254
let invoice = reader
@@ -67,12 +59,12 @@ async fn prepare(
6759
// Then, reconstruct the application manifest from the parcels.
6860
let raw: RawAppManifest =
6961
toml::from_slice(&reader.get_parcel(&find_manifest(&invoice)?).await?)?;
70-
log::trace!("Recreated manifest from bindle: {:?}", raw);
62+
tracing::trace!("Recreated manifest from bindle: {:?}", raw);
7163

7264
validate_raw_app_manifest(&raw)?;
7365

7466
let info = info(&raw, &invoice, url);
75-
log::trace!("Application information from bindle: {:?}", info);
67+
tracing::trace!("Application information from bindle: {:?}", info);
7668
let component_triggers = raw
7769
.components
7870
.iter()
@@ -81,7 +73,7 @@ async fn prepare(
8173
let components = future::join_all(
8274
raw.components
8375
.into_iter()
84-
.map(|c| async { core(c, &invoice, reader, &base_dst, allow_transient_write).await })
76+
.map(|c| async { core(c, &invoice, reader, &base_dst).await })
8577
.collect::<Vec<_>>(),
8678
)
8779
.await
@@ -115,7 +107,6 @@ async fn core(
115107
invoice: &Invoice,
116108
reader: &BindleReader,
117109
base_dst: impl AsRef<Path>,
118-
allow_transient_write: bool,
119110
) -> Result<CoreComponent> {
120111
let bytes = reader
121112
.get_parcel(&raw.source)
@@ -129,15 +120,8 @@ async fn core(
129120
Some(group) => {
130121
let parcels = parcels_in_group(invoice, &group);
131122
vec![
132-
assets::prepare_component(
133-
reader,
134-
&invoice.bindle.id,
135-
&parcels,
136-
base_dst,
137-
&id,
138-
allow_transient_write,
139-
)
140-
.await?,
123+
assets::prepare_component(reader, &invoice.bindle.id, &parcels, base_dst, &id)
124+
.await?,
141125
]
142126
}
143127
None => vec![],

crates/loader/src/local/assets.rs

+11-32
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,13 @@
11
#![deny(missing_docs)]
22

3-
use crate::assets::{
4-
change_file_permission, create_dir, ensure_all_under, ensure_under, to_relative,
5-
};
3+
use crate::assets::{create_dir, ensure_all_under, ensure_under, to_relative};
64
use anyhow::{anyhow, bail, ensure, Context, Result};
75
use futures::{future, stream, StreamExt};
86
use spin_manifest::DirectoryMount;
97
use std::{
108
path::{Path, PathBuf},
119
vec,
1210
};
13-
use tracing::log;
1411
use walkdir::WalkDir;
1512

1613
use super::config::{RawDirectoryPlacement, RawFileMount};
@@ -22,10 +19,9 @@ pub(crate) async fn prepare_component(
2219
src: impl AsRef<Path>,
2320
base_dst: impl AsRef<Path>,
2421
id: &str,
25-
allow_transient_write: bool,
2622
exclude_files: &[String],
2723
) -> Result<Vec<DirectoryMount>> {
28-
log::info!(
24+
tracing::info!(
2925
"Mounting files from '{}' to '{}'",
3026
src.as_ref().display(),
3127
base_dst.as_ref().display()
@@ -34,7 +30,7 @@ pub(crate) async fn prepare_component(
3430
let files = collect(raw_mounts, exclude_files, src)?;
3531
let host = create_dir(&base_dst, id).await?;
3632
let guest = "/".to_string();
37-
copy_all(&files, &host, allow_transient_write).await?;
33+
copy_all(&files, &host).await?;
3834

3935
Ok(vec![DirectoryMount { guest, host }])
4036
}
@@ -173,7 +169,7 @@ fn collect_placement(
173169
/// Generate a vector of file mounts given a file pattern.
174170
fn collect_pattern(pattern: &str, rel: impl AsRef<Path>) -> Result<Vec<FileMount>> {
175171
let abs = rel.as_ref().join(pattern);
176-
log::trace!("Resolving asset file pattern '{:?}'", abs);
172+
tracing::trace!("Resolving asset file pattern '{:?}'", abs);
177173

178174
let matches = glob::glob(&abs.to_string_lossy())?;
179175
let specifiers = matches
@@ -186,53 +182,36 @@ fn collect_pattern(pattern: &str, rel: impl AsRef<Path>) -> Result<Vec<FileMount
186182
}
187183

188184
/// Copy all files to the mount directory.
189-
async fn copy_all(
190-
files: &[FileMount],
191-
dir: impl AsRef<Path>,
192-
allow_transient_write: bool,
193-
) -> Result<()> {
194-
let copy_futures = files.iter().map(|f| copy(f, &dir, allow_transient_write));
185+
async fn copy_all(files: &[FileMount], dir: impl AsRef<Path>) -> Result<()> {
186+
let copy_futures = files.iter().map(|f| copy(f, &dir));
195187
let errors = stream::iter(copy_futures)
196188
.buffer_unordered(crate::MAX_PARALLEL_ASSET_PROCESSING)
197189
.filter_map(|r| future::ready(r.err()))
198-
.map(|e| log::error!("{:?}", e))
190+
.map(|e| tracing::error!("{e:?}"))
199191
.count()
200192
.await;
201193
ensure!(
202194
errors == 0,
203-
"Error copying assets: {} file(s) not copied",
204-
errors
195+
"Error copying assets: {errors} file(s) not copied",
205196
);
206197
Ok(())
207198
}
208199

209200
/// Copy a single file to the mount directory, setting it as read-only.
210-
async fn copy(file: &FileMount, dir: impl AsRef<Path>, allow_transient_write: bool) -> Result<()> {
201+
async fn copy(file: &FileMount, dir: impl AsRef<Path>) -> Result<()> {
211202
let from = &file.src;
212203
let to = dir.as_ref().join(&file.relative_dst);
213204

214205
ensure_under(&dir.as_ref(), &to.as_path())?;
215206

216-
log::trace!(
217-
"Copying asset file '{}' -> '{}'",
218-
from.display(),
219-
to.display()
220-
);
207+
tracing::trace!("Copying asset file '{from:?}' -> '{to:?}'");
221208

222-
tokio::fs::create_dir_all(to.parent().expect("Cannot copy to file '/'")).await?;
223-
224-
// if destination file is read-only, set it to writable first
225-
let metadata = tokio::fs::metadata(&to).await;
226-
if metadata.is_ok() && metadata.unwrap().permissions().readonly() {
227-
change_file_permission(&to, true).await?;
228-
}
209+
tokio::fs::create_dir_all(to.parent().context("Cannot copy to file '/'")?).await?;
229210

230211
let _ = tokio::fs::copy(&from, &to)
231212
.await
232213
.with_context(|| anyhow!("Error copying asset file '{}'", from.display()))?;
233214

234-
change_file_permission(&to, allow_transient_write).await?;
235-
236215
Ok(())
237216
}
238217

0 commit comments

Comments
 (0)