Skip to content

Commit 7317e8c

Browse files
committed
Move floki_root resolution into Environment structure
This helps reduce the amount of parameter passing that is needed in functions which figure out how to launch the container. The location of the configuration file, and the directory it is located in (or which needs to be mounted into the container) is part of how `floki` is run, so belongs in the `Environment` structure. This commit doesn't fundamentally change the function in any way, it just moves it. Signed-off-by: Richard Lupton <[email protected]>
1 parent 47a421a commit 7317e8c

File tree

3 files changed

+96
-86
lines changed

3 files changed

+96
-86
lines changed

src/environment.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::errors;
12
/// Query the current user environment
23
use failure::Error;
34
use std::env;
@@ -8,15 +9,20 @@ use std::process::Command;
89
pub struct Environment {
910
pub user_details: (String, String),
1011
pub current_directory: path::PathBuf,
12+
pub floki_root: path::PathBuf,
13+
pub config_file: path::PathBuf,
1114
pub ssh_agent_socket: Option<String>,
1215
}
1316

1417
impl Environment {
1518
/// Gather information on the environment floki is running in
16-
pub fn gather() -> Result<Self, Error> {
19+
pub fn gather(config_file: &Option<path::PathBuf>) -> Result<Self, Error> {
20+
let (floki_root, config_path) = resolve_floki_root_and_config(config_file)?;
1721
Ok(Environment {
1822
user_details: get_user_details()?,
1923
current_directory: get_current_working_directory()?,
24+
floki_root: floki_root,
25+
config_file: config_path,
2026
ssh_agent_socket: get_ssh_agent_socket_path(),
2127
})
2228
}
@@ -50,3 +56,82 @@ fn get_ssh_agent_socket_path() -> Option<String> {
5056
Err(_) => None,
5157
}
5258
}
59+
60+
/// Search all ancestors of the current directory for a floki.yaml file name.
61+
fn find_floki_yaml(current_directory: &path::Path) -> Result<path::PathBuf, Error> {
62+
current_directory
63+
.ancestors()
64+
.map(|a| a.join("floki.yaml"))
65+
.find(|f| f.is_file())
66+
.ok_or(errors::FlokiError::ProblemFindingConfigYaml {}.into())
67+
}
68+
69+
/// Take a file path, and return a tuple consisting of it's parent directory and the file path
70+
fn locate_file_in_parents(path: path::PathBuf) -> Result<(path::PathBuf, path::PathBuf), Error> {
71+
let dir = path
72+
.parent()
73+
.ok_or_else(|| errors::FlokiInternalError::InternalAssertionFailed {
74+
description: format!("config_file '{:?}' does not have a parent", &path),
75+
})?
76+
.to_path_buf();
77+
Ok((dir, path))
78+
}
79+
80+
/// Resolve floki root directory and path to configuration file
81+
fn resolve_floki_root_and_config(
82+
config_file: &Option<path::PathBuf>,
83+
) -> Result<(path::PathBuf, path::PathBuf), Error> {
84+
match config_file {
85+
Some(path) => Ok((get_current_working_directory()?, path.clone())),
86+
None => Ok(locate_file_in_parents(find_floki_yaml(
87+
&get_current_working_directory()?,
88+
)?)?),
89+
}
90+
}
91+
92+
#[cfg(test)]
93+
mod test {
94+
use super::*;
95+
use failure::format_err;
96+
use std::fs;
97+
use tempdir;
98+
99+
fn touch_file(path: &path::Path) -> Result<(), Error> {
100+
fs::create_dir_all(
101+
path.parent()
102+
.ok_or(format_err!("Unable to take parent of path"))?,
103+
)?;
104+
fs::OpenOptions::new().create(true).write(true).open(path)?;
105+
Ok(())
106+
}
107+
108+
#[test]
109+
fn test_find_floki_yaml_current_dir() -> Result<(), Error> {
110+
let tmp_dir = tempdir::TempDir::new("")?;
111+
let floki_yaml_path = tmp_dir.path().join("floki.yaml");
112+
touch_file(&floki_yaml_path)?;
113+
assert_eq!(find_floki_yaml(&tmp_dir.path())?, floki_yaml_path);
114+
Ok(())
115+
}
116+
117+
#[test]
118+
fn test_find_floki_yaml_ancestor() -> Result<(), Error> {
119+
let tmp_dir = tempdir::TempDir::new("")?;
120+
let floki_yaml_path = tmp_dir.path().join("floki.yaml");
121+
touch_file(&floki_yaml_path)?;
122+
assert_eq!(
123+
find_floki_yaml(&tmp_dir.path().join("dir/subdir"))?,
124+
floki_yaml_path
125+
);
126+
Ok(())
127+
}
128+
129+
#[test]
130+
fn test_find_floki_yaml_sibling() -> Result<(), Error> {
131+
let tmp_dir = tempdir::TempDir::new("")?;
132+
let floki_yaml_path = tmp_dir.path().join("src/floki.yaml");
133+
touch_file(&floki_yaml_path)?;
134+
assert!(find_floki_yaml(&tmp_dir.path().join("include")).is_err());
135+
Ok(())
136+
}
137+
}

src/interpret.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,18 @@ use std::path;
1111
/// Build a spec for the docker container, and then run it
1212
pub(crate) fn run_container(
1313
environ: &Environment,
14-
floki_root: &path::Path,
1514
config: &FlokiConfig,
1615
command: &str,
1716
) -> Result<(), Error> {
18-
let (mut cmd, mut dind) = build_basic_command(&floki_root, &config)?;
17+
let (mut cmd, mut dind) = build_basic_command(&environ.floki_root, &config)?;
1918

2019
cmd = configure_dind(cmd, &config, &mut dind)?;
2120
cmd = configure_floki_user_env(cmd, &environ);
22-
cmd = configure_floki_host_mountdir_env(cmd, &floki_root);
21+
cmd = configure_floki_host_mountdir_env(cmd, &environ.floki_root);
2322
cmd = configure_forward_user(cmd, &config, &environ);
2423
cmd = configure_forward_ssh_agent(cmd, &config, &environ)?;
2524
cmd = configure_docker_switches(cmd, &config);
26-
cmd = configure_working_directory(cmd, &environ, &floki_root, &config);
25+
cmd = configure_working_directory(cmd, &environ, &config);
2726

2827
cmd.run(command)
2928
}
@@ -109,13 +108,12 @@ fn configure_docker_switches(
109108
fn configure_working_directory(
110109
cmd: DockerCommandBuilder,
111110
env: &Environment,
112-
floki_root: &path::Path,
113111
config: &FlokiConfig,
114112
) -> DockerCommandBuilder {
115113
cmd.set_working_directory(
116114
get_working_directory(
117115
&env.current_directory,
118-
&floki_root,
116+
&env.floki_root,
119117
&path::PathBuf::from(&config.mount),
120118
)
121119
.to_str()

src/main.rs

Lines changed: 6 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ use verify::verify_command;
2020

2121
use failure::Error;
2222
use quicli::prelude::*;
23-
use std::path;
2423
use structopt::StructOpt;
2524

2625
fn main() -> CliResult {
@@ -41,16 +40,12 @@ fn main() -> CliResult {
4140
fn run_floki_from_args(args: &Cli) -> Result<(), Error> {
4241
debug!("Got command line arguments: {:?}", &args);
4342

44-
let environ = environment::Environment::gather()?;
43+
let environ = environment::Environment::gather(&args.config_file)?;
4544
debug!("Got environment {:?}", &environ);
4645

47-
let (floki_root, config_file) = match &args.config_file {
48-
Some(config_file) => (environ.current_directory.clone(), config_file.clone()),
49-
None => locate_file_in_system(find_floki_yaml(&environ.current_directory)?)?,
50-
};
51-
debug!("Selected configuration file: {:?}", &config_file);
46+
debug!("Selected configuration file: {:?}", &environ.config_file);
5247

53-
let config = FlokiConfig::from_file(&config_file)?;
48+
let config = FlokiConfig::from_file(&environ.config_file)?;
5449
verify_command(args.local, &config)?;
5550

5651
// Dispatch appropriate subcommand
@@ -65,93 +60,25 @@ fn run_floki_from_args(args: &Cli) -> Result<(), Error> {
6560
// Run a command in the floki container
6661
Some(Subcommand::Run { command }) => {
6762
let inner_command = interpret::command_in_shell(config.shell.inner_shell(), &command);
68-
run_floki_container(&environ, &floki_root, &config, inner_command)
63+
run_floki_container(&environ, &config, inner_command)
6964
}
7065

7166
// Launch an interactive floki shell (the default)
7267
None => {
7368
let inner_command = config.shell.inner_shell().to_string();
74-
run_floki_container(&environ, &floki_root, &config, inner_command)
69+
run_floki_container(&environ, &config, inner_command)
7570
}
7671
}
7772
}
7873

7974
/// Launch a floki container running the inner command
8075
fn run_floki_container(
8176
environ: &environment::Environment,
82-
floki_root: &path::Path,
8377
config: &FlokiConfig,
8478
inner_command: String,
8579
) -> Result<(), Error> {
8680
config.image.obtain_image()?;
87-
8881
let subshell_command = command::subshell_command(&config.init, inner_command);
8982
debug!("Running container with command '{}'", &subshell_command);
90-
interpret::run_container(&environ, &floki_root, &config, &subshell_command)
91-
}
92-
93-
/// Search all ancestors of the current directory for a floki.yaml file name.
94-
fn find_floki_yaml(current_directory: &path::Path) -> Result<path::PathBuf, Error> {
95-
current_directory
96-
.ancestors()
97-
.map(|a| a.join("floki.yaml"))
98-
.find(|f| f.is_file())
99-
.ok_or(errors::FlokiError::ProblemFindingConfigYaml {}.into())
100-
}
101-
102-
/// Take a file path, and return a tuple consisting of it's directory and the file path
103-
fn locate_file_in_system(path: path::PathBuf) -> Result<(path::PathBuf, path::PathBuf), Error> {
104-
let dir = path
105-
.parent()
106-
.ok_or_else(|| errors::FlokiInternalError::InternalAssertionFailed {
107-
description: format!("config_file '{:?}' does not have a parent", &path),
108-
})?
109-
.to_path_buf();
110-
Ok((dir, path))
111-
}
112-
113-
#[cfg(test)]
114-
mod test {
115-
use super::*;
116-
use std::fs;
117-
use tempdir;
118-
119-
fn touch_file(path: &path::Path) -> Result<(), Error> {
120-
fs::create_dir_all(
121-
path.parent()
122-
.ok_or(format_err!("Unable to take parent of path"))?,
123-
)?;
124-
fs::OpenOptions::new().create(true).write(true).open(path)?;
125-
Ok(())
126-
}
127-
128-
#[test]
129-
fn test_find_floki_yaml_current_dir() -> Result<(), Error> {
130-
let tmp_dir = tempdir::TempDir::new("")?;
131-
let floki_yaml_path = tmp_dir.path().join("floki.yaml");
132-
touch_file(&floki_yaml_path)?;
133-
assert_eq!(find_floki_yaml(&tmp_dir.path())?, floki_yaml_path);
134-
Ok(())
135-
}
136-
137-
#[test]
138-
fn test_find_floki_yaml_ancestor() -> Result<(), Error> {
139-
let tmp_dir = tempdir::TempDir::new("")?;
140-
let floki_yaml_path = tmp_dir.path().join("floki.yaml");
141-
touch_file(&floki_yaml_path)?;
142-
assert_eq!(
143-
find_floki_yaml(&tmp_dir.path().join("dir/subdir"))?,
144-
floki_yaml_path
145-
);
146-
Ok(())
147-
}
148-
149-
#[test]
150-
fn test_find_floki_yaml_sibling() -> Result<(), Error> {
151-
let tmp_dir = tempdir::TempDir::new("")?;
152-
let floki_yaml_path = tmp_dir.path().join("src/floki.yaml");
153-
touch_file(&floki_yaml_path)?;
154-
assert!(find_floki_yaml(&tmp_dir.path().join("include")).is_err());
155-
Ok(())
156-
}
83+
interpret::run_container(&environ, &config, &subshell_command)
15784
}

0 commit comments

Comments
 (0)