We want to be able to autoupgrade fireguard (remember that the docker container version is synced with the running executable version).
To do this there are a bunch of things to do:
- Figure out code to upgrade binary on the fly through double-fork, like in this aberration:
extern crate fork;
extern crate nix;
use nix::unistd::{fork, ForkResult};
use fork::{daemon, Fork};
use std::thread;
use std::time::Duration;
use nix::sys::signal;
use nix::unistd::Pid;
use std::env;
use std::fs::copy;
use std::os::unix::process::CommandExt;
use std::process::{self, Command};
struct Version {
v: usize,
}
fn main() {
let args: Vec<String> = env::args().collect();
let v = Version { v: 42 };
if args.contains(&"--version".to_string()) {
println!("{}", v.v);
process::exit(0);
}
let old_pid = if args.contains(&"--old-pid".to_string()) {
Some(args[2].clone())
} else {
None
};
let old_bin = if args.contains(&"--old-bin".to_string()) {
Some(args[4].clone())
} else {
None
};
println!("Running catoblepa version {}", v.v);
let version = Command::new("/tmp/catoblepa")
.arg("--version")
.stdout(process::Stdio::piped())
.spawn()
.unwrap()
.wait_with_output()
.unwrap()
.stdout;
let version = String::from_utf8_lossy(&version)
.trim()
.parse::<usize>()
.unwrap();
if version > v.v {
println!("Running on old executable");
println!("New catoblepa detected, version {}", version);
if let Ok(Fork::Child) = daemon(true, true) {
println!("I am inside the double fork");
let result = Command::new("/tmp/catoblepa")
.arg("--old-pid")
.arg(&process::id().to_string())
.arg("--old-bin")
.arg("./target/debug/catoblepa")
.spawn().unwrap().wait_with_output().unwrap().stdout;
println!("Post daemonize: {}", String::from_utf8_lossy(&result));
}
println!("I am at the end of the old exec");
} else {
println!("Running new executable from /tmp/catoblepa");
match old_pid {
Some(pid) => {
println!("We are killing the old blepa, pid: {}", pid);
signal::kill(Pid::from_raw(pid.parse::<i32>().unwrap()), signal::SIGINT).unwrap();
}
None => {
println!("We are NOT killing the old blepa");
}
}
thread::sleep(Duration::from_secs(2));
println!("Copying /tmp/catoblepa to {:?}", old_bin);
let bytes = copy("/tmp/catoblepa", &old_bin.unwrap()).unwrap();
println!("Copied {} new catoblepa", bytes);
}
process::exit(0);
}
- Implement command
upgrade with subcommands download, check, apply
- Subcommand
check: find latest release on github and validate the semver has changed curl -s https://api.github.com/repos/blackmesalab/fireguard/releases/latest |jq
- Subcommand
download: detect host triple and download latest release on github for the triple
- Subcommand
apply: Use the HORROR above and replace the binary after forking it twice wabbla bballabbab blu....
- Automate apply using a background thread with a jitter. If we say that the upgrade SLA is 12 hours, we check and possibly upgrade after 12/2 hour (6) + a jitter between 1 minute and 6 hours.
We want to be able to autoupgrade fireguard (remember that the docker container version is synced with the running executable version).
To do this there are a bunch of things to do:
upgradewith subcommandsdownload,check,applycheck: find latest release on github and validate the semver has changedcurl -s https://api.github.com/repos/blackmesalab/fireguard/releases/latest |jqdownload: detect host triple and download latest release on github for the tripleapply: Use the HORROR above and replace the binary after forking it twice wabbla bballabbab blu....