Skip to content

Commit 7b6b6c2

Browse files
committed
updog and migrator: signed migrations
1 parent 722ad6b commit 7b6b6c2

File tree

11 files changed

+485
-158
lines changed

11 files changed

+485
-158
lines changed

packages/os/migrator.service

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Description=Bottlerocket data store migrator
33

44
[Service]
55
Type=oneshot
6-
ExecStart=/usr/bin/migrator --datastore-path /var/lib/bottlerocket/datastore/current --migration-directories /var/lib/bottlerocket-migrations --migrate-to-version-from-os-release
6+
ExecStart=/usr/bin/migrator --datastore-path /var/lib/bottlerocket/datastore/current --migration-directory /var/lib/bottlerocket-migrations --root-path /usr/share/updog/root.json --metadata-directory /var/cache/bottlerocket-metadata --migrate-to-version-from-os-release
77
RemainAfterExit=true
88
StandardError=journal+console
99

sources/Cargo.lock

Lines changed: 15 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sources/api/migration/migrator/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,18 @@ build = "build.rs"
1111
bottlerocket-release = { path = "../../../bottlerocket-release" }
1212
lazy_static = "1.2"
1313
log = "0.4"
14+
lz4 = "1.23.1"
1415
nix = "0.17"
16+
pentacle = "0.1.1"
1517
rand = { version = "0.7", default-features = false, features = ["std"] }
1618
regex = "1.1"
1719
semver = "0.9"
1820
simplelog = "0.7"
1921
snafu = "0.6"
22+
tempfile = "3.1.0"
23+
tough = "0.6.0"
2024
update_metadata = { path = "../../../updater/update_metadata" }
25+
url = "2.1.1"
2126

2227
[build-dependencies]
2328
cargo-readme = "3.1"

