mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-05-04 06:27:25 +00:00
agent: Add config for api-server-rest
Add configuration for 'rest api server'. Optional configurations are 'agent.rest_api=attestation' will enable attestation api 'agent.rest_api=resource' will enable resource api 'agent.rest_api=all' will enable all (attestation and resource) api Fixes: #7555 Signed-off-by: Biao Lu <biao.lu@intel.com> Signed-off-by: Fabiano Fidêncio <fabiano.fidencio@intel.com> Signed-off-by: Linda Yu <linda.yu@intel.com> Co-authored-by: stevenhorsman <steven@uk.ibm.com> Co-authored-by: Jakob Naucke <jakob.naucke@ibm.com> Co-authored-by: Wang, Arron <arron.wang@intel.com> Co-authored-by: zhouliang121 <liang.a.zhou@linux.alibaba.com> Co-authored-by: Alex Carter <alex.carter@ibm.com> Co-authored-by: Suraj Deshmukh <suraj.deshmukh@microsoft.com> Co-authored-by: Xynnn007 <xynnn@linux.alibaba.com>
This commit is contained in:
parent
f476d671ed
commit
4d752e6350
src/agent
@ -70,6 +70,8 @@ vsock-exporter = { path = "vsock-exporter" }
|
||||
serde = { version = "1.0.129", features = ["derive"] }
|
||||
toml = "0.5.8"
|
||||
clap = { version = "3.0.1", features = ["derive"] }
|
||||
strum = "0.26.2"
|
||||
strum_macros = "0.26.2"
|
||||
|
||||
# Communication with the OPA service
|
||||
http = { version = "0.2.8", optional = true }
|
||||
|
@ -3,12 +3,13 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
use crate::rpc;
|
||||
use anyhow::{bail, ensure, Context, Result};
|
||||
use anyhow::{anyhow, bail, ensure, Context, Result};
|
||||
use serde::Deserialize;
|
||||
use std::env;
|
||||
use std::fs;
|
||||
use std::str::FromStr;
|
||||
use std::time;
|
||||
use strum_macros::{Display, EnumString};
|
||||
use tracing::instrument;
|
||||
use url::Url;
|
||||
|
||||
@ -26,6 +27,7 @@ const LOG_VPORT_OPTION: &str = "agent.log_vport";
|
||||
const CONTAINER_PIPE_SIZE_OPTION: &str = "agent.container_pipe_size";
|
||||
const UNIFIED_CGROUP_HIERARCHY_OPTION: &str = "systemd.unified_cgroup_hierarchy";
|
||||
const CONFIG_FILE: &str = "agent.config_file";
|
||||
const REST_API_OPTION: &str = "agent.guest_components_rest_api";
|
||||
|
||||
// Configure the proxy settings for HTTPS requests in the guest,
|
||||
// to solve the problem of not being able to access the specified image in some cases.
|
||||
@ -48,7 +50,6 @@ const ERR_INVALID_GET_VALUE_PARAM: &str = "expected name=value";
|
||||
const ERR_INVALID_GET_VALUE_NO_NAME: &str = "name=value parameter missing name";
|
||||
const ERR_INVALID_GET_VALUE_NO_VALUE: &str = "name=value parameter missing value";
|
||||
const ERR_INVALID_LOG_LEVEL_KEY: &str = "invalid log level key name";
|
||||
|
||||
const ERR_INVALID_HOTPLUG_TIMEOUT: &str = "invalid hotplug timeout parameter";
|
||||
const ERR_INVALID_HOTPLUG_TIMEOUT_PARAM: &str = "unable to parse hotplug timeout";
|
||||
const ERR_INVALID_HOTPLUG_TIMEOUT_KEY: &str = "invalid hotplug timeout key name";
|
||||
@ -58,6 +59,19 @@ 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_NEGATIVE: &str = "container pipe size should not be negative";
|
||||
|
||||
const ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE: &str = "invalid guest components rest api feature given. Valid values are `all`, `attestation`, `resource`, or `none`";
|
||||
|
||||
#[derive(Clone, Copy, Debug, Default, Display, Deserialize, EnumString, PartialEq)]
|
||||
// Features seem to typically be in kebab-case format, but we only have single words at the moment
|
||||
#[strum(serialize_all = "kebab-case")]
|
||||
pub enum GuestComponentsFeatures {
|
||||
All,
|
||||
Attestation,
|
||||
None,
|
||||
#[default]
|
||||
Resource,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AgentConfig {
|
||||
pub debug_console: bool,
|
||||
@ -74,6 +88,7 @@ pub struct AgentConfig {
|
||||
pub supports_seccomp: bool,
|
||||
pub https_proxy: String,
|
||||
pub no_proxy: String,
|
||||
pub guest_components_rest_api: GuestComponentsFeatures,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
@ -91,6 +106,7 @@ pub struct AgentConfigBuilder {
|
||||
pub tracing: Option<bool>,
|
||||
pub https_proxy: Option<String>,
|
||||
pub no_proxy: Option<String>,
|
||||
pub guest_components_rest_api: Option<GuestComponentsFeatures>,
|
||||
}
|
||||
|
||||
macro_rules! config_override {
|
||||
@ -154,6 +170,7 @@ impl Default for AgentConfig {
|
||||
supports_seccomp: rpc::have_seccomp(),
|
||||
https_proxy: String::from(""),
|
||||
no_proxy: String::from(""),
|
||||
guest_components_rest_api: GuestComponentsFeatures::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -185,6 +202,11 @@ impl FromStr for AgentConfig {
|
||||
config_override!(agent_config_builder, agent_config, tracing);
|
||||
config_override!(agent_config_builder, agent_config, https_proxy);
|
||||
config_override!(agent_config_builder, agent_config, no_proxy);
|
||||
config_override!(
|
||||
agent_config_builder,
|
||||
agent_config,
|
||||
guest_components_rest_api
|
||||
);
|
||||
|
||||
Ok(agent_config)
|
||||
}
|
||||
@ -286,6 +308,12 @@ impl AgentConfig {
|
||||
);
|
||||
parse_cmdline_param!(param, HTTPS_PROXY, config.https_proxy, get_url_value);
|
||||
parse_cmdline_param!(param, NO_PROXY, config.no_proxy, get_string_value);
|
||||
parse_cmdline_param!(
|
||||
param,
|
||||
REST_API_OPTION,
|
||||
config.guest_components_rest_api,
|
||||
get_guest_components_features_value
|
||||
);
|
||||
}
|
||||
|
||||
if let Ok(addr) = env::var(SERVER_ADDR_ENV_VAR) {
|
||||
@ -439,6 +467,19 @@ fn get_url_value(param: &str) -> Result<String> {
|
||||
Ok(Url::parse(&value)?.to_string())
|
||||
}
|
||||
|
||||
#[instrument]
|
||||
fn get_guest_components_features_value(param: &str) -> Result<GuestComponentsFeatures> {
|
||||
let fields: Vec<&str> = param.split('=').collect();
|
||||
ensure!(fields.len() >= 2, ERR_INVALID_GET_VALUE_PARAM);
|
||||
|
||||
// We need name (but the value can be blank)
|
||||
ensure!(!fields[0].is_empty(), ERR_INVALID_GET_VALUE_NO_NAME);
|
||||
|
||||
let value = fields[1..].join("=");
|
||||
GuestComponentsFeatures::from_str(&value)
|
||||
.map_err(|_| anyhow!(ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE))
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use test_utils::assert_result;
|
||||
@ -477,6 +518,7 @@ mod tests {
|
||||
tracing: bool,
|
||||
https_proxy: &'a str,
|
||||
no_proxy: &'a str,
|
||||
guest_components_rest_api: GuestComponentsFeatures,
|
||||
}
|
||||
|
||||
impl Default for TestData<'_> {
|
||||
@ -494,6 +536,7 @@ mod tests {
|
||||
tracing: false,
|
||||
https_proxy: "",
|
||||
no_proxy: "",
|
||||
guest_components_rest_api: GuestComponentsFeatures::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -883,6 +926,26 @@ mod tests {
|
||||
no_proxy: "192.168.1.0/24,172.16.0.0/12",
|
||||
..Default::default()
|
||||
},
|
||||
TestData {
|
||||
contents: "agent.guest_components_rest_api=attestation",
|
||||
guest_components_rest_api: GuestComponentsFeatures::Attestation,
|
||||
..Default::default()
|
||||
},
|
||||
TestData {
|
||||
contents: "agent.guest_components_rest_api=resource",
|
||||
guest_components_rest_api: GuestComponentsFeatures::Resource,
|
||||
..Default::default()
|
||||
},
|
||||
TestData {
|
||||
contents: "agent.guest_components_rest_api=all",
|
||||
guest_components_rest_api: GuestComponentsFeatures::All,
|
||||
..Default::default()
|
||||
},
|
||||
TestData {
|
||||
contents: "agent.guest_components_rest_api=none",
|
||||
guest_components_rest_api: GuestComponentsFeatures::None,
|
||||
..Default::default()
|
||||
},
|
||||
];
|
||||
|
||||
let dir = tempdir().expect("failed to create tmpdir");
|
||||
@ -932,6 +995,11 @@ mod tests {
|
||||
assert_eq!(d.tracing, config.tracing, "{}", msg);
|
||||
assert_eq!(d.https_proxy, config.https_proxy, "{}", msg);
|
||||
assert_eq!(d.no_proxy, config.no_proxy, "{}", msg);
|
||||
assert_eq!(
|
||||
d.guest_components_rest_api, config.guest_components_rest_api,
|
||||
"{}",
|
||||
msg
|
||||
);
|
||||
|
||||
for v in vars_to_unset {
|
||||
env::remove_var(v);
|
||||
@ -1403,6 +1471,68 @@ Caused by:
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_get_guest_components_features_value() {
|
||||
#[derive(Debug)]
|
||||
struct TestData<'a> {
|
||||
param: &'a str,
|
||||
result: Result<GuestComponentsFeatures>,
|
||||
}
|
||||
|
||||
let tests = &[
|
||||
TestData {
|
||||
param: "",
|
||||
result: Err(anyhow!(ERR_INVALID_GET_VALUE_PARAM)),
|
||||
},
|
||||
TestData {
|
||||
param: "=",
|
||||
result: Err(anyhow!(ERR_INVALID_GET_VALUE_NO_NAME)),
|
||||
},
|
||||
TestData {
|
||||
param: "==",
|
||||
result: Err(anyhow!(ERR_INVALID_GET_VALUE_NO_NAME)),
|
||||
},
|
||||
TestData {
|
||||
param: "x=all",
|
||||
result: Ok(GuestComponentsFeatures::All),
|
||||
},
|
||||
TestData {
|
||||
param: "x=attestation",
|
||||
result: Ok(GuestComponentsFeatures::Attestation),
|
||||
},
|
||||
TestData {
|
||||
param: "x=none",
|
||||
result: Ok(GuestComponentsFeatures::None),
|
||||
},
|
||||
TestData {
|
||||
param: "x=resource",
|
||||
result: Ok(GuestComponentsFeatures::Resource),
|
||||
},
|
||||
TestData {
|
||||
param: "x===",
|
||||
result: Err(anyhow!(ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE)),
|
||||
},
|
||||
TestData {
|
||||
param: "x==x",
|
||||
result: Err(anyhow!(ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE)),
|
||||
},
|
||||
TestData {
|
||||
param: "x=x",
|
||||
result: Err(anyhow!(ERR_INVALID_GUEST_COMPONENTS_REST_API_VALUE)),
|
||||
},
|
||||
];
|
||||
|
||||
for (i, d) in tests.iter().enumerate() {
|
||||
let msg = format!("test[{}]: {:?}", i, d);
|
||||
|
||||
let result = get_guest_components_features_value(d.param);
|
||||
|
||||
let msg = format!("{}: result: {:?}", msg, result);
|
||||
|
||||
assert_result!(d.result, result, msg);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_config_builder_from_string() {
|
||||
let config = AgentConfig::from_str(
|
||||
|
Loading…
Reference in New Issue
Block a user