k8s_openapi_ext/ext/
secret.rs1use super::*;
2
3const DOCKER_CONFIG_JSON_TYPE: &str = "kubernetes.io/dockerconfigjson";
13const DOCKER_CONFIG_JSON_KEY: &str = ".dockerconfigjson";
14
15const BASIC_AUTH_TYPE: &str = "kubernetes.io/basic-auth";
16const BASIC_AUTH_USERNAME: &str = "username";
17const BASIC_AUTH_PASSWORD: &str = "password";
18
19const SSH_AUTH_TYPE: &str = "kubernetes.io/ssh-auth";
20const SSH_AUTH_PRIVATE_KEY: &str = "ssh-privatekey";
21
22pub trait SecretExt: super::ResourceBuilder + Sized {
23 fn new(name: impl ToString) -> Self;
24
25 fn immutable(self, yes: bool) -> Self;
26
27 fn r#type(self, r#type: impl ToString) -> Self;
28
29 fn data(self, data: impl IntoIterator<Item = (impl ToString, ByteString)>) -> Self;
30
31 fn string_data(self, data: impl IntoIterator<Item = (impl ToString, impl ToString)>) -> Self;
32
33 fn image_pull_secret(
36 name: impl ToString,
37 registry: impl ToString,
38 username: impl ToString,
39 password: impl ToString,
40 ) -> Self {
41 let registry = registry.to_string();
42 let username = username.to_string();
43 let password = password.to_string();
44 let auth = format!("{username}:{password}");
45 let auth =
46 base64::display::Base64Display::new(auth.as_bytes(), &base64::prelude::BASE64_STANDARD);
47 let config = format!(
48 r#"{{"auths":{{"{registry}":{{"username":"{username}","password":"{password}","auth":"{auth}"}}}}}}"#
49 );
50 let data = [(DOCKER_CONFIG_JSON_KEY, config)];
51 Self::new(name)
52 .r#type(DOCKER_CONFIG_JSON_TYPE)
53 .string_data(data)
54 }
55
56 fn basic_auth(name: impl ToString, username: impl ToString, password: impl ToString) -> Self {
59 let data = [
60 (BASIC_AUTH_USERNAME, username.to_string()),
61 (BASIC_AUTH_PASSWORD, password.to_string()),
62 ];
63 Self::new(name).r#type(BASIC_AUTH_TYPE).string_data(data)
64 }
65
66 fn ssh_auth(name: impl ToString, private_key: impl ToString) -> Self {
67 let data = [(SSH_AUTH_PRIVATE_KEY, private_key)];
68 Self::new(name).r#type(SSH_AUTH_TYPE).string_data(data)
69 }
70}
71
72pub trait SecretExt2: SecretExt {
73 fn image_pull_secret(name: impl ToString, data: impl ToString) -> Self {
77 let data = [(DOCKER_CONFIG_JSON_KEY, data)];
78 Self::new(name)
79 .r#type(DOCKER_CONFIG_JSON_TYPE)
80 .string_data(data)
81 }
82}
83
84impl SecretExt for corev1::Secret {
85 fn new(name: impl ToString) -> Self {
86 let metadata = metadata(name);
87 Self {
88 metadata,
89 ..default()
94 }
95 }
96
97 fn immutable(self, yes: bool) -> Self {
98 let immutable = Some(yes);
99 Self { immutable, ..self }
100 }
101
102 fn r#type(self, r#type: impl ToString) -> Self {
103 let type_ = Some(r#type.to_string());
104 Self { type_, ..self }
105 }
106
107 fn data(self, data: impl IntoIterator<Item = (impl ToString, ByteString)>) -> Self {
108 let data = data
109 .into_iter()
110 .map(|(key, value)| (key.to_string(), value))
111 .collect();
112 Self {
113 data: Some(data),
114 ..self
115 }
116 }
117
118 fn string_data(self, data: impl IntoIterator<Item = (impl ToString, impl ToString)>) -> Self {
119 let data = data
120 .into_iter()
121 .map(|(key, value)| (key.to_string(), value.to_string()))
122 .collect();
123 Self {
124 string_data: Some(data),
125 ..self
126 }
127 }
128}
129
130impl SecretExt2 for corev1::Secret {}
131
132#[cfg(test)]
133mod tests {
134 use super::*;
135
136 use serde_json as json;
137
138 #[test]
139 fn image_pull_secret() {
140 let secret = <corev1::Secret as SecretExt>::image_pull_secret(
141 "name", "registry", "username", "password",
142 );
143 let string_data = secret.string_data.unwrap_or_default();
144 assert_eq!(string_data.len(), 1);
145 let config: json::Value = json::from_str(&string_data[DOCKER_CONFIG_JSON_KEY]).unwrap();
146 assert!(config.is_object());
147 }
148
149 #[test]
150 fn ssh_auth() {
151 let secret = corev1::Secret::ssh_auth(
152 "name",
153 "KGpwKaqlGas+LaAqdwdfAAAEEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAIClTFvhvwp1UH25b",
154 );
155 let string_data = secret.string_data.unwrap_or_default();
156 assert_eq!(string_data.len(), 1);
157 assert_eq!(string_data[SSH_AUTH_PRIVATE_KEY].len(), 70);
158 }
159}