Skip to content

Commit e6e30ba

Browse files
authored
Merge pull request #4636 from ytsssun/host-bootstrap-container-entry-command
Support Entrypoint command for Host and Bootstrap containers
2 parents ca6cfca + 23a27fb commit e6e30ba

File tree

8 files changed

+273
-1
lines changed

8 files changed

+273
-1
lines changed

Release.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,4 +439,5 @@ version = "1.47.0"
439439
]
440440
"(1.46.0, 1.47.0)" = [
441441
"migrate_v1.47.0_container-runtime-concurrent-download-chunk-size.lz4",
442+
"migrate_v1.47.0_host-bootstrap-containers-command-setting.lz4"
442443
]

sources/Cargo.lock

Lines changed: 10 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sources/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ members = [
4343
"settings-migrations/v1.44.0/container-runtime-snapshotter-setting",
4444
"settings-migrations/v1.46.0/kubernetes-static-pods-enabled-setting",
4545
"settings-migrations/v1.47.0/container-runtime-concurrent-download-chunk-size",
46+
"settings-migrations/v1.47.0/host-bootstrap-containers-command-setting",
4647

4748
"settings-plugins/aws-dev",
4849
"settings-plugins/aws-ecs-2",

sources/api/migration/migration-helpers/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ bottlerocket-release.workspace = true
1313
datastore.workspace = true
1414
handlebars.workspace = true
1515
models.workspace = true
16+
regex.workspace = true
1617
serde.workspace = true
1718
serde_json.workspace = true
1819
shlex.workspace = true

sources/api/migration/migration-helpers/src/common_migrations.rs

Lines changed: 202 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::{error, Migration, MigrationData, Result};
2-
use snafu::OptionExt;
2+
use regex::Regex;
3+
use snafu::{OptionExt, ResultExt};
34

45
/// We use this migration when we add settings and want to make sure they're removed before we go
56
/// back to old versions that don't understand them.
@@ -152,6 +153,206 @@ mod test_add_prefixes_migration {
152153
}
153154
}
154155

156+
// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^=
157+
pub struct PrefixSuffix {
158+
pub prefix: &'static str,
159+
pub suffix: &'static str,
160+
}
161+
pub struct AddPrefixSuffixMigration(pub Vec<PrefixSuffix>);
162+
163+
impl Migration for AddPrefixSuffixMigration {
164+
/// New versions must either have a default for the settings or generate them; we don't need to
165+
/// do anything.
166+
fn forward(&mut self, input: MigrationData) -> Result<MigrationData> {
167+
println!(
168+
"AddPrefixSuffixMigration({:?}) has no work to do on upgrade.",
169+
self.0
170+
.iter()
171+
.map(|ps| format!("{}*{}", ps.prefix, ps.suffix))
172+
.collect::<Vec<_>>()
173+
);
174+
Ok(input)
175+
}
176+
177+
/// Older versions don't know about the settings; we remove them so that old versions don't see
178+
/// them and fail deserialization.
179+
fn backward(&mut self, mut input: MigrationData) -> Result<MigrationData> {
180+
let mut compiled_patterns = Vec::new();
181+
for pattern in &self.0 {
182+
let regex_pattern = format!(
183+
r"^{}\.(.+)\.{}$",
184+
regex::escape(pattern.prefix),
185+
regex::escape(pattern.suffix)
186+
);
187+
let regex =
188+
Regex::new(&regex_pattern).context(error::InvalidPrefixSuffixPatternSnafu {
189+
prefix: pattern.prefix,
190+
suffix: pattern.suffix,
191+
})?;
192+
compiled_patterns.push(regex);
193+
}
194+
195+
let settings = input
196+
.data
197+
.keys()
198+
.filter(|k| compiled_patterns.iter().any(|regex| regex.is_match(k)))
199+
.cloned()
200+
.collect::<Vec<_>>();
201+
for setting in settings {
202+
if let Some(data) = input.data.remove(&setting) {
203+
println!("Removed {setting}, which was set to '{data}'");
204+
}
205+
}
206+
Ok(input)
207+
}
208+
}
209+
210+
#[cfg(test)]
211+
mod test_add_prefix_suffix_migration {
212+
use super::{AddPrefixSuffixMigration, PrefixSuffix};
213+
use crate::{Migration, MigrationData};
214+
use maplit::hashmap;
215+
use std::collections::HashMap;
216+
217+
#[test]
218+
fn single_entry() {
219+
let data = MigrationData {
220+
data: hashmap! {
221+
"keep.stuff.like.this".into() => 0.into(),
222+
"remove.stuff.like.this".into() => 0.into(),
223+
"keep.this.too".into() => 0.into(),
224+
"remove.also.like.this".into() => 0.into(),
225+
},
226+
metadata: HashMap::new(),
227+
};
228+
let result = AddPrefixSuffixMigration(vec![PrefixSuffix {
229+
prefix: "remove",
230+
suffix: "this",
231+
}])
232+
.backward(data)
233+
.unwrap();
234+
assert_eq!(
235+
result.data,
236+
hashmap! {
237+
"keep.stuff.like.this".into() => 0.into(),
238+
"keep.this.too".into() => 0.into(),
239+
}
240+
);
241+
}
242+
243+
#[test]
244+
fn compound_suffix() {
245+
let data = MigrationData {
246+
data: hashmap! {
247+
"keep.stuff.like.this".into() => 0.into(),
248+
"remove.stuff.like.this".into() => 0.into(),
249+
"keep.this.too".into() => 0.into(),
250+
"remove.not.this".into() => 0.into(),
251+
},
252+
metadata: HashMap::new(),
253+
};
254+
let result = AddPrefixSuffixMigration(vec![PrefixSuffix {
255+
prefix: "remove",
256+
suffix: "like.this",
257+
}])
258+
.backward(data)
259+
.unwrap();
260+
assert_eq!(
261+
result.data,
262+
hashmap! {
263+
"keep.stuff.like.this".into() => 0.into(),
264+
"keep.this.too".into() => 0.into(),
265+
"remove.not.this".into() => 0.into(),
266+
}
267+
);
268+
}
269+
270+
#[test]
271+
fn multiple_entries() {
272+
let data = MigrationData {
273+
data: hashmap! {
274+
"keep.stuff.like.this".into() => 0.into(),
275+
"remove.stuff.like.this".into() => 0.into(),
276+
"keep.this.too".into() => 0.into(),
277+
"remove.also.this".into() => 0.into(),
278+
"delete.something.here".into() => 0.into(),
279+
},
280+
metadata: HashMap::new(),
281+
};
282+
let result = AddPrefixSuffixMigration(vec![
283+
PrefixSuffix {
284+
prefix: "remove",
285+
suffix: "this",
286+
},
287+
PrefixSuffix {
288+
prefix: "delete",
289+
suffix: "here",
290+
},
291+
])
292+
.backward(data)
293+
.unwrap();
294+
assert_eq!(
295+
result.data,
296+
hashmap! {
297+
"keep.stuff.like.this".into() => 0.into(),
298+
"keep.this.too".into() => 0.into(),
299+
}
300+
);
301+
}
302+
303+
#[test]
304+
fn no_match() {
305+
let data = MigrationData {
306+
data: hashmap! {
307+
"keep.stuff.like.this".into() => 0.into(),
308+
"keep.this.too".into() => 0.into(),
309+
"other.setting.here".into() => 0.into(),
310+
},
311+
metadata: HashMap::new(),
312+
};
313+
let result = AddPrefixSuffixMigration(vec![PrefixSuffix {
314+
prefix: "remove.",
315+
suffix: ".this",
316+
}])
317+
.backward(data)
318+
.unwrap();
319+
assert_eq!(
320+
result.data,
321+
hashmap! {
322+
"keep.stuff.like.this".into() => 0.into(),
323+
"keep.this.too".into() => 0.into(),
324+
"other.setting.here".into() => 0.into(),
325+
}
326+
);
327+
}
328+
329+
#[test]
330+
fn tight_matching() {
331+
let data = MigrationData {
332+
data: hashmap! {
333+
"settings.host-containers.admin.command".into() => 0.into(),
334+
"settings.host-containers.command".into() => 0.into(), // No middle segment
335+
"settings.host-containersadmincommand".into() => 0.into(), // No dots
336+
"keep.this".into() => 0.into(),
337+
},
338+
metadata: HashMap::new(),
339+
};
340+
let result = AddPrefixSuffixMigration(vec![PrefixSuffix {
341+
prefix: "settings.host-containers",
342+
suffix: "command",
343+
}])
344+
.backward(data)
345+
.unwrap();
346+
assert_eq!(
347+
result.data,
348+
hashmap! {
349+
"settings.host-containers.command".into() => 0.into(),
350+
"settings.host-containersadmincommand".into() => 0.into(),
351+
"keep.this".into() => 0.into(),
352+
}
353+
);
354+
}
355+
}
155356
// =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^= =^..^=
156357

