alien_core/
access_request_crd.rs1use crate::DEFAULT_ALIEN_LABEL_DOMAIN;
27
28pub const DEFAULT_BRAND: &str = "alien";
30
31#[derive(Debug, Clone, PartialEq, Eq)]
33pub struct AccessRequestCrdNames {
34 pub group: String,
36 pub kind: String,
38 pub plural: String,
40 pub singular: String,
42 pub short_name: String,
44 pub api_version: String,
46 pub crd_name: String,
49}
50
51pub const ACCESS_REQUEST_CRD_VERSION: &str = "v1alpha1";
53
54pub fn access_request_crd_names(brand_name: Option<&str>) -> AccessRequestCrdNames {
61 let name = brand_name
62 .map(str::trim)
63 .filter(|n| !n.is_empty())
64 .unwrap_or(DEFAULT_BRAND);
65
66 let brand = brand_slug(name);
67 let group = format!("accessrequests.{brand}");
68 let plural = format!("{brand}accessrequests");
69 let singular = format!("{brand}accessrequest");
70 let short_name = format!("{brand}ar");
71 let kind = format!("{}AccessRequest", capitalize(&brand));
72
73 AccessRequestCrdNames {
74 api_version: format!("{group}/{ACCESS_REQUEST_CRD_VERSION}"),
75 crd_name: format!("{plural}.{group}"),
76 group,
77 kind,
78 plural,
79 singular,
80 short_name,
81 }
82}
83
84pub fn brand_slug(name: &str) -> String {
88 let first_label = name.split('.').next().unwrap_or(name);
89 let slug: String = first_label
90 .chars()
91 .filter(|c| c.is_ascii_alphanumeric())
92 .map(|c| c.to_ascii_lowercase())
93 .collect();
94 if slug.is_empty() {
95 "alien".to_string()
96 } else {
97 slug
98 }
99}
100
101pub fn current_kubernetes_label_domain(configured: &str) -> String {
103 if configured == DEFAULT_ALIEN_LABEL_DOMAIN {
104 configured.to_string()
105 } else {
106 brand_slug(configured)
107 }
108}
109
110pub fn explicit_legacy_kubernetes_label_domain(configured: &str) -> Option<&str> {
112 let current = current_kubernetes_label_domain(configured);
113 (configured != current && is_valid_kubernetes_label_domain(configured)).then_some(configured)
114}
115
116pub fn is_valid_kubernetes_label_domain(value: &str) -> bool {
118 !value.is_empty()
119 && value.len() <= 253
120 && value.split('.').all(|label| {
121 !label.is_empty()
122 && label.len() <= 63
123 && label
124 .bytes()
125 .all(|byte| byte.is_ascii_lowercase() || byte.is_ascii_digit() || byte == b'-')
126 && label
127 .as_bytes()
128 .first()
129 .is_some_and(u8::is_ascii_alphanumeric)
130 && label
131 .as_bytes()
132 .last()
133 .is_some_and(u8::is_ascii_alphanumeric)
134 })
135}
136
137fn capitalize(s: &str) -> String {
139 let mut chars = s.chars();
140 match chars.next() {
141 Some(first) => first.to_ascii_uppercase().to_string() + chars.as_str(),
142 None => String::new(),
143 }
144}
145
146#[cfg(test)]
147mod tests {
148 use super::*;
149
150 #[test]
151 fn default_is_alien() {
152 let n = access_request_crd_names(None);
153 assert_eq!(n.group, "accessrequests.alien");
154 assert_eq!(n.kind, "AlienAccessRequest");
155 assert_eq!(n.plural, "alienaccessrequests");
156 assert_eq!(n.short_name, "alienar");
157 assert_eq!(n.crd_name, "alienaccessrequests.accessrequests.alien");
158 assert_eq!(n.api_version, "accessrequests.alien/v1alpha1");
159 }
160
161 #[test]
162 fn brands_from_domain() {
163 let n = access_request_crd_names(Some("acme.dev"));
164 assert_eq!(n.group, "accessrequests.acme");
165 assert_eq!(n.kind, "AcmeAccessRequest");
166 assert_eq!(n.plural, "acmeaccessrequests");
167 assert_eq!(n.singular, "acmeaccessrequest");
168 assert_eq!(n.short_name, "acmear");
169 assert_eq!(n.crd_name, "acmeaccessrequests.accessrequests.acme");
170 }
171
172 #[test]
173 fn brands_from_plain_name() {
174 let n = access_request_crd_names(Some("My Cool App"));
175 assert_eq!(n.group, "accessrequests.mycoolapp");
176 assert_eq!(n.kind, "MycoolappAccessRequest");
177 assert_eq!(n.plural, "mycoolappaccessrequests");
178 assert_eq!(n.short_name, "mycoolappar");
179 }
180
181 #[test]
182 fn plural_is_brand_prefixed_accessrequests() {
183 let n = access_request_crd_names(Some("globex.dev"));
185 assert_eq!(n.plural, "globexaccessrequests");
186 assert_eq!(n.kind, "GlobexAccessRequest");
187 assert_eq!(n.group, "accessrequests.globex");
188 }
189
190 #[test]
191 fn strips_non_alphanumerics_from_slug() {
192 let n = access_request_crd_names(Some("my-startup.io"));
193 assert_eq!(n.group, "accessrequests.mystartup");
194 assert_eq!(n.kind, "MystartupAccessRequest");
195 assert_eq!(n.plural, "mystartupaccessrequests");
196 }
197
198 #[test]
199 fn empty_domain_falls_back() {
200 assert_eq!(
201 access_request_crd_names(Some("")).kind,
202 "AlienAccessRequest"
203 );
204 assert_eq!(
205 access_request_crd_names(Some(" ")).kind,
206 "AlienAccessRequest"
207 );
208 }
209}