refactor(kubernetes): Remove nested Options (#4743)

Kubernetes module was previously a bit messy, with lots of
unnecessarily nested options. Clean this up using filter_map and
find_map, with two major results:

1. `ctx_components` is now a Vec<KubeCtxComponent> instead of a
   Vec<Option<KubeCtxComponent>>. This greatly simplified downstream
   processing of these context components.

2. Instead of storing a partial computation of the namespace in
   variables `kube_ns`, etc, compute them directly in the formatter
   mapping. This is made simpler (read: actually doable) by change 1.
This commit is contained in:
Kevin Song 2022-12-20 19:04:40 -06:00 committed by GitHub
parent a51f76375f
commit addd11e300
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 17 additions and 38 deletions

View File

@ -34,10 +34,7 @@ fn get_kube_context(filename: path::PathBuf) -> Option<String> {
Some(current_ctx.to_string())
}
fn get_kube_ctx_component(
filename: path::PathBuf,
current_ctx: String,
) -> Option<KubeCtxComponents> {
fn get_kube_ctx_component(filename: path::PathBuf, current_ctx: &str) -> Option<KubeCtxComponents> {
let contents = utils::read_file(filename).ok()?;
let yaml_docs = YamlLoader::load_from_str(&contents).ok()?;
@ -120,7 +117,7 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
};
// If we have some config for doing the directory scan then we use it but if we don't then we
// assume we should treat it like the module is enabled to preserve backward compatability.
// assume we should treat it like the module is enabled to preserve backward compatibility.
let have_scan_config = !(config.detect_files.is_empty()
&& config.detect_folders.is_empty()
&& config.detect_extensions.is_empty());
@ -144,23 +141,10 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
let kube_ctx = env::split_paths(&kube_cfg).find_map(get_kube_context)?;
let ctx_components: Vec<Option<KubeCtxComponents>> = env::split_paths(&kube_cfg)
.map(|filename| get_kube_ctx_component(filename, kube_ctx.clone()))
let ctx_components: Vec<KubeCtxComponents> = env::split_paths(&kube_cfg)
.filter_map(|filename| get_kube_ctx_component(filename, &kube_ctx))
.collect();
let kube_user = ctx_components.iter().find(|&ctx| match ctx {
Some(kube) => kube.user.is_some(),
None => false,
});
let kube_ns = ctx_components.iter().find(|&ctx| match ctx {
Some(kube) => kube.namespace.is_some(),
None => false,
});
let kube_cluster = ctx_components.iter().find(|&ctx| match ctx {
Some(kube) => kube.cluster.is_some(),
None => false,
});
let parsed = StringFormatter::new(config.format).and_then(|formatter| {
formatter
.map_meta(|variable, _| match variable {
@ -174,25 +158,20 @@ pub fn module<'a>(context: &'a Context) -> Option<Module<'a>> {
.map(|variable| match variable {
"context" => Some(Ok(get_kube_context_name(&config, &kube_ctx))),
"namespace" => kube_ns.and_then(|ctx| {
ctx.as_ref().map(|kube| {
// unwrap is safe as kube_ns only holds kube.namespace.is_some()
Ok(Cow::Borrowed(kube.namespace.as_ref().unwrap().as_str()))
})
}),
"user" => kube_user.and_then(|ctx| {
ctx.as_ref().map(|kube| {
// unwrap is safe as kube_user only holds kube.user.is_some()
Ok(get_kube_user(&config, kube.user.as_ref().unwrap().as_str()))
})
}),
"cluster" => kube_cluster.and_then(|ctx| {
ctx.as_ref().map(|kube| {
// unwrap is safe as kube_cluster only holds kube.cluster.is_some()
Ok(Cow::Borrowed(kube.cluster.as_ref().unwrap().as_str()))
})
}),
"namespace" => ctx_components
.iter()
.find_map(|kube| kube.namespace.as_deref())
.map(|namespace| Ok(Cow::Borrowed(namespace))),
"user" => ctx_components
.iter()
.find_map(|kube| kube.user.as_deref())
.map(|user| Ok(get_kube_user(&config, user))),
"cluster" => ctx_components
.iter()
.find_map(|kube| kube.cluster.as_deref())
.map(|cluster| Ok(Cow::Borrowed(cluster))),
_ => None,
})
.parse(None, Some(context))