Skip to content

Commit

Permalink
Merge pull request #927 from tjkirch/set-wave-relative
Browse files Browse the repository at this point in the history
updata: allow specifying a start time for waves
  • Loading branch information
tjkirch authored May 15, 2020
2 parents 812e0d0 + e50cbd2 commit db32a93
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 14 deletions.
15 changes: 11 additions & 4 deletions sources/parse-datetime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ pub use error::Error;
type Result<T> = std::result::Result<T, error::Error>;

/// Parses a user-specified datetime, either in full RFC 3339 format, or a shorthand like "in 7
/// days"
/// days" that's taken as an offset from the time the function is run.
pub fn parse_datetime(input: &str) -> Result<DateTime<Utc>> {
// If the user gave an absolute date in a standard format, accept it.
let try_dt: std::result::Result<DateTime<FixedOffset>, chrono::format::ParseError> =
Expand All @@ -57,6 +57,15 @@ pub fn parse_datetime(input: &str) -> Result<DateTime<Utc>> {
return Ok(utc);
}

let offset = parse_offset(input)?;

let now = Utc::now();
let then = now + offset;
Ok(then)
}

/// Parses a user-specified datetime offset in the form of a shorthand like "in 7 days".
pub fn parse_offset(input: &str) -> Result<Duration> {
// Otherwise, pull apart a request like "in 5 days" to get an exact datetime.
let mut parts: Vec<&str> = input.split_whitespace().collect();
ensure!(
Expand Down Expand Up @@ -95,9 +104,7 @@ pub fn parse_datetime(input: &str) -> Result<DateTime<Utc>> {
}
};

let now = Utc::now();
let then = now + duration;
Ok(then)
Ok(duration)
}

#[cfg(test)]
Expand Down
10 changes: 7 additions & 3 deletions sources/updater/update_metadata/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,13 @@ pub enum Error {
#[snafu(display("Migration {} matches regex but missing name", name))]
BadRegexName { name: String },

#[snafu(display("Unable to parse datetime from string '{}': {}", datetime, source))]
BadDateTime {
datetime: String,
#[snafu(display(
"Unable to parse 'start_after' offset from string '{}': {}",
offset,
source
))]
BadOffset {
offset: String,
source: parse_datetime::Error,
},

Expand Down
9 changes: 5 additions & 4 deletions sources/updater/update_metadata/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ mod se;
use crate::error::Result;
use chrono::{DateTime, Duration, Utc};
use lazy_static::lazy_static;
use parse_datetime::parse_datetime;
use parse_datetime::parse_offset;
use rand::{thread_rng, Rng};
use regex::Regex;
use semver::Version;
Expand Down Expand Up @@ -293,6 +293,7 @@ impl Manifest {
variant: String,
arch: String,
image_version: Version,
start_at: DateTime<Utc>,
waves: &UpdateWaves,
) -> Result<usize> {
let matching = self.get_matching_updates(variant, arch, image_version);
Expand All @@ -311,10 +312,10 @@ impl Manifest {
}
);

let start_time = parse_datetime(&wave.start_after).context(error::BadDateTime {
datetime: &wave.start_after,
let offset = parse_offset(&wave.start_after).context(error::BadOffset {
offset: &wave.start_after,
})?;
update.waves.insert(seed, start_time);
update.waves.insert(seed, start_at + offset);

// Get the appropriate seed from the percentage given
// First get the percentage as a decimal,
Expand Down
27 changes: 24 additions & 3 deletions sources/updater/updog/src/bin/updata.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ mod error;
extern crate log;

use crate::error::Result;
use chrono::{DateTime, Utc};
use semver::Version;
use simplelog::{Config as LogConfig, LevelFilter, TermLogger, TerminalMode};
use snafu::{ErrorCompat, OptionExt, ResultExt};
Expand Down Expand Up @@ -143,6 +144,19 @@ struct WaveArgs {
// file that contains wave structure
#[structopt(short = "w", long = "wave-file", conflicts_with_all = &["bound", "start"])]
wave_file: Option<PathBuf>,

// The user can specify the starting point for the the wave offsets, if they don't want them to
// start when they run this tool.
//
// For example, let's say you have a wave with start_after "1 hour" and you run this tool at
// 2020-02-02 02:00. If you don't specify --start-at, it will assume "now", and the wave will
// start 1 hour from then, i.e. 2020-02-02 03:00.
//
// If instead you specify --start-at "2020-02-02T10:00:00Z" then the first wave will start 1
// hour after that, i.e. 2020-02-02 11:00.
/// Wave offsets will be relative to this RFC3339 datetime, instead of right now
#[structopt(long = "start-at")]
start_at: Option<DateTime<Utc>>,
}

impl WaveArgs {
Expand All @@ -154,8 +168,15 @@ impl WaveArgs {
fs::read_to_string(&wave_file).context(error::ConfigRead { path: &wave_file })?;
let waves: UpdateWaves =
toml::from_str(&wave_str).context(error::ConfigParse { path: &wave_file })?;
let num_matching =
manifest.set_waves(self.variant, self.arch, self.image_version, &waves)?;

let start_at = self.start_at.unwrap_or(Utc::now());
let num_matching = manifest.set_waves(
self.variant,
self.arch,
self.image_version,
start_at,
&waves,
)?;

if num_matching > 1 {
warn!("Multiple matching updates for wave - this is weird but not a disaster");
Expand Down Expand Up @@ -294,7 +315,7 @@ mod tests {
let image_version = manifest.updates[0].version.clone();

assert!(manifest
.set_waves(variant, arch, image_version, &waves)
.set_waves(variant, arch, image_version, Utc::now(), &waves)
.is_ok());

assert!(manifest.updates[0].waves.len() == 4)
Expand Down

0 comments on commit db32a93

Please sign in to comment.