2020//! become less frequent, then this module can be incorporated into stackable-operator. The module
2121//! structure should already resemble the one of stackable-operator.
2222
23- use std:: { fmt:: Display , str:: FromStr } ;
24-
25- use snafu:: { ResultExt , Snafu , ensure} ;
26- use stackable_operator:: kvp:: LabelValue ;
23+ use snafu:: Snafu ;
2724use strum:: { EnumDiscriminants , IntoStaticStr } ;
28- use uuid:: Uuid ;
2925
3026pub mod builder;
3127pub mod cluster_resources;
@@ -107,13 +103,16 @@ pub trait NameIsValidLabelValue {
107103}
108104
109105/// Restricted string type with attributes like maximum length.
106+ ///
107+ /// Fully-qualified types are used to ease the import into other modules.
108+ #[ macro_export( local_inner_macros) ]
110109macro_rules! attributed_string_type {
111110 ( $name: ident, $description: literal, $example: literal $( , $attribute: tt) * ) => {
112- #[ doc = concat!( $description, ", e.g. \" " , $example, "\" " ) ]
111+ #[ doc = std :: concat!( $description, ", e.g. \" " , $example, "\" " ) ]
113112 #[ derive( Clone , Debug , Eq , Ord , PartialEq , PartialOrd ) ]
114113 pub struct $name( String ) ;
115114
116- impl Display for $name {
115+ impl std :: fmt :: Display for $name {
117116 fn fmt( & self , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
118117 self . 0 . fmt( f)
119118 }
@@ -137,14 +136,17 @@ macro_rules! attributed_string_type {
137136 }
138137 }
139138
140- impl FromStr for $name {
141- type Err = Error ;
139+ impl std :: str :: FromStr for $name {
140+ type Err = $crate :: framework :: Error ;
142141
143142 fn from_str( s: & str ) -> std:: result:: Result <Self , Self :: Err > {
143+ // ResultExt::context is used on most but not all usages of this macro
144+ #[ allow( unused_imports) ]
145+ use snafu:: ResultExt ;
144146
145- ensure!(
147+ snafu :: ensure!(
146148 !s. is_empty( ) ,
147- EmptyStringSnafu { }
149+ $crate :: framework :: EmptyStringSnafu { }
148150 ) ;
149151
150152 $( attributed_string_type!( @from_str $name, s, $attribute) ; ) *
@@ -157,7 +159,7 @@ macro_rules! attributed_string_type {
157159 impl $name {
158160 #[ allow( dead_code) ]
159161 pub fn from_str_unsafe( s: & str ) -> Self {
160- FromStr :: from_str( s) . expect( "should be a valid {name}" )
162+ std :: str :: FromStr :: from_str( s) . expect( "should be a valid {name}" )
161163 }
162164
163165 // A dead_code warning is emitted if there is no unit test that calls this function.
@@ -170,56 +172,72 @@ macro_rules! attributed_string_type {
170172 } ;
171173 ( @from_str $name: ident, $s: expr, ( max_length = $max_length: expr) ) => {
172174 let length = $s. len( ) as usize ;
173- ensure!(
175+ snafu :: ensure!(
174176 length <= $name:: MAX_LENGTH ,
175- LengthExceededSnafu {
177+ $crate :: framework :: LengthExceededSnafu {
176178 length,
177179 max_length: $name:: MAX_LENGTH ,
178180 }
179181 ) ;
180182 } ;
181183 ( @from_str $name: ident, $s: expr, is_rfc_1123_dns_subdomain_name) => {
182- stackable_operator:: validation:: is_rfc_1123_subdomain( $s) . context( InvalidRfc1123DnsSubdomainNameSnafu ) ?;
184+ stackable_operator:: validation:: is_rfc_1123_subdomain( $s) . context( $crate :: framework :: InvalidRfc1123DnsSubdomainNameSnafu ) ?;
183185 } ;
184186 ( @from_str $name: ident, $s: expr, is_rfc_1123_label_name) => {
185- stackable_operator:: validation:: is_rfc_1123_label( $s) . context( InvalidRfc1123LabelNameSnafu ) ?;
187+ stackable_operator:: validation:: is_rfc_1123_label( $s) . context( $crate :: framework :: InvalidRfc1123LabelNameSnafu ) ?;
186188 } ;
187189 ( @from_str $name: ident, $s: expr, is_rfc_1035_label_name) => {
188- stackable_operator:: validation:: is_rfc_1035_label( $s) . context( InvalidRfc1035LabelNameSnafu ) ?;
190+ stackable_operator:: validation:: is_rfc_1035_label( $s) . context( $crate :: framework :: InvalidRfc1035LabelNameSnafu ) ?;
189191 } ;
190192 ( @from_str $name: ident, $s: expr, is_valid_label_value) => {
191- LabelValue :: from_str( $s) . context( InvalidLabelValueSnafu ) ?;
193+ stackable_operator :: kvp :: LabelValue :: from_str( $s) . context( $crate :: framework :: InvalidLabelValueSnafu ) ?;
192194 } ;
193195 ( @from_str $name: ident, $s: expr, is_uid) => {
194- Uuid :: try_parse( $s) . context( InvalidUidSnafu ) ?;
196+ uuid :: Uuid :: try_parse( $s) . context( $crate :: framework :: InvalidUidSnafu ) ?;
195197 } ;
196198 ( @trait_impl $name: ident, ( max_length = $max_length: expr) ) => {
197199 impl $name {
198200 // type arithmetic would be better
199201 pub const MAX_LENGTH : usize = $max_length;
200202 }
201203 } ;
204+ ( @trait_impl $name: ident, is_rfc_1035_label_name) => {
205+ impl $name {
206+ pub const IS_RFC_1035_LABEL_NAME : bool = true ;
207+ pub const IS_RFC_1123_LABEL_NAME : bool = true ;
208+ pub const IS_RFC_1123_SUBDOMAIN_NAME : bool = true ;
209+ }
210+ } ;
202211 ( @trait_impl $name: ident, is_rfc_1123_dns_subdomain_name) => {
212+ impl $name {
213+ pub const IS_RFC_1123_SUBDOMAIN_NAME : bool = true ;
214+ }
203215 } ;
204216 ( @trait_impl $name: ident, is_rfc_1123_label_name) => {
205- } ;
206- ( @trait_impl $name: ident, is_rfc_1035_label_name) => {
217+ impl $name {
218+ pub const IS_RFC_1123_LABEL_NAME : bool = true ;
219+ pub const IS_RFC_1123_SUBDOMAIN_NAME : bool = true ;
220+ }
207221 } ;
208222 ( @trait_impl $name: ident, is_uid) => {
209- impl From <Uuid > for $name {
210- fn from( value: Uuid ) -> Self {
223+ impl From <uuid :: Uuid > for $name {
224+ fn from( value: uuid :: Uuid ) -> Self {
211225 Self ( value. to_string( ) )
212226 }
213227 }
214228
215- impl From <& Uuid > for $name {
216- fn from( value: & Uuid ) -> Self {
229+ impl From <& uuid :: Uuid > for $name {
230+ fn from( value: & uuid :: Uuid ) -> Self {
217231 Self ( value. to_string( ) )
218232 }
219233 }
220234 } ;
221235 ( @trait_impl $name: ident, is_valid_label_value) => {
222- impl NameIsValidLabelValue for $name {
236+ impl $name {
237+ pub const IS_VALID_LABEL_VALUE : bool = true ;
238+ }
239+
240+ impl $crate:: framework:: NameIsValidLabelValue for $name {
223241 fn to_label_value( & self ) -> String {
224242 self . 0 . clone( )
225243 }
@@ -321,7 +339,12 @@ attributed_string_type! {
321339 StatefulSetName ,
322340 "The name of a StatefulSet" ,
323341 "opensearch-nodes-default" ,
324- ( max_length = min( MAX_RFC_1123_LABEL_NAME_LENGTH , MAX_LABEL_VALUE_LENGTH ) ) ,
342+ ( max_length = min(
343+ // see https://github.com/kubernetes/kubernetes/issues/64023
344+ MAX_RFC_1123_LABEL_NAME_LENGTH
345+ - 1 /* dash */
346+ - 10 /* digits for the controller-revision-hash label */ ,
347+ MAX_LABEL_VALUE_LENGTH ) ) ,
325348 is_rfc_1123_label_name,
326349 is_valid_label_value
327350}
@@ -351,6 +374,7 @@ attributed_string_type! {
351374 // A suffix is added to produce a label value. An according compile-time check ensures that
352375 // max_length cannot be set higher.
353376 ( max_length = min( 54 , MAX_LABEL_VALUE_LENGTH ) ) ,
377+ is_rfc_1123_dns_subdomain_name,
354378 is_valid_label_value
355379}
356380attributed_string_type ! {
@@ -364,9 +388,10 @@ attributed_string_type! {
364388 ClusterName ,
365389 "The name of a cluster/stacklet" ,
366390 "my-opensearch-cluster" ,
367- // Suffixes are added to produce a resource names. According compile-time check ensures that
391+ // Suffixes are added to produce resource names. According compile-time checks ensure that
368392 // max_length cannot be set higher.
369393 ( max_length = min( 24 , MAX_LABEL_VALUE_LENGTH ) ) ,
394+ is_rfc_1035_label_name,
370395 is_valid_label_value
371396}
372397attributed_string_type ! {
@@ -391,6 +416,7 @@ attributed_string_type! {
391416 // are valid, max_length is restricted. Compile-time checks ensure that max_length cannot be
392417 // set higher if not other names like the RoleName are set lower accordingly.
393418 ( max_length = min( 16 , MAX_LABEL_VALUE_LENGTH ) ) ,
419+ is_rfc_1123_label_name,
394420 is_valid_label_value
395421}
396422attributed_string_type ! {
@@ -401,23 +427,20 @@ attributed_string_type! {
401427 // valid, max_length is restricted. Compile-time checks ensure that max_length cannot be set
402428 // higher if not other names like the RoleGroupName are set lower accordingly.
403429 ( max_length = min( 10 , MAX_LABEL_VALUE_LENGTH ) ) ,
430+ is_rfc_1123_label_name,
404431 is_valid_label_value
405432}
406433
407434#[ cfg( test) ]
408435mod tests {
409- use std:: { fmt :: Display , str:: FromStr } ;
436+ use std:: str:: FromStr ;
410437
411- use snafu:: { ResultExt , ensure} ;
412- use uuid:: { Uuid , uuid} ;
438+ use uuid:: uuid;
413439
414440 use super :: {
415- ClusterName , ClusterRoleName , ConfigMapName , ControllerName , EmptyStringSnafu , Error ,
416- ErrorDiscriminants , InvalidLabelValueSnafu , InvalidRfc1035LabelNameSnafu ,
417- InvalidRfc1123DnsSubdomainNameSnafu , InvalidRfc1123LabelNameSnafu , InvalidUidSnafu ,
418- LabelValue , LengthExceededSnafu , NamespaceName , OperatorName , PersistentVolumeClaimName ,
419- ProductVersion , RoleBindingName , RoleGroupName , RoleName , ServiceAccountName , ServiceName ,
420- StatefulSetName , Uid , VolumeName ,
441+ ClusterName , ClusterRoleName , ConfigMapName , ControllerName , ErrorDiscriminants ,
442+ NamespaceName , OperatorName , PersistentVolumeClaimName , ProductVersion , RoleBindingName ,
443+ RoleGroupName , RoleName , ServiceAccountName , ServiceName , StatefulSetName , Uid , VolumeName ,
421444 } ;
422445 use crate :: framework:: { NameIsValidLabelValue , ProductName } ;
423446
@@ -505,6 +528,10 @@ mod tests {
505528 fn test_attributed_string_type_is_rfc_1035_label_name ( ) {
506529 type T = IsRfc1035LabelNameTest ;
507530
531+ let _ = T :: IS_RFC_1035_LABEL_NAME ;
532+ let _ = T :: IS_RFC_1123_LABEL_NAME ;
533+ let _ = T :: IS_RFC_1123_SUBDOMAIN_NAME ;
534+
508535 T :: test_example ( ) ;
509536 assert_eq ! (
510537 Err ( ErrorDiscriminants :: InvalidRfc1035LabelName ) ,
@@ -523,6 +550,8 @@ mod tests {
523550 fn test_attributed_string_type_is_rfc_1123_dns_subdomain_name ( ) {
524551 type T = IsRfc1123DnsSubdomainNameTest ;
525552
553+ let _ = T :: IS_RFC_1123_SUBDOMAIN_NAME ;
554+
526555 T :: test_example ( ) ;
527556 assert_eq ! (
528557 Err ( ErrorDiscriminants :: InvalidRfc1123DnsSubdomainName ) ,
@@ -541,6 +570,9 @@ mod tests {
541570 fn test_attributed_string_type_is_rfc_1123_label_name ( ) {
542571 type T = IsRfc1123LabelNameTest ;
543572
573+ let _ = T :: IS_RFC_1123_LABEL_NAME ;
574+ let _ = T :: IS_RFC_1123_SUBDOMAIN_NAME ;
575+
544576 T :: test_example ( ) ;
545577 assert_eq ! (
546578 Err ( ErrorDiscriminants :: InvalidRfc1123LabelName ) ,
@@ -559,6 +591,8 @@ mod tests {
559591 fn test_attributed_string_type_is_valid_label_value ( ) {
560592 type T = IsValidLabelValueTest ;
561593
594+ let _ = T :: IS_VALID_LABEL_VALUE ;
595+
562596 T :: test_example ( ) ;
563597 assert_eq ! (
564598 Err ( ErrorDiscriminants :: InvalidLabelValue ) ,
0 commit comments