Skip to content

Commit 721fdb2

Browse files
committed
feat(k8s-plugin): add support for kubeconfig context switching
This feature will allow user to choose between different kubeconfig contexts. Useful in case there are multiple clusters in a single kubeconfig file. Signed-off-by: Hristo Voyvodov <hristo.voyvodov@redsift.io>
1 parent 1797de5 commit 721fdb2

2 files changed

Lines changed: 35 additions & 10 deletions

File tree

k8s/proxy/src/lib.rs

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,19 @@ pub use proxy::{ConfigBuilder, ForwardingProxy, LokiClient, Scheme};
1616
/// Get the `kube::Config` from the given kubeconfig file, or the default.
1717
pub async fn config_from_kubeconfig(
1818
kube_config_path: Option<PathBuf>,
19+
options: KubeConfigOptions,
1920
) -> anyhow::Result<kube::Config> {
2021
let mut config = match kube_config_path {
2122
Some(config_path) => {
2223
// NOTE: Kubeconfig file may hold multiple contexts to communicate
23-
// with different kubernetes clusters. We have to pick master
24-
// address of current-context config only
24+
// with different kubernetes clusters. We'll pick either the one
25+
// specified in the options, or the current-context from the
26+
// kubeconfig file.
2527
let kube_config = kube::config::Kubeconfig::read_from(&config_path)?;
26-
kube::Config::from_custom_kubeconfig(kube_config, &Default::default()).await?
28+
kube::Config::from_custom_kubeconfig(kube_config, &options).await?
2729
}
28-
None => kube::Config::from_kubeconfig(&KubeConfigOptions::default()).await?,
30+
31+
None => kube::Config::from_kubeconfig(&options).await?,
2932
};
3033
config.apply_debug_overrides();
3134
Ok(config)
@@ -34,8 +37,21 @@ pub async fn config_from_kubeconfig(
3437
/// Get the `kube::Client` from the given kubeconfig file, or the default.
3538
pub async fn client_from_kubeconfig(
3639
kube_config_path: Option<PathBuf>,
40+
context: Option<String>,
3741
) -> anyhow::Result<kube::Client> {
42+
let options = kubeconfig_options_from_context(context);
3843
Ok(kube::Client::try_from(
39-
config_from_kubeconfig(kube_config_path).await?,
44+
config_from_kubeconfig(kube_config_path, options).await?,
4045
)?)
4146
}
47+
48+
/// Create a `KubeConfigOptions` from the given context.
49+
pub fn kubeconfig_options_from_context(context: Option<String>) -> KubeConfigOptions {
50+
match context {
51+
Some(ctx) => KubeConfigOptions {
52+
context: Some(ctx),
53+
..Default::default()
54+
},
55+
None => KubeConfigOptions::default(),
56+
}
57+
}

k8s/proxy/src/proxy.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use tower::{util::BoxService, ServiceExt};
2222
/// ```
2323
pub struct ConfigBuilder<T> {
2424
kube_config: Option<PathBuf>,
25+
context: Option<String>,
2526
target: kube_forward::Target,
2627
timeout: Option<std::time::Duration>,
2728
jwt: Option<String>,
@@ -77,6 +78,7 @@ impl Default for ConfigBuilder<ApiRest> {
7778
fn default() -> Self {
7879
Self {
7980
kube_config: None,
81+
context: None,
8082
target: kube_forward::Target::new(
8183
kube_forward::TargetSelector::ServiceLabel(utils::API_REST_LABEL.to_string()),
8284
utils::API_REST_HTTP_PORT,
@@ -94,6 +96,7 @@ impl Default for ConfigBuilder<Etcd> {
9496
fn default() -> Self {
9597
Self {
9698
kube_config: None,
99+
context: None,
97100
target: kube_forward::Target::new(
98101
kube_forward::TargetSelector::PodLabel(utils::ETCD_LABEL.to_string()),
99102
utils::ETCD_PORT,
@@ -111,6 +114,7 @@ impl Default for ConfigBuilder<Loki> {
111114
fn default() -> Self {
112115
Self {
113116
kube_config: None,
117+
context: None,
114118
target: kube_forward::Target::new(
115119
kube_forward::TargetSelector::ServiceLabel(utils::LOKI_LABEL.to_string()),
116120
utils::LOKI_PORT,
@@ -155,6 +159,11 @@ impl<T> ConfigBuilder<T> {
155159
self.target = target;
156160
self
157161
}
162+
/// Move self with the following context.
163+
pub fn with_context(mut self, context: Option<String>) -> Self {
164+
self.context = context;
165+
self
166+
}
158167
/// Move self with the following target closure.
159168
pub fn with_target_mod(
160169
mut self,
@@ -191,7 +200,7 @@ impl ConfigBuilder<ApiRest> {
191200
}
192201
/// Tries to build an HTTP `Configuration` from the current self.
193202
async fn build_http(self) -> Result<Configuration, Error> {
194-
let client = super::client_from_kubeconfig(self.kube_config).await?;
203+
let client = super::client_from_kubeconfig(self.kube_config, self.context).await?;
195204
let uri =
196205
kube_forward::HttpForward::new(self.target, Some(self.scheme.into()), client.clone())
197206
.uri()
@@ -209,7 +218,7 @@ impl ConfigBuilder<ApiRest> {
209218
}
210219
/// Tries to build a TCP `Configuration` from the current self.
211220
async fn build_tcp(self) -> Result<Configuration, Error> {
212-
let client = super::client_from_kubeconfig(self.kube_config).await?;
221+
let client = super::client_from_kubeconfig(self.kube_config, self.context).await?;
213222

214223
let pf = kube_forward::PortForward::new(self.target, None, client);
215224

@@ -238,7 +247,7 @@ impl ConfigBuilder<ApiRest> {
238247
impl ConfigBuilder<Etcd> {
239248
/// Tries to build a TCP `Configuration` from the current self.
240249
pub async fn build(self) -> Result<Uri, Error> {
241-
let client = super::client_from_kubeconfig(self.kube_config).await?;
250+
let client = super::client_from_kubeconfig(self.kube_config, self.context).await?;
242251

243252
let pf = kube_forward::PortForward::new(self.target, None, client);
244253

@@ -284,7 +293,7 @@ impl ConfigBuilder<Loki> {
284293
}
285294
/// Tries to build an HTTP `Configuration` from the current self.
286295
async fn build_http(self) -> Result<(Uri, LokiClient), Error> {
287-
let client = super::client_from_kubeconfig(self.kube_config).await?;
296+
let client = super::client_from_kubeconfig(self.kube_config, self.context).await?;
288297

289298
let uri =
290299
kube_forward::HttpForward::new(self.target, Some(self.scheme.into()), client.clone())
@@ -300,7 +309,7 @@ impl ConfigBuilder<Loki> {
300309
}
301310
/// Tries to build a TCP `Configuration` from the current self.
302311
async fn build_tcp(self) -> Result<(Uri, LokiClient), Error> {
303-
let client = super::client_from_kubeconfig(self.kube_config).await?;
312+
let client = super::client_from_kubeconfig(self.kube_config, self.context).await?;
304313

305314
let pf = kube_forward::PortForward::new(self.target, None, client);
306315

0 commit comments

Comments
 (0)