mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-06-25 06:52:13 +00:00
agent: config: Allow for building the configuration from a file
When the kernel command line includes a agent.config_file=<path> entry, then we will try to override the default confiuguration values with the ones we parse from a TOML file at <path>. As the configuration file overrides the default values, we need to go through a simplified builder that convert a set of Option<> fields into the actual AgentConfig structure. Fixes: #1837 Signed-off-by: Samuel Ortiz <samuel.e.ortiz@protonmail.com>
This commit is contained in:
parent
63539dc9fd
commit
0ea2e3af07
19
src/agent/Cargo.lock
generated
19
src/agent/Cargo.lock
generated
@ -544,6 +544,7 @@ dependencies = [
|
|||||||
"rustjail",
|
"rustjail",
|
||||||
"scan_fmt",
|
"scan_fmt",
|
||||||
"scopeguard",
|
"scopeguard",
|
||||||
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"slog",
|
"slog",
|
||||||
"slog-scope",
|
"slog-scope",
|
||||||
@ -552,6 +553,7 @@ dependencies = [
|
|||||||
"thiserror",
|
"thiserror",
|
||||||
"tokio",
|
"tokio",
|
||||||
"tokio-vsock",
|
"tokio-vsock",
|
||||||
|
"toml",
|
||||||
"tracing",
|
"tracing",
|
||||||
"tracing-opentelemetry",
|
"tracing-opentelemetry",
|
||||||
"tracing-subscriber",
|
"tracing-subscriber",
|
||||||
@ -1323,18 +1325,18 @@ checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.126"
|
version = "1.0.129"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ec7505abeacaec74ae4778d9d9328fe5a5d04253220a85c4ee022239fc996d03"
|
checksum = "d1f72836d2aa753853178eda473a3b9d8e4eefdaf20523b919677e6de489f8f1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.126"
|
version = "1.0.129"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "963a7dbc9895aeac7ac90e74f34a5d5261828f79df35cbed41e10189d3804d43"
|
checksum = "e57ae87ad533d9a56427558b516d0adac283614e347abf85b0dc0cbbf0a249f3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 1.0.26",
|
"proc-macro2 1.0.26",
|
||||||
"quote 1.0.9",
|
"quote 1.0.9",
|
||||||
@ -1618,6 +1620,15 @@ dependencies = [
|
|||||||
"vsock",
|
"vsock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "toml"
|
||||||
|
version = "0.5.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
|
||||||
|
dependencies = [
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tracing"
|
name = "tracing"
|
||||||
version = "0.1.26"
|
version = "0.1.26"
|
||||||
|
@ -58,6 +58,10 @@ tracing-opentelemetry = "0.13.0"
|
|||||||
opentelemetry = { version = "0.14.0", features = ["rt-tokio-current-thread"]}
|
opentelemetry = { version = "0.14.0", features = ["rt-tokio-current-thread"]}
|
||||||
vsock-exporter = { path = "vsock-exporter" }
|
vsock-exporter = { path = "vsock-exporter" }
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
serde = { version = "1.0.129", features = ["derive"] }
|
||||||
|
toml = "0.5.8"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
tempfile = "3.1.0"
|
tempfile = "3.1.0"
|
||||||
|
|
||||||
|
@ -4,8 +4,10 @@
|
|||||||
//
|
//
|
||||||
use crate::tracer;
|
use crate::tracer;
|
||||||
use anyhow::{bail, ensure, Context, Result};
|
use anyhow::{bail, ensure, Context, Result};
|
||||||
|
use serde::Deserialize;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use std::str::FromStr;
|
||||||
use std::time;
|
use std::time;
|
||||||
use tracing::instrument;
|
use tracing::instrument;
|
||||||
|
|
||||||
@ -19,6 +21,7 @@ const DEBUG_CONSOLE_VPORT_OPTION: &str = "agent.debug_console_vport";
|
|||||||
const LOG_VPORT_OPTION: &str = "agent.log_vport";
|
const LOG_VPORT_OPTION: &str = "agent.log_vport";
|
||||||
const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
|
const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
|
||||||
const UNIFIED_CGROUP_HIERARCHY_OPTION: &str = "agent.unified_cgroup_hierarchy";
|
const UNIFIED_CGROUP_HIERARCHY_OPTION: &str = "agent.unified_cgroup_hierarchy";
|
||||||
|
const CONFIG_FILE: &str = "agent.config_file";
|
||||||
|
|
||||||
const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info;
|
const DEFAULT_LOG_LEVEL: slog::Level = slog::Level::Info;
|
||||||
const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3);
|
const DEFAULT_HOTPLUG_TIMEOUT: time::Duration = time::Duration::from_secs(3);
|
||||||
@ -47,7 +50,7 @@ const ERR_INVALID_CONTAINER_PIPE_SIZE_PARAM: &str = "unable to parse container p
|
|||||||
const ERR_INVALID_CONTAINER_PIPE_SIZE_KEY: &str = "invalid container pipe size key name";
|
const ERR_INVALID_CONTAINER_PIPE_SIZE_KEY: &str = "invalid container pipe size key name";
|
||||||
const ERR_INVALID_CONTAINER_PIPE_NEGATIVE: &str = "container pipe size should not be negative";
|
const ERR_INVALID_CONTAINER_PIPE_NEGATIVE: &str = "container pipe size should not be negative";
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default, Deserialize)]
|
||||||
pub struct EndpointsConfig {
|
pub struct EndpointsConfig {
|
||||||
pub allowed: Vec<String>,
|
pub allowed: Vec<String>,
|
||||||
}
|
}
|
||||||
@ -67,6 +70,35 @@ pub struct AgentConfig {
|
|||||||
pub endpoints: EndpointsConfig,
|
pub endpoints: EndpointsConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Deserialize)]
|
||||||
|
pub struct AgentConfigBuilder {
|
||||||
|
pub debug_console: Option<bool>,
|
||||||
|
pub dev_mode: Option<bool>,
|
||||||
|
pub log_level: Option<String>,
|
||||||
|
pub hotplug_timeout: Option<time::Duration>,
|
||||||
|
pub debug_console_vport: Option<i32>,
|
||||||
|
pub log_vport: Option<i32>,
|
||||||
|
pub container_pipe_size: Option<i32>,
|
||||||
|
pub server_addr: Option<String>,
|
||||||
|
pub unified_cgroup_hierarchy: Option<bool>,
|
||||||
|
pub tracing: Option<tracer::TraceType>,
|
||||||
|
pub endpoints: Option<EndpointsConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! config_override {
|
||||||
|
($builder:ident, $config:ident, $field:ident) => {
|
||||||
|
if let Some(v) = $builder.$field {
|
||||||
|
$config.$field = v;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
($builder:ident, $config:ident, $field:ident, $func: ident) => {
|
||||||
|
if let Some(v) = $builder.$field {
|
||||||
|
$config.$field = $func(&v)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
// parse_cmdline_param parse commandline parameters.
|
// parse_cmdline_param parse commandline parameters.
|
||||||
macro_rules! parse_cmdline_param {
|
macro_rules! parse_cmdline_param {
|
||||||
// commandline flags, without func to parse the option values
|
// commandline flags, without func to parse the option values
|
||||||
@ -115,6 +147,36 @@ impl Default for AgentConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for AgentConfig {
|
||||||
|
type Err = anyhow::Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
let agent_config_builder: AgentConfigBuilder =
|
||||||
|
toml::from_str(s).map_err(anyhow::Error::new)?;
|
||||||
|
let mut agent_config: AgentConfig = Default::default();
|
||||||
|
|
||||||
|
// Overwrite default values with the configuration files ones.
|
||||||
|
config_override!(agent_config_builder, agent_config, debug_console);
|
||||||
|
config_override!(agent_config_builder, agent_config, dev_mode);
|
||||||
|
config_override!(
|
||||||
|
agent_config_builder,
|
||||||
|
agent_config,
|
||||||
|
log_level,
|
||||||
|
logrus_to_slog_level
|
||||||
|
);
|
||||||
|
config_override!(agent_config_builder, agent_config, hotplug_timeout);
|
||||||
|
config_override!(agent_config_builder, agent_config, debug_console_vport);
|
||||||
|
config_override!(agent_config_builder, agent_config, log_vport);
|
||||||
|
config_override!(agent_config_builder, agent_config, container_pipe_size);
|
||||||
|
config_override!(agent_config_builder, agent_config, server_addr);
|
||||||
|
config_override!(agent_config_builder, agent_config, unified_cgroup_hierarchy);
|
||||||
|
config_override!(agent_config_builder, agent_config, tracing);
|
||||||
|
config_override!(agent_config_builder, agent_config, endpoints);
|
||||||
|
|
||||||
|
Ok(agent_config)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AgentConfig {
|
impl AgentConfig {
|
||||||
#[instrument]
|
#[instrument]
|
||||||
pub fn from_cmdline(file: &str) -> Result<AgentConfig> {
|
pub fn from_cmdline(file: &str) -> Result<AgentConfig> {
|
||||||
@ -122,6 +184,15 @@ impl AgentConfig {
|
|||||||
let cmdline = fs::read_to_string(file)?;
|
let cmdline = fs::read_to_string(file)?;
|
||||||
let params: Vec<&str> = cmdline.split_ascii_whitespace().collect();
|
let params: Vec<&str> = cmdline.split_ascii_whitespace().collect();
|
||||||
for param in params.iter() {
|
for param in params.iter() {
|
||||||
|
// If we get a configuration file path from the command line, we
|
||||||
|
// generate our config from it.
|
||||||
|
// The agent will fail to start if the configuration file is not present,
|
||||||
|
// or if it can't be parsed properly.
|
||||||
|
if param.starts_with(format!("{}=", CONFIG_FILE).as_str()) {
|
||||||
|
let config_file = get_string_value(param)?;
|
||||||
|
return AgentConfig::from_config_file(&config_file);
|
||||||
|
}
|
||||||
|
|
||||||
// parse cmdline flags
|
// parse cmdline flags
|
||||||
parse_cmdline_param!(param, DEBUG_CONSOLE_FLAG, config.debug_console);
|
parse_cmdline_param!(param, DEBUG_CONSOLE_FLAG, config.debug_console);
|
||||||
parse_cmdline_param!(param, DEV_MODE_FLAG, config.dev_mode);
|
parse_cmdline_param!(param, DEV_MODE_FLAG, config.dev_mode);
|
||||||
@ -201,6 +272,12 @@ impl AgentConfig {
|
|||||||
|
|
||||||
Ok(config)
|
Ok(config)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[instrument]
|
||||||
|
pub fn from_config_file(file: &str) -> Result<AgentConfig> {
|
||||||
|
let config = fs::read_to_string(file)?;
|
||||||
|
AgentConfig::from_str(&config)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[instrument]
|
#[instrument]
|
||||||
@ -1262,4 +1339,29 @@ Caused by:
|
|||||||
assert_result!(d.result, result, msg);
|
assert_result!(d.result, result, msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_config_builder_from_string() {
|
||||||
|
let config = AgentConfig::from_str(
|
||||||
|
r#"
|
||||||
|
dev_mode = true
|
||||||
|
server_addr = 'vsock://8:2048'
|
||||||
|
|
||||||
|
[endpoints]
|
||||||
|
allowed = ["CreateContainer", "StartContainer"]
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Verify that the override worked
|
||||||
|
assert!(config.dev_mode);
|
||||||
|
assert_eq!(config.server_addr, "vsock://8:2048");
|
||||||
|
assert_eq!(
|
||||||
|
config.endpoints.allowed,
|
||||||
|
vec!["CreateContainer".to_string(), "StartContainer".to_string()]
|
||||||
|
);
|
||||||
|
|
||||||
|
// Verify that the default values are valid
|
||||||
|
assert_eq!(config.hotplug_timeout, DEFAULT_HOTPLUG_TIMEOUT);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,7 @@ use crate::config::AgentConfig;
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use opentelemetry::sdk::propagation::TraceContextPropagator;
|
use opentelemetry::sdk::propagation::TraceContextPropagator;
|
||||||
use opentelemetry::{global, sdk::trace::Config, trace::TracerProvider};
|
use opentelemetry::{global, sdk::trace::Config, trace::TracerProvider};
|
||||||
|
use serde::Deserialize;
|
||||||
use slog::{info, o, Logger};
|
use slog::{info, o, Logger};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
@ -17,7 +18,7 @@ use tracing_subscriber::layer::SubscriberExt;
|
|||||||
use tracing_subscriber::Registry;
|
use tracing_subscriber::Registry;
|
||||||
use ttrpc::r#async::TtrpcContext;
|
use ttrpc::r#async::TtrpcContext;
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Debug, Deserialize, PartialEq)]
|
||||||
pub enum TraceType {
|
pub enum TraceType {
|
||||||
Disabled,
|
Disabled,
|
||||||
Isolated,
|
Isolated,
|
||||||
|
Loading…
Reference in New Issue
Block a user