Vagrant (#422)
This commit is contained in:
committed by
GitHub
parent
05612b51f2
commit
ddd10981b4
@@ -76,6 +76,7 @@ pub enum Step {
|
|||||||
Tldr,
|
Tldr,
|
||||||
Wsl,
|
Wsl,
|
||||||
Tmux,
|
Tmux,
|
||||||
|
Vagrant,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Debug)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
@@ -86,6 +87,12 @@ pub struct Git {
|
|||||||
pull_predefined: Option<bool>,
|
pull_predefined: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default, Debug)]
|
||||||
|
pub struct Vagrant {
|
||||||
|
directories: Option<Vec<String>>,
|
||||||
|
power_on: Option<bool>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Deserialize, Default, Debug)]
|
#[derive(Deserialize, Default, Debug)]
|
||||||
pub struct Windows {
|
pub struct Windows {
|
||||||
accept_all_updates: Option<bool>,
|
accept_all_updates: Option<bool>,
|
||||||
@@ -136,6 +143,7 @@ pub struct ConfigFile {
|
|||||||
linux: Option<Linux>,
|
linux: Option<Linux>,
|
||||||
git: Option<Git>,
|
git: Option<Git>,
|
||||||
windows: Option<Windows>,
|
windows: Option<Windows>,
|
||||||
|
vagrant: Option<Vagrant>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ConfigFile {
|
impl ConfigFile {
|
||||||
@@ -487,6 +495,19 @@ impl Config {
|
|||||||
self.config_file.git.as_ref().and_then(|git| git.max_concurrency)
|
self.config_file.git.as_ref().and_then(|git| git.max_concurrency)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Should we power on vagrant boxes if needed
|
||||||
|
pub fn vagrant_power_on(&self) -> Option<bool> {
|
||||||
|
self.config_file.vagrant.as_ref().and_then(|vagrant| vagrant.power_on)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Vagrant directories
|
||||||
|
pub fn vagrant_directories(&self) -> Option<&Vec<String>> {
|
||||||
|
self.config_file
|
||||||
|
.vagrant
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|vagrant| vagrant.directories.as_ref())
|
||||||
|
}
|
||||||
|
|
||||||
/// Extra yay arguments
|
/// Extra yay arguments
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn enable_tlmgr_linux(&self) -> bool {
|
pub fn enable_tlmgr_linux(&self) -> bool {
|
||||||
|
|||||||
@@ -388,6 +388,10 @@ fn run() -> Result<()> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config.should_run(Step::Vagrant) {
|
||||||
|
runner.execute("Vagrant", || vagrant::topgrade_vagrant_boxes(&ctx))?;
|
||||||
|
}
|
||||||
|
|
||||||
if !runner.report().data().is_empty() {
|
if !runner.report().data().is_empty() {
|
||||||
print_separator("Summary");
|
print_separator("Summary");
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ pub mod os;
|
|||||||
pub mod powershell;
|
pub mod powershell;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub mod tmux;
|
pub mod tmux;
|
||||||
|
pub mod vagrant;
|
||||||
pub mod vim;
|
pub mod vim;
|
||||||
#[cfg(unix)]
|
#[cfg(unix)]
|
||||||
pub mod zsh;
|
pub mod zsh;
|
||||||
|
|||||||
151
src/steps/vagrant.rs
Normal file
151
src/steps/vagrant.rs
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
use crate::execution_context::ExecutionContext;
|
||||||
|
use crate::executor::CommandExt;
|
||||||
|
use crate::terminal::print_separator;
|
||||||
|
use crate::utils;
|
||||||
|
use anyhow::Result;
|
||||||
|
use log::debug;
|
||||||
|
use std::path::{Path, PathBuf};
|
||||||
|
use std::process::Command;
|
||||||
|
use std::{fmt::Display, str::FromStr};
|
||||||
|
use strum::EnumString;
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, EnumString)]
|
||||||
|
#[strum(serialize_all = "lowercase")]
|
||||||
|
enum BoxStatus {
|
||||||
|
PowerOff,
|
||||||
|
Running,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BoxStatus {
|
||||||
|
fn powered_on(self) -> bool {
|
||||||
|
match self {
|
||||||
|
BoxStatus::PowerOff => false,
|
||||||
|
BoxStatus::Running => true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct VagrantBox<'a> {
|
||||||
|
path: &'a str,
|
||||||
|
name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Display for VagrantBox<'a> {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
write!(f, "{} @ {}", self.name, self.path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Vagrant {
|
||||||
|
path: PathBuf,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Vagrant {
|
||||||
|
fn get_boxes<'a>(&self, directory: &'a str) -> Result<Vec<(VagrantBox<'a>, BoxStatus)>> {
|
||||||
|
let output = Command::new(&self.path)
|
||||||
|
.arg("status")
|
||||||
|
.current_dir(directory)
|
||||||
|
.check_output()?;
|
||||||
|
debug!("Vagrant output in {}: {}", directory, output);
|
||||||
|
|
||||||
|
let boxes = output
|
||||||
|
.split('\n')
|
||||||
|
.skip(2)
|
||||||
|
.take_while(|line| !(line.is_empty() || line.starts_with('\r')))
|
||||||
|
.map(|line| {
|
||||||
|
debug!("Vagrant line: {:?}", line);
|
||||||
|
let mut elements = line.split_whitespace();
|
||||||
|
let vagrant_box = VagrantBox {
|
||||||
|
name: elements.next().unwrap().to_string(),
|
||||||
|
path: directory,
|
||||||
|
};
|
||||||
|
let box_status = BoxStatus::from_str(elements.next().unwrap()).unwrap();
|
||||||
|
debug!("{:?}: {:?}", vagrant_box, box_status);
|
||||||
|
(vagrant_box, box_status)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(boxes)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn temporary_power_on<'a>(
|
||||||
|
&'a self,
|
||||||
|
vagrant_box: &'a VagrantBox,
|
||||||
|
ctx: &'a ExecutionContext,
|
||||||
|
) -> Result<TemporaryPowerOn<'a>> {
|
||||||
|
TemporaryPowerOn::create(&self.path, vagrant_box, ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct TemporaryPowerOn<'a> {
|
||||||
|
vagrant: &'a Path,
|
||||||
|
vagrant_box: &'a VagrantBox<'a>,
|
||||||
|
ctx: &'a ExecutionContext<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TemporaryPowerOn<'a> {
|
||||||
|
fn create(vagrant: &'a Path, vagrant_box: &'a VagrantBox<'a>, ctx: &'a ExecutionContext<'a>) -> Result<Self> {
|
||||||
|
println!("Powering on {}", vagrant_box);
|
||||||
|
ctx.run_type()
|
||||||
|
.execute(vagrant)
|
||||||
|
.args(&["up", &vagrant_box.name])
|
||||||
|
.current_dir(vagrant_box.path)
|
||||||
|
.check_run()?;
|
||||||
|
Ok(TemporaryPowerOn {
|
||||||
|
vagrant,
|
||||||
|
vagrant_box,
|
||||||
|
ctx,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for TemporaryPowerOn<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
println!("Powering off {}", self.vagrant_box);
|
||||||
|
self.ctx
|
||||||
|
.run_type()
|
||||||
|
.execute(self.vagrant)
|
||||||
|
.args(&["halt", &self.vagrant_box.name])
|
||||||
|
.current_dir(self.vagrant_box.path)
|
||||||
|
.check_run()
|
||||||
|
.ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn topgrade_vagrant_boxes(ctx: &ExecutionContext) -> Result<()> {
|
||||||
|
let directories = utils::require_option(ctx.config().vagrant_directories())?;
|
||||||
|
let vagrant = Vagrant {
|
||||||
|
path: utils::require("vagrant")?,
|
||||||
|
};
|
||||||
|
|
||||||
|
print_separator("Vagrant");
|
||||||
|
|
||||||
|
for directory in directories {
|
||||||
|
let boxes = vagrant.get_boxes(directory)?;
|
||||||
|
debug!("{:?}", boxes);
|
||||||
|
for (vagrant_box, status) in boxes {
|
||||||
|
let mut _poweron = None;
|
||||||
|
if !status.powered_on() {
|
||||||
|
if !(ctx.config().vagrant_power_on().unwrap_or(true)) {
|
||||||
|
debug!("Skipping powered off box {}", vagrant_box);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
_poweron = Some(vagrant.temporary_power_on(&vagrant_box, ctx)?);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("Running Topgrade in {} @ {}", vagrant_box, directory);
|
||||||
|
let mut command = format!("env TOPGRADE_PREFIX={} topgrade", vagrant_box.name);
|
||||||
|
if ctx.config().yes() {
|
||||||
|
command.push_str(" -y");
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.run_type()
|
||||||
|
.execute(&vagrant.path)
|
||||||
|
.args(&["ssh", "-c", &command])
|
||||||
|
.check_run()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user