Skip to main content

xianyun_cluster/kubeconfig/
mod.rs

1//! Port of `internal/kubeconfig`: manages virtual kubeconfigs for clusters
2//! managed by Caproni, and merges cluster kubeconfigs into the user's own.
3
4pub mod file;
5pub mod merge;
6
7use thiserror::Error;
8
9/// Port of `kubeconfig.Config`: a temporary, Caproni-managed virtual kubeconfig.
10pub struct Config {
11    temp: tempfile::NamedTempFile,
12    cache_dir: String,
13}
14
15/// Errors from creating or using a virtual [`Config`].
16#[derive(Debug, Error)]
17pub enum KubeconfigError {
18    #[error("getting home dir: {0}")]
19    HomeDir(String),
20    #[error("creating kubeconfig tempfile: {0}")]
21    CreateTempfile(String),
22    #[error("writing kubeconfig to tempfile: {0}")]
23    WriteTempfile(String),
24}
25
26impl Config {
27    /// Port of `kubeconfig.Create`. The caller must call [`Config::close`]
28    /// once the config is no longer used, so the temporary file can be
29    /// deleted.
30    pub fn create(kubeconfig_yaml: &str) -> Result<Self, KubeconfigError> {
31        let home_dir = dirs_home().ok_or_else(|| {
32            KubeconfigError::HomeDir("could not determine home directory".to_string())
33        })?;
34
35        let mut temp = tempfile::Builder::new()
36            .prefix("xianyun-kubeconfig-")
37            .tempfile()
38            .map_err(|e| KubeconfigError::CreateTempfile(e.to_string()))?;
39
40        use std::io::Write;
41        temp.write_all(kubeconfig_yaml.as_bytes())
42            .map_err(|e| KubeconfigError::WriteTempfile(e.to_string()))?;
43        temp.flush()
44            .map_err(|e| KubeconfigError::WriteTempfile(e.to_string()))?;
45
46        Ok(Self {
47            temp,
48            cache_dir: home_dir
49                .join(".kube")
50                .join("cache")
51                .to_string_lossy()
52                .into_owned(),
53        })
54    }
55
56    /// Port of `(*Config).Close`.
57    pub fn close(self) -> Result<(), KubeconfigError> {
58        self.temp
59            .close()
60            .map_err(|e| KubeconfigError::WriteTempfile(e.to_string()))
61    }
62
63    /// Port of `(*Config).Path`.
64    pub fn path(&self) -> &str {
65        self.temp.path().to_str().unwrap_or_default()
66    }
67
68    /// Port of `(*Config).Environ`.
69    pub fn environ(&self) -> Vec<String> {
70        vec![
71            format!("KUBECONFIG={}", self.path()),
72            format!("KUBECACHEDIR={}", self.cache_dir),
73        ]
74    }
75}
76
77/// Port of Go's `os.UserHomeDir()`, without pulling in a `dirs`-style crate
78/// dependency: checks `$HOME` (Unix) / `%USERPROFILE%` (Windows), matching
79/// the environment variables Go's implementation reads.
80fn dirs_home() -> Option<std::path::PathBuf> {
81    std::env::var_os("HOME")
82        .or_else(|| std::env::var_os("USERPROFILE"))
83        .map(std::path::PathBuf::from)
84}