Skip to content

Commit 275ad4b

Browse files
Merge pull request #38 from osusec/dr/async-build-fixes
Fix problems from async build process
2 parents 1b9e7ac + 701af61 commit 275ad4b

File tree

9 files changed

+168
-117
lines changed

9 files changed

+168
-117
lines changed

Cargo.lock

Lines changed: 3 additions & 2 deletions
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
@@ -35,6 +35,7 @@ rust-s3 = { version = "0.35.1", default-features = false, features = [
3535
] }
3636
minijinja = "2.6.0"
3737
duct = "0.13.7"
38+
fastrand = "2.3.0"
3839

3940

4041
[dev-dependencies]

src/builder/artifacts.rs

Lines changed: 71 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
11
use anyhow::{anyhow, Context, Error, Result};
2-
use futures::future::try_join_all;
32
use futures::FutureExt;
43
use itertools::Itertools;
54
use simplelog::{debug, trace};
65
use std::fs::File;
76
use std::io::{BufReader, Read, Write};
7+
use std::iter::repeat_with;
88
use std::path::{Path, PathBuf};
99
use tempfile::tempdir_in;
1010
use zip;
1111

1212
use crate::builder::docker;
1313
use crate::clients::docker;
1414
use crate::configparser::challenge::{ChallengeConfig, ProvideConfig};
15+
use crate::utils::TryJoinAll;
1516

1617
/// extract assets from provide config and possible container to challenge directory, return file path(s) extracted
17-
#[tokio::main(flavor = "current_thread")] // make this a sync function
1818
pub async fn extract_asset(
1919
chal: &ChallengeConfig,
2020
provide: &ProvideConfig,
@@ -62,73 +62,76 @@ pub async fn extract_asset(
6262
Ok(vec![archive_name.clone()])
6363
}
6464

65+
// handle all container events together to manage container, then match again
6566
ProvideConfig::FromContainer {
6667
container: container_name,
67-
files,
68-
} => {
69-
let tag = chal.container_tag_for_pod(profile_name, container_name)?;
70-
71-
let name = format!(
72-
"asset-container-{}-{}",
73-
chal.directory.to_string_lossy().replace("/", "-"),
74-
container_name
75-
);
76-
let container = docker::create_container(&tag, &name).await?;
77-
78-
let files = extract_files(chal, &container, files).await;
79-
80-
docker::remove_container(container).await?;
81-
82-
files
68+
..
8369
}
84-
.with_context(|| format!("could not copy files {files:?} from container {container_name}")),
85-
86-
ProvideConfig::FromContainerRename {
70+
| ProvideConfig::FromContainerRename {
8771
container: container_name,
88-
from,
89-
to,
90-
} => {
91-
let tag = chal.container_tag_for_pod(profile_name, container_name)?;
92-
93-
let name = format!(
94-
"asset-container-{}-{}",
95-
chal.directory.to_string_lossy().replace("/", "-"),
96-
container_name
97-
);
98-
let container = docker::create_container(&tag, &name).await?;
99-
100-
let files = extract_rename(chal, &container, from, &chal.directory.join(to)).await;
101-
102-
docker::remove_container(container).await?;
103-
104-
files
72+
..
10573
}
106-
.with_context(|| format!("could not copy file {from:?} from container {container_name}")),
107-
108-
ProvideConfig::FromContainerArchive {
74+
| ProvideConfig::FromContainerArchive {
10975
container: container_name,
110-
files,
111-
archive_name,
76+
..
11277
} => {
11378
let tag = chal.container_tag_for_pod(profile_name, container_name)?;
11479

11580
let name = format!(
116-
"asset-container-{}-{}",
81+
"asset-container-{}-{}-{}",
11782
chal.directory.to_string_lossy().replace("/", "-"),
118-
container_name
83+
container_name,
84+
// include random discriminator to avoid name collisions
85+
repeat_with(fastrand::alphanumeric)
86+
.take(6)
87+
.collect::<String>()
11988
);
89+
12090
let container = docker::create_container(&tag, &name).await?;
12191

122-
let files =
123-
extract_archive(chal, &container, files, &chal.directory.join(archive_name)).await;
92+
// match on `provide` enum again to handle each container type
93+
let files = match provide {
94+
ProvideConfig::FromContainer {
95+
container: container_name,
96+
files,
97+
} => extract_files(chal, &container, files)
98+
.await
99+
.with_context(|| {
100+
format!("could not copy files {files:?} from container {container_name}")
101+
}),
102+
103+
ProvideConfig::FromContainerRename {
104+
container: container_name,
105+
from,
106+
to,
107+
} => extract_rename(chal, &container, from, &chal.directory.join(to))
108+
.await
109+
.with_context(|| {
110+
format!("could not copy file {from:?} from container {container_name}")
111+
}),
112+
113+
ProvideConfig::FromContainerArchive {
114+
container: container_name,
115+
files,
116+
archive_name,
117+
} => extract_archive(chal, &container, files, &chal.directory.join(archive_name))
118+
.await
119+
.with_context(|| {
120+
// rustfmt chokes silently if these format args are inlined... ???
121+
format!(
122+
"could not create archive {:?} with files {:?} from container {}",
123+
archive_name, files, container_name
124+
)
125+
}),
126+
127+
// non-container variants handled by outer match
128+
_ => unreachable!(),
129+
};
124130

125131
docker::remove_container(container).await?;
126132

127133
files
128134
}
129-
.with_context(|| {
130-
format!("could not create archive {archive_name:?} from container {container_name}")
131-
}),
132135
}
133136
}
134137

@@ -144,12 +147,15 @@ async fn extract_files(
144147
files
145148
);
146149

147-
try_join_all(files.iter().map(|from| async {
148-
// use basename of source file as target name
149-
let to = chal.directory.join(from.file_name().unwrap());
150-
docker::copy_file(container, from, &to).await
151-
}))
152-
.await
150+
files
151+
.iter()
152+
.map(|from| async {
153+
// use basename of source file as target name
154+
let to = chal.directory.join(from.file_name().unwrap());
155+
docker::copy_file(container, from, &to).await
156+
})
157+
.try_join_all()
158+
.await
153159
}
154160