157358
/// We use this migration when we remove settings from the model, so the new version doesn't see

sources/api/migration/migration-helpers/src/error.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,18 @@ pub enum Error {
7272
source: Box<datastore::Error>,
7373
},
7474

75+
#[snafu(display(
76+
"Invalid regex pattern for prefix '{}' and suffix '{}': {}",
77+
prefix,
78+
suffix,
79+
source
80+
))]
81+
InvalidPrefixSuffixPattern {
82+
prefix: String,
83+
suffix: String,
84+
source: regex::Error,
85+
},
86+
7587
#[snafu(display("Unable to list transactions in data store: {}", source))]
7688
ListTransactions {
7789
#[snafu(source(from(datastore::Error, Box::new)))]
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[package]
2+
name = "host-bootstrap-containers-command-setting"
3+
version = "0.1.0"
4+
authors = ["Yutong Sun <[email protected]>"]
5+
license = "Apache-2.0 OR MIT"
6+
edition = "2021"
7+
publish = false
8+
# Don't rebuild crate just because of changes to README.
9+
exclude = ["README.md"]
10+
11+
12+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
13+
14+
[dependencies]
15+
migration-helpers.workspace = true
16+
snafu.workspace = true
17+
18+
[dev-dependencies]
19+
maplit.workspace = true
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use migration_helpers::common_migrations::{AddPrefixSuffixMigration, PrefixSuffix};
2+
use migration_helpers::{migrate, Result};
3+
use std::process;
4+
5+
// We added new settings container-runtime-plugins
6+
fn run() -> Result<()> {
7+
migrate(AddPrefixSuffixMigration(vec![
8+
PrefixSuffix {
9+
prefix: "settings.host-containers",
10+
suffix: "command",
11+
},
12+
PrefixSuffix {
13+
prefix: "settings.bootstrap-containers",
14+
suffix: "command",
15+
},
16+
]))
17+
}
18+
19+
// Returning a Result from main makes it print a Debug representation of the error, but with Snafu
20+
// we have nice Display representations of the error, so we wrap "main" (run) and print any error.
21+
// https://github.com/shepmaster/snafu/issues/110
22+
fn main() {
23+
if let Err(e) = run() {
24+
eprintln!("{e}");
25+
process::exit(1);
26+
}
27+
}

0 commit comments

Comments
 (0)