sources/api/migration/migrator/src/args.rs

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ fn usage() -> ! {
1515
eprintln!(
1616
r"Usage: {}
1717
--datastore-path PATH
18-
--migration-directories PATH[:PATH:PATH...]
18+
--migration-directory PATH
19+
--root-path PATH
20+
--metadata-directory PATH
1921
(--migrate-to-version x.y | --migrate-to-version-from-os-release)
2022
[ --no-color ]
2123
[ --log-level trace|debug|info|warn|error ]",
@@ -34,8 +36,10 @@ fn usage_msg<S: AsRef<str>>(msg: S) -> ! {
3436
pub(crate) struct Args {
3537
pub(crate) datastore_path: PathBuf,
3638
pub(crate) log_level: LevelFilter,
37-
pub(crate) migration_directories: Vec<PathBuf>,
39+
pub(crate) migration_directory: PathBuf,
3840
pub(crate) migrate_to_version: Version,
41+
pub(crate) root_path: PathBuf,
42+
pub(crate) metadata_directory: PathBuf,
3943
}
4044

4145
impl Args {
@@ -44,8 +48,10 @@ impl Args {
4448
// Required parameters.
4549
let mut datastore_path = None;
4650
let mut log_level = None;
47-
let mut migration_directories = None;
51+
let mut migration_directory = None;
4852
let mut migrate_to_version = None;
53+
let mut root_path = None;
54+
let mut metadata_path = None;
4955

5056
let mut iter = args.skip(1);
5157
while let Some(arg) = iter.next() {
@@ -84,16 +90,12 @@ impl Args {
8490
}));
8591
}
8692

87-
"--migration-directories" => {
88-
let paths_str = iter.next().unwrap_or_else(|| {
89-
usage_msg("Did not give argument to --migration-directories")
93+
"--migration-directory" => {
94+
let path_str = iter.next().unwrap_or_else(|| {
95+
usage_msg("Did not give argument to --migration-directory")
9096
});
91-
trace!("Given --migration-directories: {}", paths_str);
92-
let paths: Vec<_> = paths_str.split(':').map(PathBuf::from).collect();
93-
if paths.is_empty() {
94-
usage_msg("Found no paths in argument to --migration-directories");
95-
}
96-
migration_directories = Some(paths);
97+
trace!("Given --migration-directory: {}", path_str);
98+
migration_directory = Some(PathBuf::from(path_str));
9799
}
98100

99101
"--migrate-to-version" => {
@@ -114,15 +116,40 @@ impl Args {
114116
migrate_to_version = Some(br.version_id)
115117
}
116118

117-
_ => usage(),
119+
"--root-path" => {
120+
let path_str = iter
121+
.next()
122+
.unwrap_or_else(|| usage_msg("Did not give argument to --root-path"));
123+
trace!("Given --root-path: {}", path_str);
124+
root_path = Some(PathBuf::from(path_str));
125+
}
126+
127+
"--metadata-directory" => {
128+
let path_str = iter.next().unwrap_or_else(|| {
129+
usage_msg("Did not give argument to --metadata-directory")
130+
});
131+
trace!("Given --metadata-directory: {}", path_str);
132+
metadata_path = Some(PathBuf::from(path_str));
133+
}
134+
_ => usage_msg(format!("Unable to parse input '{}'", arg)),
118135
}
119136
}
120137

121138
Self {
122-
datastore_path: datastore_path.unwrap_or_else(|| usage()),
139+
datastore_path: datastore_path
140+
.unwrap_or_else(|| usage_msg("--datastore-path must be specified")),
123141
log_level: log_level.unwrap_or_else(|| LevelFilter::Info),
124-
migration_directories: migration_directories.unwrap_or_else(|| usage()),
125-
migrate_to_version: migrate_to_version.unwrap_or_else(|| usage()),
142+
migration_directory: migration_directory
143+
.unwrap_or_else(|| usage_msg("--migration-directory must be specified")),
144+
migrate_to_version: migrate_to_version.unwrap_or_else(|| {
145+
usage_msg(
146+
"Desired version could not be determined; pass --migrate-to-version or \
147+
--migrate-to-version-from-os-release",
148+
)
149+
}),
150+
root_path: root_path.unwrap_or_else(|| usage_msg("--root-path must be specified")),
151+
metadata_directory: metadata_path
152+
.unwrap_or_else(|| usage_msg("--metadata-directory must be specified")),
126153
}
127154
}
128155
}

sources/api/migration/migrator/src/direction.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//! is moving forward to a new version or rolling back to a previous version.
33
44
use semver::Version;
5-
use std::cmp::Ordering;
5+
use std::cmp::{Ord, Ordering};
66
use std::fmt;
77

88
/// Direction represents whether we're moving forward toward a newer version, or rolling back to
@@ -45,14 +45,20 @@ mod test {
4545
let v02 = Version::new(0, 0, 2);
4646
let v10 = Version::new(0, 1, 0);
4747

48-
assert_eq!(Direction::from_versions(&v01, &v02), Some(Direction::Forward));
48+
assert_eq!(
49+
Direction::from_versions(&v01, &v02),
50+
Some(Direction::Forward)
51+
);
4952
assert_eq!(
5053
Direction::from_versions(&v02, &v01),
5154
Some(Direction::Backward)
5255
);
5356
assert_eq!(Direction::from_versions(&v01, &v01), None);
5457

55-
assert_eq!(Direction::from_versions(&v02, &v10), Some(Direction::Forward));
58+
assert_eq!(
59+
Direction::from_versions(&v02, &v10),
60+
Some(Direction::Forward)
61+
);
5662
assert_eq!(
5763
Direction::from_versions(&v10, &v02),
5864
Some(Direction::Backward)

sources/api/migration/migrator/src/error.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ use semver::Version;
44
use snafu::Snafu;
55
use std::io;
66
use std::path::PathBuf;
7-
use std::process::{Command, Output};
7+
use std::process::Output;
88

99
/// Error contains the errors that can happen during migration.
1010
#[derive(Debug, Snafu)]
@@ -13,6 +13,9 @@ pub(crate) enum Error {
1313
#[snafu(display("Internal error: {}", msg))]
1414
Internal { msg: String },
1515

16+
#[snafu(display("Unable to create tempdir for tough datastore: '{}'", source))]
17+
CreateToughTempDir { source: std::io::Error },
18+
1619
#[snafu(display("Data store path '{}' contains invalid UTF-8", path.display()))]
1720
DataStorePathNotUTF8 { path: PathBuf },
1821

@@ -22,6 +25,14 @@ pub(crate) enum Error {
2225
#[snafu(display("Data store link '{}' points to /", path.display()))]
2326
DataStoreLinkToRoot { path: PathBuf },
2427

28+
#[snafu(display("Unable to create URL from path '{}'", path.display()))]
29+
DirectoryUrl { path: PathBuf },
30+
31+
#[snafu(display("Error finding migration: {}", source))]
32+
FindMigrations {
33+
source: update_metadata::error::Error,
34+
},
35+
2536
#[snafu(display("Data store path '{}' contains invalid version: {}", path.display(), source))]
2637
InvalidDataStoreVersion {
2738
path: PathBuf,
@@ -37,8 +48,11 @@ pub(crate) enum Error {
3748
#[snafu(display("Data store for new version {} already exists at {}", version, path.display()))]
3849
NewVersionAlreadyExists { version: Version, path: PathBuf },
3950

40-
#[snafu(display("Unable to start migration command {:?} - {}", command, source))]
41-
StartMigration { command: Command, source: io::Error },
51+
#[snafu(display("Unable to seal migration command: {}", source))]
52+
SealMigration { source: std::io::Error },
53+
54+
#[snafu(display("Unable to start migration command: {}", source))]
55+
StartMigration { source: std::io::Error },
4256

4357
#[snafu(display("Migration returned '{}' - stderr: {}",
4458
output.status.code()
@@ -59,9 +73,38 @@ pub(crate) enum Error {
5973
#[snafu(display("Failed listing migration directory '{}': {}", dir.display(), source))]
6074
ListMigrations { dir: PathBuf, source: io::Error },
6175

76+
#[snafu(display("Error loading manifest: {}", source))]
77+
LoadManifest {
78+
source: update_metadata::error::Error,
79+
},
80+
81+
#[snafu(display("Error loading migration '{}': {}", migration, source))]
82+
LoadMigration {
83+
migration: String,
84+
source: tough::error::Error,
85+
},
86+
87+
#[snafu(display("Failed to decode LZ4-compressed migration {}: {}", migration, source))]
88+
Lz4Decode {
89+
migration: String,
90+
source: std::io::Error,
91+
},
92+
93+
#[snafu(display("Migration '{}' not found", migration))]
94+
MigrationNotFound { migration: String },
95+
96+
#[snafu(display("Failed to open trusted root metadata file {}: {}", path.display(), source))]
97+
OpenRoot {
98+
path: PathBuf,
99+
source: std::io::Error,
100+
},
101+
62102
#[snafu(display("Failed reading migration directory entry: {}", source))]
63103
ReadMigrationEntry { source: io::Error },
64104

105+
#[snafu(display("Failed to load TUF repo: {}", source))]
106+
RepoLoad { source: tough::error::Error },
107+
65108
#[snafu(display("Failed reading metadata of '{}': {}", path.display(), source))]
66109
PathMetadata { path: PathBuf, source: io::Error },
67110

@@ -70,9 +113,6 @@ pub(crate) enum Error {
70113

71114
#[snafu(display("Migration path '{}' contains invalid UTF-8", path.display()))]
72115
MigrationNameNotUTF8 { path: PathBuf },
73-
74-
#[snafu(display("Logger setup error: {}", source))]
75-
Logger { source: simplelog::TermLogError },
76116
}
77117

78118
/// Result alias containing our Error type.

0 commit comments

Comments
 (0)