155161
/// Extract one file from container and rename
@@ -170,7 +176,6 @@ async fn extract_rename(
170176
async fn extract_archive(
171177
chal: &ChallengeConfig,
172178
container: &docker::ContainerInfo,
173-
// files: &Vec<PathBuf>,
174179
files: &[PathBuf],
175180
archive_name: &Path,
176181
) -> Result<Vec<PathBuf>> {
@@ -185,16 +190,19 @@ async fn extract_archive(
185190
let tempdir = tempfile::Builder::new()
186191
.prefix(".beavercds-archive-")
187192
.tempdir_in(".")?;
188-
let copied_files = try_join_all(files.iter().map(|from| async {
189-
let to = tempdir.path().join(from.file_name().unwrap());
190-
docker::copy_file(container, from, &to).await
191-
}))
192-
.await?;
193+
let copied_files = files
194+
.iter()
195+
.map(|from| async {
196+
let to = tempdir.path().join(from.file_name().unwrap());
197+
docker::copy_file(container, from, &to).await
198+
})
199+
.try_join_all()
200+
.await?;
193201

194202
// archive_name already has the chal dir prepended
195203
zip_files(archive_name, &copied_files)?;
196204

197-
Ok(vec![chal.directory.join(archive_name)])
205+
Ok(vec![archive_name.to_path_buf()])
198206
}
199207

200208
/// Add multiple local `files` to a zipfile at `zip_name`

src/builder/docker.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,6 @@ pub async fn build_image(context: &Path, options: &BuildObject, tag: &str) -> Re
8383
Ok(tag.to_string())
8484
}
8585

86-
// #[tokio::main(flavor = "current_thread")] // make this a sync function
8786
pub async fn push_image(image_tag: &str, creds: &UserPass) -> Result<String> {
8887
info!("pushing image {image_tag:?} to registry");
8988
let client = docker().await?;

0 commit comments

Comments
 (0)