Skip to content

Commit dd760cf

Browse files
Merge #1072
1072: Fix persistent data volumes with remote cross. r=Emilgardis a=Alexhuszagh This fixes copying files into a directory inside a docker data volume, where previously we copied the entire temp directory into the volume itself. This meant that `tmp.tmpLkX8M3` would be copied to `"${volume}/tmp.tmpLkX8M3"`, rather than its contents being copied into `"${volume}"`. This also contains numerous other bugs fixes and changes internally, which have been submitted each as separate commits. This fixes a regression in #1054 to re-enable fingerprinting to work, since previously the fingerprint file name was based off the container name. Since #1054 changes the container names to rely on the system time, this ensures the fingerprints are specific for only the toolchain and the path of directory. This also simplifies the internals of the docker module substantially. Most free functions have been modified to become methods of structs to simplify their function signatures. Some structs have also been renamed to make it clearer what their purpose is. Closes #1016. Co-authored-by: Alex Huszagh <ahuszagh@gmail.com>
2 parents 7afbfe9 + 3a897ba commit dd760cf

File tree

11 files changed

+1068
-1083
lines changed

11 files changed

+1068
-1083
lines changed

src/bin/commands/containers.rs

Lines changed: 37 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,8 @@ fn get_cross_volumes(
320320
msg_info: &mut MessageInfo,
321321
) -> cross::Result<Vec<String>> {
322322
use cross::docker::VOLUME_PREFIX;
323-
let stdout = docker::subcommand(engine, "volume")
323+
let stdout = engine
324+
.subcommand("volume")
324325
.arg("list")
325326
.args(["--format", "{{.Name}}"])
326327
// handles simple regex: ^ for start of line.
@@ -348,7 +349,7 @@ pub fn remove_all_volumes(
348349
) -> cross::Result<()> {
349350
let volumes = get_cross_volumes(engine, msg_info)?;
350351

351-
let mut command = docker::subcommand(engine, "volume");
352+
let mut command = engine.subcommand("volume");
352353
command.arg("rm");
353354
if force {
354355
command.arg("--force");
@@ -370,7 +371,7 @@ pub fn prune_volumes(
370371
engine: &docker::Engine,
371372
msg_info: &mut MessageInfo,
372373
) -> cross::Result<()> {
373-
let mut command = docker::subcommand(engine, "volume");
374+
let mut command = engine.subcommand("volume");
374375
command.args(["prune", "--force"]);
375376
if execute {
376377
command.run(msg_info, false).map_err(Into::into)
@@ -397,34 +398,34 @@ pub fn create_persistent_volume(
397398
};
398399
let mount_finder = docker::MountFinder::create(engine)?;
399400
let dirs = docker::ToolchainDirectories::assemble(&mount_finder, toolchain.clone())?;
400-
let container = dirs.unique_container_identifier(&toolchain.host().target)?;
401-
let volume = dirs.unique_toolchain_identifier()?;
401+
let container_id = dirs.unique_container_identifier(&toolchain.host().target)?;
402+
let volume_id = dirs.unique_toolchain_identifier()?;
403+
let volume = docker::DockerVolume::new(engine, &volume_id);
402404

403-
if docker::volume_exists(engine, &volume, msg_info)? {
404-
eyre::bail!("Error: volume {volume} already exists.");
405+
if volume.exists(msg_info)? {
406+
eyre::bail!("Error: volume {volume_id} already exists.");
405407
}
406408

407-
docker::subcommand(engine, "volume")
408-
.args(["create", &volume])
409-
.run_and_get_status(msg_info, false)?;
409+
volume.create(msg_info)?;
410410

411411
// stop the container if it's already running
412-
let state = docker::container_state(engine, &container, msg_info)?;
412+
let container = docker::DockerContainer::new(engine, &container_id);
413+
let state = container.state(msg_info)?;
413414
if !state.is_stopped() {
414-
msg_info.warn(format_args!("container {container} was running."))?;
415-
docker::container_stop_default(engine, &container, msg_info)?;
415+
msg_info.warn(format_args!("container {container_id} was running."))?;
416+
container.stop_default(msg_info)?;
416417
}
417418
if state.exists() {
418-
msg_info.warn(format_args!("container {container} was exited."))?;
419-
docker::container_rm(engine, &container, msg_info)?;
419+
msg_info.warn(format_args!("container {container_id} was exited."))?;
420+
container.remove(msg_info)?;
420421
}
421422

422423
// create a dummy running container to copy data over
423424
let mount_prefix = docker::MOUNT_PREFIX;
424-
let mut docker = docker::subcommand(engine, "run");
425-
docker.args(["--name", &container]);
425+
let mut docker = engine.subcommand("run");
426+
docker.args(["--name", &container_id]);
426427
docker.arg("--rm");
427-
docker.args(["-v", &format!("{}:{}", volume, mount_prefix)]);
428+
docker.args(["-v", &format!("{}:{}", volume_id, mount_prefix)]);
428429
docker.arg("-d");
429430
let is_tty = io::Stdin::is_atty() && io::Stdout::is_atty() && io::Stderr::is_atty();
430431
if is_tty {
@@ -440,34 +441,15 @@ pub fn create_persistent_volume(
440441
docker.args(["sh", "-c", "sleep infinity"]);
441442
}
442443
// store first, since failing to non-existing container is fine
443-
docker::Container::create(engine.clone(), container.clone())?;
444-
docker.run_and_get_status(msg_info, false)?;
445-
446-
docker::remote::copy_volume_container_xargo(
447-
engine,
448-
&container,
449-
&dirs,
450-
mount_prefix.as_ref(),
451-
msg_info,
452-
)?;
453-
docker::remote::copy_volume_container_cargo(
454-
engine,
455-
&container,
456-
&dirs,
457-
mount_prefix.as_ref(),
458-
copy_registry,
459-
msg_info,
460-
)?;
461-
docker::remote::copy_volume_container_rust(
462-
engine,
463-
&container,
464-
&dirs,
465-
None,
466-
mount_prefix.as_ref(),
467-
msg_info,
468-
)?;
469-
470-
docker::Container::finish_static(is_tty, msg_info);
444+
docker::ChildContainer::create(engine.clone(), container_id.clone())?;
445+
docker.run_and_get_status(msg_info, true)?;
446+
447+
let data_volume = docker::ContainerDataVolume::new(engine, &container_id, &dirs);
448+
data_volume.copy_xargo(mount_prefix.as_ref(), msg_info)?;
449+
data_volume.copy_cargo(mount_prefix.as_ref(), copy_registry, msg_info)?;
450+
data_volume.copy_rust(None, mount_prefix.as_ref(), msg_info)?;
451+
452+
docker::ChildContainer::finish_static(is_tty, msg_info);
471453

472454
Ok(())
473455
}
@@ -484,13 +466,14 @@ pub fn remove_persistent_volume(
484466
};
485467
let mount_finder = docker::MountFinder::create(engine)?;
486468
let dirs = docker::ToolchainDirectories::assemble(&mount_finder, toolchain)?;
487-
let volume = dirs.unique_toolchain_identifier()?;
469+
let volume_id = dirs.unique_toolchain_identifier()?;
470+
let volume = docker::DockerVolume::new(engine, &volume_id);
488471

489-
if !docker::volume_exists(engine, &volume, msg_info)? {
490-
eyre::bail!("Error: volume {volume} does not exist.");
472+
if !volume.exists(msg_info)? {
473+
eyre::bail!("Error: volume {volume_id} does not exist.");
491474
}
492475

493-
docker::volume_rm(engine, &volume, msg_info)?;
476+
volume.remove(msg_info)?;
494477

495478
Ok(())
496479
}
@@ -500,7 +483,8 @@ fn get_cross_containers(
500483
msg_info: &mut MessageInfo,
501484
) -> cross::Result<Vec<String>> {
502485
use cross::docker::VOLUME_PREFIX;
503-
let stdout = docker::subcommand(engine, "ps")
486+
let stdout = engine
487+
.subcommand("ps")
504488
.arg("-a")
505489
.args(["--format", "{{.Names}}: {{.State}}"])
506490
// handles simple regex: ^ for start of line.
@@ -543,13 +527,13 @@ pub fn remove_all_containers(
543527

544528
let mut commands = vec![];
545529
if !running.is_empty() {
546-
let mut stop = docker::subcommand(engine, "stop");
530+
let mut stop = engine.subcommand("stop");
547531
stop.args(&running);
548532
commands.push(stop);
549533
}
550534

551535
if !(stopped.is_empty() && running.is_empty()) {
552-
let mut rm = docker::subcommand(engine, "rm");
536+
let mut rm = engine.subcommand("rm");
553537
if force {
554538
rm.arg("--force");
555539
}

src/bin/commands/images.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,8 @@ fn get_cross_images(
166166
msg_info: &mut MessageInfo,
167167
local: bool,
168168
) -> cross::Result<Vec<Image>> {
169-
let mut images: BTreeSet<_> = cross::docker::subcommand(engine, "images")
169+
let mut images: BTreeSet<_> = engine
170+
.subcommand("images")
170171
.args(["--format", "{{.Repository}}:{{.Tag}} {{.ID}}"])
171172
.args([
172173
"--filter",
@@ -177,7 +178,8 @@ fn get_cross_images(
177178
.map(parse_image)
178179
.collect();
179180

180-
let stdout = cross::docker::subcommand(engine, "images")
181+
let stdout = engine
182+
.subcommand("images")
181183
.args(["--format", "{{.Repository}}:{{.Tag}} {{.ID}}"])
182184
.run_and_get_stdout(msg_info)?;
183185
let ids: Vec<_> = images.iter().map(|i| i.id.to_string()).collect();
@@ -238,7 +240,7 @@ fn get_image_target(
238240
return Ok(target);
239241
}
240242
}
241-
let mut command = cross::docker::subcommand(engine, "inspect");
243+
let mut command = engine.subcommand("inspect");
242244
command.args([
243245
"--format",
244246
&format!(
@@ -332,7 +334,7 @@ fn remove_images(
332334
force: bool,
333335
execute: bool,
334336
) -> cross::Result<()> {
335-
let mut command = docker::subcommand(engine, "rmi");
337+
let mut command = engine.subcommand("rmi");
336338
if force {
337339
command.arg("--force");
338340
}

src/docker/custom.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::shell::MessageInfo;
77
use crate::{errors::*, file, CommandExt, ToUtf8};
88
use crate::{CargoMetadata, TargetTriple};
99

10-
use super::{get_image_name, parse_docker_opts, path_hash, ImagePlatform};
10+
use super::{get_image_name, path_hash, Engine, ImagePlatform};
1111

1212
pub const CROSS_CUSTOM_DOCKERFILE_IMAGE_PREFIX: &str = "localhost/cross-rs/cross-custom-";
1313

@@ -71,7 +71,7 @@ impl<'a> Dockerfile<'a> {
7171
msg_info: &mut MessageInfo,
7272
) -> Result<String> {
7373
let uses_zig = options.cargo_variant.uses_zig();
74-
let mut docker_build = docker::command(&options.engine);
74+
let mut docker_build = options.engine.command();
7575
match docker::Engine::has_buildkit() {
7676
true => docker_build.args(["buildx", "build"]),
7777
false => docker_build.arg("build"),
@@ -147,7 +147,7 @@ impl<'a> Dockerfile<'a> {
147147
docker_build.args(["--file".into(), path]);
148148

149149
if let Some(build_opts) = options.config.build_opts() {
150-
docker_build.args(parse_docker_opts(&build_opts)?);
150+
docker_build.args(Engine::parse_opts(&build_opts)?);
151151
}
152152

153153
let has_output = options.config.build_opts().map_or(false, |opts| {
@@ -205,7 +205,7 @@ impl<'a> Dockerfile<'a> {
205205
"{}{package_name}:{target_triple}-{path_hash}{custom}",
206206
CROSS_CUSTOM_DOCKERFILE_IMAGE_PREFIX,
207207
package_name = docker_package_name(metadata),
208-
path_hash = path_hash(&metadata.workspace_root)?,
208+
path_hash = path_hash(&metadata.workspace_root, docker::PATH_HASH_SHORT)?,
209209
custom = if matches!(self, Self::File { .. }) {
210210
""
211211
} else {

src/docker/local.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,34 +30,34 @@ pub(crate) fn run(
3030
let toolchain_dirs = paths.directories.toolchain_directories();
3131
let package_dirs = paths.directories.package_directories();
3232

33-
let mut cmd = cargo_safe_command(options.cargo_variant);
33+
let mut cmd = options.cargo_variant.safe_command();
3434
cmd.args(args);
3535

36-
let mut docker = subcommand(engine, "run");
37-
docker_userns(&mut docker);
36+
let mut docker = engine.subcommand("run");
37+
docker.add_userns();
3838

3939
options
4040
.image
4141
.platform
4242
.specify_platform(&options.engine, &mut docker);
43-
docker_envvars(&mut docker, &options, toolchain_dirs, msg_info)?;
43+
docker.add_envvars(&options, toolchain_dirs, msg_info)?;
4444

45-
docker_mount(
46-
&mut docker,
45+
docker.add_mounts(
4746
&options,
4847
&paths,
4948
|docker, host, absolute| mount(docker, host, absolute, ""),
5049
|_| {},
5150
msg_info,
5251
)?;
5352

54-
let container = toolchain_dirs.unique_container_identifier(options.target.target())?;
55-
docker.args(["--name", &container]);
53+
let container_id = toolchain_dirs.unique_container_identifier(options.target.target())?;
54+
docker.args(["--name", &container_id]);
5655
docker.arg("--rm");
5756

58-
docker_seccomp(&mut docker, engine.kind, &options.target, &paths.metadata)
57+
docker
58+
.add_seccomp(engine.kind, &options.target, &paths.metadata)
5959
.wrap_err("when copying seccomp profile")?;
60-
docker_user_id(&mut docker, engine.kind);
60+
docker.add_user_id(engine.kind);
6161

6262
docker
6363
.args([
@@ -99,7 +99,7 @@ pub(crate) fn run(
9999
"-v",
100100
&format!("{}:/target:z", package_dirs.target().to_utf8()?),
101101
]);
102-
docker_cwd(&mut docker, &paths)?;
102+
docker.add_cwd(&paths)?;
103103

104104
// When running inside NixOS or using Nix packaging we need to add the Nix
105105
// Store to the running container so it can load the needed binaries.
@@ -124,10 +124,10 @@ pub(crate) fn run(
124124
.wrap_err("when building custom image")?;
125125
}
126126

127-
Container::create(engine.clone(), container)?;
127+
ChildContainer::create(engine.clone(), container_id)?;
128128
let status = docker
129129
.arg(&image_name)
130-
.args(["sh", "-c", &build_command(toolchain_dirs, &cmd)])
130+
.add_build_command(toolchain_dirs, &cmd)
131131
.run_and_get_status(msg_info, false)
132132
.map_err(Into::into);
133133

@@ -138,7 +138,7 @@ pub(crate) fn run(
138138
// SAFETY: an atomic load.
139139
let is_terminated = unsafe { crate::errors::TERMINATED.load(Ordering::SeqCst) };
140140
if !is_terminated {
141-
Container::exit_static();
141+
ChildContainer::exit_static();
142142
}
143143

144144
status

0 commit comments

Comments
 (0)