Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run-script vault fix, add run-script --no-deps option #72

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion src/args/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ fn exec_options_to_args_returns_appropriate_flags() {
assert_eq!(opts.to_args(), expected);
}

/// Options for `docker_compose exec`.
/// Options for `docker_compose run`.
#[derive(Debug, Clone, Default)]
pub struct Run {
/// Our "superclass", faked using `Deref`.
Expand All @@ -185,6 +185,10 @@ pub struct Run {
/// to reset the entrypoint to the default.
pub entrypoint: Option<String>,

/// Don't start linked services when running specified service,
/// default: false
pub no_deps: bool,

/// PRIVATE: This field is a stand-in for future options.
/// See http://stackoverflow.com/q/39277157/12089
#[doc(hidden)]
Expand Down Expand Up @@ -216,6 +220,9 @@ impl ToArgs for Run {
args.push(OsStr::new("--entrypoint").to_owned());
args.push(entrypoint.into());
}
if self.no_deps {
args.push(OsStr::new("--no-deps").to_owned());
}
args
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/cli.yml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,9 @@ subcommands:
- run-script:
about: "Run a named script defined in metadata for specified pods or services"
args:
- no-deps: &nodeps
long: "--no-deps"
help: "Do not start linked services when running scripts"
- SCRIPT_NAME:
value_name: "SCRIPT_NAME"
required: true
Expand Down
21 changes: 16 additions & 5 deletions src/cmd/run_script.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,22 @@ use project::{Project, PodOrService};
/// Included into project in order to run named scripts on one ore more services
pub trait CommandRunScript {
/// Run a named script on all matching services
fn run_script<CR>(&self, runner: &CR, act_on: &args::ActOn, script_name: &str) -> Result<()>
fn run_script<CR>(&self,
runner: &CR,
act_on: &args::ActOn,
script_name: &str,
opts: &args::opts::Run
) -> Result<()>
where CR: CommandRunner;
}

impl CommandRunScript for Project {
fn run_script<CR>(&self, runner: &CR, act_on: &args::ActOn, script_name: &str) -> Result<()>
fn run_script<CR>(&self,
runner: &CR,
act_on: &args::ActOn,
script_name: &str,
opts: &args::opts::Run
) -> Result<()>
where CR: CommandRunner
{
let target = self.current_target();
Expand All @@ -27,7 +37,7 @@ impl CommandRunScript for Project {
// Ignore any pods that aren't enabled in the current target
if pod.enabled_in(&target) {
for service_name in pod.service_names() {
pod.run_script(runner, &self, &service_name, &script_name)?;
pod.run_script(runner, &self, &service_name, &script_name, &opts)?;
}
}
}
Expand All @@ -36,7 +46,7 @@ impl CommandRunScript for Project {
// Don't run this on any service whose pod isn't enabled in
// the current target
if pod.enabled_in(&target) {
pod.run_script(runner, &self, &service_name, &script_name)?;
pod.run_script(runner, &self, &service_name, &script_name, &opts)?;
}
}
}
Expand All @@ -51,9 +61,10 @@ fn runs_scripts_on_all_services() {
let _ = env_logger::init();
let proj = Project::from_example("rails_hello").unwrap();
let runner = TestCommandRunner::new();
let opts = args::opts::Run::default();
proj.output().unwrap();

proj.run_script(&runner, &args::ActOn::All, "routes").unwrap();
proj.run_script(&runner, &args::ActOn::All, "routes", &opts).unwrap();
assert_ran!(runner, {
["docker-compose",
"-p",
Expand Down
10 changes: 7 additions & 3 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,9 @@ trait ArgMatchesExt {

impl<'a> ArgMatchesExt for clap::ArgMatches<'a> {
fn should_output_project(&self) -> bool {
self.subcommand_name() != Some("export")
let subcommand = self.subcommand_name();
subcommand != Some("export") &&
subcommand != Some("run-script")
}

fn target_name(&self) -> &str {
Expand Down Expand Up @@ -132,6 +134,7 @@ impl<'a> ArgMatchesExt for clap::ArgMatches<'a> {
opts.environment.insert(env_val[0].to_owned(), env_val[1].to_owned());
}
}
opts.no_deps = self.is_present("no-deps");
opts
}

Expand Down Expand Up @@ -260,10 +263,11 @@ fn run(matches: &clap::ArgMatches) -> Result<()> {
proj.run(&runner, service, cmd.as_ref(), &opts)?;
}
"run-script" => {
warn_if_pods_are_enabled_but_not_running(&proj)?;
let opts = sc_matches.to_run_options();
let script_name = sc_matches.value_of("SCRIPT_NAME").unwrap();
let acts_on = sc_matches.to_acts_on("POD_OR_SERVICE", true);
proj.run_script(&runner, &acts_on, script_name.as_ref())?;
proj.output_enabled()?;
proj.run_script(&runner, &acts_on, script_name.as_ref(), &opts)?;
}
"exec" => {
warn_if_pods_are_enabled_but_not_running(&proj)?;
Expand Down
10 changes: 8 additions & 2 deletions src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -290,10 +290,16 @@ impl Pod {
}

/// Run a named script for specified service name
pub fn run_script<CR>(&self, runner: &CR, project: &Project, service_name: &str, script_name: &str) -> Result<()>
pub fn run_script<CR>(&self,
runner: &CR,
project: &Project,
service_name: &str,
script_name: &str,
opts: &args::opts::Run
) -> Result<()>
where CR: CommandRunner
{
self.config.run_script(runner, &project, &service_name, &script_name)
self.config.run_script(runner, &project, &service_name, &script_name, &opts)
}
}

Expand Down
33 changes: 27 additions & 6 deletions src/pod_config.in.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,23 @@ struct Config {
impl Config {

/// Run a named script for the specified service in this pod
pub fn run_script<CR>(&self, runner: &CR, project: &Project, service_name: &str, script_name: &str) -> Result<()>
pub fn run_script<CR>(&self,
runner: &CR,
project: &Project,
service_name: &str,
script_name: &str,
opts: &args::opts::Run
) -> Result<()>
where CR: CommandRunner
{
match self.services.get(service_name) {
Some(service_config) => {
service_config.run_script(runner, &project, &service_name, &script_name)?
service_config.run_script(
runner,
&project,
&service_name,
&script_name,
&opts)?
},
None => {}
}
Expand All @@ -81,11 +92,17 @@ struct ServiceConfig {
impl ServiceConfig {

/// Run a named script for the given service
pub fn run_script<CR>(&self, runner: &CR, project: &Project, service_name: &str, script_name: &str) -> Result<()>
pub fn run_script<CR>(&self,
runner: &CR,
project: &Project,
service_name: &str,
script_name: &str,
opts: &args::opts::Run
) -> Result<()>
where CR: CommandRunner
{
if let Some(script) = self.scripts.get(script_name) {
script.run(runner, &project, service_name)?;
script.run(runner, &project, service_name, &opts)?;
}
Ok(())
}
Expand All @@ -98,7 +115,12 @@ struct Script(Vec<Vec<String>>);
impl Script {

/// Execute each command defined for the named script
pub fn run<CR>(&self, runner: &CR, project: &Project, service_name: &str) -> Result<()>
pub fn run<CR>(
&self,
runner: &CR,
project: &Project,
service_name: &str,
opts: &args::opts::Run) -> Result<()>
where CR: CommandRunner
{
for cmd in &self.0 {
Expand All @@ -111,7 +133,6 @@ impl Script {
} else {
None
};
let opts = args::opts::Run::default();
project.run(runner, service_name, cmd.as_ref(), &opts)?;
}
Ok(())
Expand Down
42 changes: 31 additions & 11 deletions src/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -410,17 +410,10 @@ impl Project {

/// Process our pods, flattening and transforming them using our
/// plugins, and output them to the specified directory.
fn output_helper(&self, op: Operation, export_dir: &Path) -> Result<()> {
fn output_helper(&self, pods: Vec<&Pod>, op: Operation, export_dir: &Path) -> Result<()> {
// Output each pod. This isn't especially slow (except maybe the
// Vault plugin), but parallelizing things is easy.
self.pods.par_iter()
// Don't export pods which aren't enabled. However, we currently
// need to output these for `Operation::Output` in case the user
// wants to `run` a task using one of these pod definitions.
.filter(|pod| {
pod.enabled_in(&self.current_target) ||
op == Operation::Output
})
pods.par_iter()
// Process each pod in parallel.
.map(|pod| -> Result<()> {
// Figure out where to put our pod.
Expand Down Expand Up @@ -452,6 +445,8 @@ impl Project {
/// Delete our existing output and replace it with a processed and
/// expanded version of our pod definitions.
pub fn output(&self) -> Result<()> {
let pods = self.pods().iter.map(|p| p).collect();

// Get a path to our output pods directory (and delete it if it
// exists).
let out_pods = self.output_pods_dir();
Expand All @@ -460,13 +455,36 @@ impl Project {
.map_err(|e| err!("Cannot delete {}: {}", out_pods.display(), e)));
}

self.output_helper(Operation::Output, &out_pods)
self.output_helper(pods, Operation::Output, &out_pods)
}

/// Delete our existing output and replace it with a processed and
/// expanded version of our pod definitions, excluding any pods not enabled
/// for the current target.
pub fn output_enabled(&self) -> Result<()> {
let pods = self.pods.iter().filter(|pod| {
pod.enabled_in(&self.current_target)
}).collect::<Vec<&_>>();

// Get a path to our output pods directory (and delete it if it
// exists).
let outdir = self.output_pods_dir();
if outdir.exists() {
try!(fs::remove_dir_all(&outdir)
.map_err(|e| err!("Cannot delete {}: {}", outdir.display(), e)));
}

self.output_helper(pods, Operation::Output, &outdir)
}

/// Export this project (with the specified target applied) as a set
/// of standalone `*.yml` files with no environment variable
/// interpolations and no external dependencies.
pub fn export(&self, export_dir: &Path) -> Result<()> {
let pods = self.pods.iter().filter(|pod| {
pod.enabled_in(&self.current_target)
}).collect::<Vec<&_>>();

// Don't clobber an existing directory.
if export_dir.exists() {
return Err(err!("The directory {} already exists", export_dir.display()));
Expand All @@ -477,8 +495,10 @@ impl Project {
warn!("Exporting project without --default-tags");
}

self.output_helper(Operation::Export, export_dir)
self.output_helper(pods, Operation::Export, export_dir)
}


}

/// Convert to JSON for use in generator templates.
Expand Down