Skip to content

Commit

Permalink
prairiedog: adjust to leverage a rendered config file
Browse files Browse the repository at this point in the history
Changes prairiedog to read from /etc/prairiedog.toml which is generated
automatically from the settings.
  • Loading branch information
jmt-lab committed Feb 7, 2024
1 parent c325a08 commit 1f8500c
Show file tree
Hide file tree
Showing 15 changed files with 147 additions and 54 deletions.
6 changes: 5 additions & 1 deletion Release.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version = "1.19.1"
version = "1.19.2"

[migrations]
"(0.3.1, 0.3.2)" = ["migrate_v0.3.2_admin-container-v0-5-0.lz4"]
Expand Down Expand Up @@ -270,3 +270,7 @@ version = "1.19.1"
"migrate_v1.19.1_aws-control-container-v0-7-8.lz4",
"migrate_v1.19.1_public-control-container-v0-7-8.lz4",
]
"(1.19.1, 1.19.2)" = [
"migrate_v1.19.2_prairiedog-config-file-v0-1-0.lz4",
"migrate_v1.19.2_prairiedog-services-cfg-v0-1-0.lz4"
]
2 changes: 1 addition & 1 deletion Twoliter.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
schema-version = 1
release-version = "1.19.1"
release-version = "1.19.2"

[sdk]
registry = "public.ecr.aws/bottlerocket"
Expand Down
4 changes: 3 additions & 1 deletion packages/os/os.spec
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ Source12: 00-resolved.conf
%if %{with k8s_runtime}
Source13: cis-checks-k8s-metadata-json
%endif
Source15: prairiedog-toml

# 1xx sources: systemd units
Source100: apiserver.service
Expand Down Expand Up @@ -472,7 +473,7 @@ install -d %{buildroot}%{_cross_datadir}/updog
install -p -m 0644 %{_cross_repo_root_json} %{buildroot}%{_cross_datadir}/updog

install -d %{buildroot}%{_cross_templatedir}
install -p -m 0644 %{S:5} %{S:6} %{S:7} %{S:8} %{buildroot}%{_cross_templatedir}
install -p -m 0644 %{S:5} %{S:6} %{S:7} %{S:8} %{S:15} %{buildroot}%{_cross_templatedir}

install -d %{buildroot}%{_cross_unitdir}
install -p -m 0644 \
Expand Down Expand Up @@ -681,6 +682,7 @@ install -p -m 0644 %{S:400} %{S:401} %{S:402} %{buildroot}%{_cross_licensedir}
%files -n %{_cross_os}prairiedog
%{_cross_bindir}/prairiedog
%{_cross_unitdir}/reboot-if-required.service
%{_cross_templatedir}/prairiedog-toml

