mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-27 19:35:32 +00:00
genpolicy: Add support for envFrom
This change adds support for the `envFrom` field in the `Pod` resource Signed-off-by: Saul Paredes <saulparedes@microsoft.com>
This commit is contained in:
parent
fc4357f642
commit
2681fc7eb0
@ -64,6 +64,19 @@ impl ConfigMap {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_key_value_pairs(&self) -> Option<Vec<String>> {
|
||||
//eg ["key1=value1", "key2=value2"]
|
||||
self.data
|
||||
.as_ref()?
|
||||
.keys()
|
||||
.map(|key| {
|
||||
let value = self.data.as_ref().unwrap().get(key).unwrap();
|
||||
format!("{key}={value}")
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_value(value_from: &pod::EnvVarSource, config_maps: &Vec<ConfigMap>) -> Option<String> {
|
||||
@ -76,6 +89,18 @@ pub fn get_value(value_from: &pod::EnvVarSource, config_maps: &Vec<ConfigMap>) -
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_values(config_map_name: &str, config_maps: &Vec<ConfigMap>) -> Option<Vec<String>> {
|
||||
for config_map in config_maps {
|
||||
if let Some(existing_configmap_name) = &config_map.metadata.name {
|
||||
if config_map_name == existing_configmap_name {
|
||||
return config_map.get_key_value_pairs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl yaml::K8sResource for ConfigMap {
|
||||
async fn init(
|
||||
|
@ -122,6 +122,9 @@ pub struct Container {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
env: Option<Vec<EnvVar>>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
envFrom: Option<Vec<EnvFromSource>>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
resources: Option<ResourceRequirements>,
|
||||
|
||||
@ -416,6 +419,37 @@ pub struct ConfigMapKeySelector {
|
||||
optional: Option<bool>,
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Workload Resources / Pod.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct EnvFromSource {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub configMapRef: Option<ConfigMapEnvSource>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub secretRef: Option<SecretEnvSource>,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub prefix: Option<String>,
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Workload Resources / Pod.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct SecretEnvSource {
|
||||
pub name: String,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
optional: Option<bool>,
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Workload Resources / Pod.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub struct ConfigMapEnvSource {
|
||||
pub name: String,
|
||||
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
optional: Option<bool>,
|
||||
}
|
||||
|
||||
/// See Reference / Kubernetes API / Common Definitions / ResourceFieldSelector.
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
struct ResourceFieldSelector {
|
||||
@ -571,6 +605,18 @@ impl Container {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(env_from_sources) = &self.envFrom {
|
||||
for env_from_source in env_from_sources {
|
||||
let env_from_source_values = env_from_source.get_values(config_maps, secrets);
|
||||
|
||||
for value in env_from_source_values {
|
||||
if !dest_env.contains(&value) {
|
||||
dest_env.push(value.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_privileged(&self) -> bool {
|
||||
@ -652,6 +698,37 @@ impl Container {
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvFromSource {
|
||||
pub fn get_values(
|
||||
&self,
|
||||
config_maps: &Vec<config_map::ConfigMap>,
|
||||
secrets: &Vec<secret::Secret>,
|
||||
) -> Vec<String> {
|
||||
if let Some(config_map_env_source) = &self.configMapRef {
|
||||
if let Some(value) = config_map::get_values(&config_map_env_source.name, config_maps) {
|
||||
return value.clone();
|
||||
} else {
|
||||
panic!(
|
||||
"Couldn't get values from configmap ref: {}",
|
||||
&config_map_env_source.name
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(secret_env_source) = &self.secretRef {
|
||||
if let Some(value) = secret::get_values(&secret_env_source.name, secrets) {
|
||||
return value.clone();
|
||||
} else {
|
||||
panic!(
|
||||
"Couldn't get values from secret ref: {}",
|
||||
&secret_env_source.name
|
||||
);
|
||||
}
|
||||
}
|
||||
panic!("envFrom: no configmap or secret source found!");
|
||||
}
|
||||
}
|
||||
|
||||
impl EnvVar {
|
||||
pub fn get_value(
|
||||
&self,
|
||||
|
@ -58,6 +58,21 @@ impl Secret {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_key_value_pairs(&self) -> Option<Vec<String>> {
|
||||
//eg ["key1=secret1", "key2=secret2"]
|
||||
self.data
|
||||
.as_ref()?
|
||||
.keys()
|
||||
.map(|key| {
|
||||
let value = self.data.as_ref().unwrap().get(key).unwrap();
|
||||
let value_bytes = general_purpose::STANDARD.decode(value).unwrap();
|
||||
let value_string = std::str::from_utf8(&value_bytes).unwrap();
|
||||
format!("{key}={value_string}")
|
||||
})
|
||||
.collect::<Vec<String>>()
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_value(value_from: &pod::EnvVarSource, secrets: &Vec<Secret>) -> Option<String> {
|
||||
@ -70,6 +85,18 @@ pub fn get_value(value_from: &pod::EnvVarSource, secrets: &Vec<Secret>) -> Optio
|
||||
None
|
||||
}
|
||||
|
||||
pub fn get_values(secret_name: &str, secrets: &Vec<Secret>) -> Option<Vec<String>> {
|
||||
for secret in secrets {
|
||||
if let Some(existing_secret_name) = &secret.metadata.name {
|
||||
if existing_secret_name == secret_name {
|
||||
return secret.get_key_value_pairs();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl yaml::K8sResource for Secret {
|
||||
async fn init(&mut self, _config: &Config, doc_mapping: &serde_yaml::Value, _silent: bool) {
|
||||
|
@ -15,6 +15,11 @@ setup() {
|
||||
pod_name="policy-pod"
|
||||
|
||||
get_pod_config_dir
|
||||
policy_settings_dir="$(create_tmp_policy_settings_dir "${pod_config_dir}")"
|
||||
|
||||
exec_command="printenv data-3"
|
||||
add_exec_to_policy_settings "${policy_settings_dir}" "${exec_command}"
|
||||
add_requests_to_policy_settings "${policy_settings_dir}" "ReadStreamRequest"
|
||||
|
||||
correct_configmap_yaml="${pod_config_dir}/k8s-policy-configmap.yaml"
|
||||
pre_generate_configmap_yaml="${pod_config_dir}/k8s-policy-configmap-pre-generation.yaml"
|
||||
@ -34,7 +39,7 @@ setup() {
|
||||
cp "${correct_pod_yaml}" "${pre_generate_pod_yaml}"
|
||||
|
||||
# Add policy to the correct pod yaml file
|
||||
auto_generate_policy "${pod_config_dir}" "${correct_pod_yaml}" "${correct_configmap_yaml}"
|
||||
auto_generate_policy "${policy_settings_dir}" "${correct_pod_yaml}" "${correct_configmap_yaml}"
|
||||
fi
|
||||
|
||||
# Start each test case with a copy of the correct yaml files.
|
||||
@ -57,6 +62,14 @@ wait_for_pod_ready() {
|
||||
wait_for_pod_ready
|
||||
}
|
||||
|
||||
@test "Able to read env variables sourced from configmap using envFrom" {
|
||||
kubectl create -f "${correct_configmap_yaml}"
|
||||
kubectl create -f "${correct_pod_yaml}"
|
||||
kubectl wait --for=condition=Ready "--timeout=${timeout}" pod "${pod_name}"
|
||||
expected_env_var=$(kubectl exec "${pod_name}" -- printenv data-3)
|
||||
[ "$expected_env_var" = "value-3" ] || fail "expected_env_var is not equal to value-3"
|
||||
}
|
||||
|
||||
@test "Successful pod with auto-generated policy and runtimeClassName filter" {
|
||||
runtime_class_name=$(yq ".spec.runtimeClassName" < "${testcase_pre_generate_pod_yaml}")
|
||||
|
||||
|
@ -10,3 +10,4 @@ metadata:
|
||||
data:
|
||||
data-1: value-1
|
||||
data-2: value-2
|
||||
data-3: value-3
|
||||
|
@ -49,6 +49,9 @@ spec:
|
||||
- echo
|
||||
- startupProbe
|
||||
- test
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: policy-configmap
|
||||
topologySpreadConstraints:
|
||||
- maxSkew: 2
|
||||
topologyKey: kubernetes.io/hostname
|
||||
|
Loading…
Reference in New Issue
Block a user