Skip to main content

lade_sdk/providers/network/
mod.rs

1use anyhow::{Result, bail};
2use rustc_hash::FxHashMap;
3use std::collections::HashMap;
4
5mod kubectl;
6mod kubefwd;
7mod ssh;
8mod tsh;
9
10#[derive(Debug, Clone)]
11pub enum ProviderSpec {
12    Kubectl {
13        cluster_endpoint: String,
14        context_selector: String,
15        namespace: String,
16        kind: String,
17        name: String,
18        remote_port: String,
19        pod_running_timeout: Option<String>,
20    },
21    Kubefwd {
22        cluster_endpoint: String,
23        context_selector: String,
24        namespace: String,
25        kind: String,
26        name: String,
27        service_port: u16,
28        domain: Option<String>,
29        selector: Option<String>,
30    },
31    TshKubeCluster {
32        teleport_proxy: String,
33        kube_cluster: String,
34        namespace: String,
35        kind: String,
36        name: String,
37        remote_port: u16,
38    },
39    TshApp {
40        teleport_proxy: String,
41        app_name: String,
42        target_port: Option<u16>,
43    },
44    Ssh {
45        jump_host: String,
46        jump_port: u16,
47        remote_host: String,
48        remote_port: u16,
49    },
50}
51
52pub trait NetworkProvider: Sync {
53    fn scheme(&self) -> &'static str;
54    fn parse(
55        &self,
56        authority: &str,
57        segments: &[&str],
58        query: &HashMap<String, String>,
59    ) -> Result<ProviderSpec>;
60}
61
62pub struct NetworkProviders {
63    by_scheme: FxHashMap<&'static str, Box<dyn NetworkProvider + Send>>,
64}
65
66impl Default for NetworkProviders {
67    fn default() -> Self {
68        Self::new()
69    }
70}
71
72impl NetworkProviders {
73    pub fn new() -> Self {
74        let providers: Vec<Box<dyn NetworkProvider + Send>> = vec![
75            Box::new(kubectl::KubectlProvider),
76            Box::new(kubefwd::KubefwdProvider),
77            Box::new(tsh::TshProvider),
78            Box::new(ssh::SshProvider),
79        ];
80        let by_scheme = providers
81            .into_iter()
82            .map(|provider| (provider.scheme(), provider))
83            .collect();
84        Self { by_scheme }
85    }
86
87    pub fn provider(&self, scheme: &str) -> Option<&(dyn NetworkProvider + Send)> {
88        self.by_scheme.get(scheme).map(|p| p.as_ref())
89    }
90}
91
92pub(crate) fn reject_unknown_query(
93    query: &HashMap<String, String>,
94    allowed: &[&str],
95) -> Result<()> {
96    for key in query.keys() {
97        if !allowed.contains(&key.as_str()) {
98            bail!("unsupported query parameter '{}'", key);
99        }
100    }
101    Ok(())
102}