%files -n %{_cross_os}certdog
%{_cross_bindir}/certdog
Expand Down
22 changes: 22 additions & 0 deletions packages/os/prairiedog-toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
[required-extensions]
boot = "v1"
+++
{{#if settings.boot}}
{{#if settings.boot.reboot-to-reconcile}}
reboot-to-reconcile = {{settings.boot.reboot-to-reconcile}}

{{/if}}
{{#if settings.boot.kernel}}
[kernel]
{{#each settings.boot.kernel}}
"{{@key}}" = [ {{#each this}}"{{this}}",{{/each}} ]
{{/each}}

{{/if}}
{{#if settings.boot.init}}
[init]
{{#each settings.boot.init}}
"{{@key}}" = [ {{#each this}}"{{this}}",{{/each}} ]
{{/each}}
{{/if}}
{{/if}}
16 changes: 15 additions & 1 deletion sources/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions sources/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ members = [
"api/migration/migrations/v1.19.1/public-admin-container-v0-11-4",
"api/migration/migrations/v1.19.1/aws-control-container-v0-7-8",
"api/migration/migrations/v1.19.1/public-control-container-v0-7-8",
"api/migration/migrations/v1.19.2/prairiedog-config-file-v0-1-0",
"api/migration/migrations/v1.19.2/prairiedog-services-cfg-v0-1-0",

"bloodhound",

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "prairiedog-config-file-v0-1-0"
version = "0.1.0"
authors = ["Jarrett Tierney <[email protected]>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
publish = false
exclude = ["README.md"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
migration-helpers = { path = "../../../migration-helpers", version = "0.1.0" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
use migration_helpers::common_migrations::AddPrefixesMigration;
use migration_helpers::{migrate, Result};
use std::process;

fn run() -> Result<()> {
migrate(AddPrefixesMigration(vec![
"configuration-files.prairiedog-toml",
]))
}

fn main() {
if let Err(e) = run() {
eprintln!("{}", e);
process::exit(1);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "prairiedog-services-cfg-v0-1-0"
version = "0.1.0"
authors = ["Jarrett Tierney <[email protected]>"]
license = "Apache-2.0 OR MIT"
edition = "2021"
publish = false
exclude = ["README.md"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
migration-helpers = { path = "../../../migration-helpers", version = "0.1.0" }
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use migration_helpers::common_migrations::{ListReplacement, ReplaceListsMigration};
use migration_helpers::{migrate, Result};
use std::process;

fn run() -> Result<()> {
migrate(ReplaceListsMigration(vec![ListReplacement {
setting: "services.bootconfig.configuration-files",
old_vals: &[],
new_vals: &["prairiedog-toml"],
}]))
}

fn main() {
if let Err(e) = run() {
eprintln!("{}", e);
process::exit(1);
}
}
2 changes: 1 addition & 1 deletion sources/api/prairiedog/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ signpost = { path = "../../updater/signpost", version = "0.1" }
simplelog = "0.12"
snafu = "0.7"
serde_json = "1"
tokio = { version = "~1.32", default-features = false, features = ["macros", "rt-multi-thread"] } # LTS
toml = "0.8"

[dev-dependencies]
maplit = "1"
Expand Down
45 changes: 16 additions & 29 deletions sources/api/prairiedog/src/bootconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use model::BootSettings;
use snafu::{ensure, ResultExt};
use std::collections::HashMap;
use std::convert::TryInto;
use std::{fs, io};
use std::path::Path;
use tokio::io;

// Boot config related consts
const BOOTCONFIG_INITRD_PATH: &str = "/var/lib/bottlerocket/bootconfig.data";
Expand Down Expand Up @@ -66,11 +66,11 @@ fn serialize_boot_settings_to_boot_config(boot_settings: &BootSettings) -> Resul
}

/// Queries Bottlerocket boot settings and generates initrd image file with boot config as the only data
pub(crate) async fn generate_boot_config<P>(socket_path: P) -> Result<()>
pub(crate) fn generate_boot_config<P>(config_path: P) -> Result<()>
where
P: AsRef<Path>,
{
let bootconfig_bytes = match get_boot_config_settings(socket_path).await? {
let bootconfig_bytes = match get_boot_config_settings(config_path)? {
Some(boot_settings) => {
info!("Generating initrd boot config from boot settings");
trace!("Boot settings: {:?}", boot_settings);
Expand All @@ -86,36 +86,25 @@ where
};
let initrd = generate_initrd(&bootconfig_bytes)?;
trace!("Writing initrd image file: {:?}", initrd);
tokio::fs::write(BOOTCONFIG_INITRD_PATH, &initrd)
.await
.context(error::WriteInitrdSnafu)?;
fs::write(BOOTCONFIG_INITRD_PATH, &initrd).context(error::WriteInitrdSnafu)?;
Ok(())
}

/// Retrieves boot config related Bottlerocket settings. If they don't exist in the settings model,
/// we return `None` instead.
async fn get_boot_config_settings<P>(socket_path: P) -> Result<Option<BootSettings>>
fn get_boot_config_settings<P>(config_path: P) -> Result<Option<BootSettings>>
where
P: AsRef<Path>,
{
let uri = "/settings";
let settings: serde_json::Value =
schnauzer::v1::get_json(socket_path, uri, Some(("prefix", "boot")))
.await
.context(error::RetrieveSettingsSnafu)?;

match settings.get("boot") {
None => Ok(None),
Some(boot_settings_val) => Ok(Some(
serde_json::from_value(boot_settings_val.to_owned())
.context(error::BootSettingsFromJsonValueSnafu)?,
)),
}
let config_str = fs::read_to_string(config_path.as_ref()).context(error::ReadFileSnafu {
path: config_path.as_ref().to_path_buf(),
})?;
toml::from_str(config_str.as_str()).context(error::InputTomlSnafu)
}

/// Reads `/proc/bootconfig`. Not having any boot config is ignored.
async fn read_proc_bootconfig() -> Result<Option<String>> {
match tokio::fs::read_to_string(PROC_BOOTCONFIG).await {
fn read_proc_bootconfig() -> Result<Option<String>> {
match fs::read_to_string(PROC_BOOTCONFIG) {
Ok(s) => Ok(Some(s)),
Err(e) => {
// If there's no `/proc/bootconfig`, then the user hasn't provisioned any kernel boot configuration.
Expand All @@ -131,8 +120,8 @@ async fn read_proc_bootconfig() -> Result<Option<String>> {
}

/// Reads `/proc/bootconfig` and populates the Bottlerocket boot settings based on the existing boot config data
pub(crate) async fn generate_boot_settings() -> Result<()> {
if let Some(proc_bootconfig) = read_proc_bootconfig().await? {
pub(crate) fn generate_boot_settings() -> Result<()> {
if let Some(proc_bootconfig) = read_proc_bootconfig()? {
debug!(
"Generating kernel boot config settings from `{}`",
PROC_BOOTCONFIG
Expand Down Expand Up @@ -275,18 +264,16 @@ fn boot_config_to_boot_settings_json(bootconfig_str: &str) -> Result<String> {
}

/// Decides whether the host should be rebooted to have its boot settings take effect
pub(crate) async fn is_reboot_required<P>(socket_path: P) -> Result<bool>
pub(crate) fn is_reboot_required<P>(config_path: P) -> Result<bool>
where
P: AsRef<Path>,
{
let old_boot_settings = match read_proc_bootconfig().await? {
let old_boot_settings = match read_proc_bootconfig()? {
Some(proc_bootconfig) => parse_boot_config_to_boot_settings(&proc_bootconfig)?,
None => DEFAULT_BOOT_SETTINGS,
};

let new_boot_settings = get_boot_config_settings(socket_path)
.await?
.unwrap_or(DEFAULT_BOOT_SETTINGS);
let new_boot_settings = get_boot_config_settings(config_path)?.unwrap_or(DEFAULT_BOOT_SETTINGS);

let reboot_required = if new_boot_settings.reboot_to_reconcile.unwrap_or(false) {
boot_settings_change_requires_reboot(&old_boot_settings, &new_boot_settings)
Expand Down
9 changes: 3 additions & 6 deletions sources/api/prairiedog/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,6 @@ pub(super) enum Error {
path: PathBuf,
},

#[snafu(display("Failed to retrieve settings: {}", source))]
RetrieveSettings { source: schnauzer::v1::Error },

#[snafu(display("Failed to convert usize to u32: {}", source))]
UsizeToU32 { source: std::num::TryFromIntError },

Expand All @@ -68,12 +65,12 @@ pub(super) enum Error {
#[snafu(display("Failed to write initrd image file: {}", source))]
WriteInitrd { source: std::io::Error },

#[snafu(display("Error deserializing `BootSettings` from TOML: {}", source))]
InputToml { source: toml::de::Error },

#[snafu(display("Error serializing `BootSettings` to JSON: {}", source))]
OutputJson { source: serde_json::error::Error },

#[snafu(display("Failed to deserialize `BootSettings` from JSON value: {}", source))]
BootSettingsFromJsonValue { source: serde_json::error::Error },

#[snafu(display(
"Invalid boot config file, expected key-value, or key entries for each line"
))]
Expand Down
27 changes: 14 additions & 13 deletions sources/api/prairiedog/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use simplelog::{Config as LogConfig, LevelFilter, SimpleLogger, WriteLogger};
use snafu::{ensure, ResultExt};
use std::ffi::OsStr;
use std::fs::{self, File};
use std::path::Path;
use std::path::{Path, PathBuf};
use std::process::{self, Command};
use std::thread;
use std::time::Duration;
Expand All @@ -29,6 +29,8 @@ mod bootconfig;
mod error;
mod initrd;

// Prairie dog config path
const DEFAULT_CONFIG_FILE: &str = "/etc/prairiedog.toml";
// Kdump related binary paths
const MAKEDUMPFILE_PATH: &str = "/sbin/makedumpfile";
const KEXEC_PATH: &str = "/sbin/kexec";
Expand Down Expand Up @@ -60,9 +62,9 @@ struct Args {
#[argh(option, default = "LevelFilter::Info", short = 'l')]
/// log-level trace|debug|info|warn|error
log_level: LevelFilter,
#[argh(option, default = "constants::API_SOCKET.to_string()", short = 's')]
/// socket-path path to apiserver socket
socket_path: String,
#[argh(option, default = "PathBuf::from(DEFAULT_CONFIG_FILE)", short = 'c')]
/// config-path to provide alternate config file path
config_path: PathBuf,
#[argh(subcommand)]
subcommand: Subcommand,
}
Expand Down Expand Up @@ -283,11 +285,11 @@ fn load_crash_kernel() -> Result<()> {
Ok(())
}

async fn reboot_if_required<P>(socket_path: P) -> Result<()>
fn reboot_if_required<P>(config_path: P) -> Result<()>
where
P: AsRef<Path>,
{
if is_reboot_required(socket_path).await? {
if is_reboot_required(config_path)? {
info!("Boot settings changed and require a reboot to take effect. Initiating reboot...");
command("/usr/bin/systemctl", ["reboot"])?;
// The "systemctl reboot" process will not block until the host does
Expand Down Expand Up @@ -333,23 +335,22 @@ fn setup_logger(args: &Args) -> Result<()> {
Ok(())
}

async fn run() -> Result<()> {
fn run() -> Result<()> {
let args: Args = argh::from_env();
setup_logger(&args)?;

match args.subcommand {
Subcommand::CaptureDump(_) => capture_dump(),
Subcommand::PrepareBoot(_) => prepare_boot(),
Subcommand::LoadCrashKernel(_) => load_crash_kernel(),
Subcommand::GenerateBootConfig(_) => generate_boot_config(args.socket_path).await,
Subcommand::GenerateBootSettings(_) => generate_boot_settings().await,
Subcommand::RebootIfRequired(_) => reboot_if_required(args.socket_path).await,
Subcommand::GenerateBootConfig(_) => generate_boot_config(args.config_path),
Subcommand::GenerateBootSettings(_) => generate_boot_settings(),
Subcommand::RebootIfRequired(_) => reboot_if_required(args.config_path),
}
}

#[tokio::main]
async fn main() {
if let Err(e) = run().await {
fn main() {
if let Err(e) = run() {
error!("{}", e);
process::exit(1);
}
Expand Down
6 changes: 5 additions & 1 deletion sources/models/shared-defaults/boot.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,9 @@ affected-services = ["bootconfig"]
setting-generator = "/usr/bin/prairiedog generate-boot-settings"

[services.bootconfig]
configuration-files = []
configuration-files = ["prairiedog-toml"]
restart-commands = ["/usr/bin/prairiedog generate-boot-config"]

[configuration-files.prairiedog-toml]
path = "/etc/prairiedog.toml"
template-path = "/usr/share/templates/prairiedog-toml"

0 comments on commit 1f8500c

Please sign in to comment.