11//! This module provides various types and functions to construct valid
22//! Kubernetes labels. Labels are key/value pairs, where the key must meet
3- //! certain requirementens regarding length and character set. The value can
3+ //! certain requirements regarding length and character set. The value can
44//! contain a limited set of ASCII characters.
55//!
66//! Additionally, the [`Label`] struct provides various helper functions to
@@ -42,6 +42,63 @@ pub type LabelsError = KeyValuePairsError;
4242/// of labels fails.
4343pub type LabelError = KeyValuePairError < LabelValueError > ;
4444
45+ /// Add [`Label`]s to any Kubernetes resource.
46+ ///
47+ /// It should be noted, that after the addition of labels to the resource, the validity of keys and
48+ /// values **can no longer be enforced** as they are both stored as plain [`String`]s. To update a
49+ /// label use [`LabelExt::add_label`] which will update the label in place if it is already present.
50+ pub trait LabelExt
51+ where
52+ Self : ResourceExt ,
53+ {
54+ /// Adds a single label to `self`.
55+ fn add_label ( & mut self , label : Label ) -> & mut Self ;
56+
57+ /// Adds multiple labels to `self`.
58+ fn add_labels ( & mut self , label : Labels ) -> & mut Self ;
59+ }
60+
61+ impl < T > LabelExt for T
62+ where
63+ T : ResourceExt ,
64+ {
65+ fn add_label ( & mut self , label : Label ) -> & mut Self {
66+ let meta = self . meta_mut ( ) ;
67+
68+ match & mut meta. labels {
69+ Some ( labels) => {
70+ // TODO (@Techassi): Add an API to consume key and value
71+ let KeyValuePair { key, value } = label. into_inner ( ) ;
72+ labels. insert ( key. to_string ( ) , value. to_string ( ) ) ;
73+ }
74+ None => {
75+ let mut labels = BTreeMap :: new ( ) ;
76+
77+ // TODO (@Techassi): Add an API to consume key and value
78+ let KeyValuePair { key, value } = label. into_inner ( ) ;
79+ labels. insert ( key. to_string ( ) , value. to_string ( ) ) ;
80+
81+ meta. labels = Some ( labels) ;
82+ }
83+ }
84+
85+ self
86+ }
87+
88+ fn add_labels ( & mut self , labels : Labels ) -> & mut Self {
89+ let meta = self . meta_mut ( ) ;
90+
91+ match & mut meta. labels {
92+ Some ( existing_labels) => {
93+ existing_labels. extend :: < BTreeMap < String , String > > ( labels. into ( ) )
94+ }
95+ None => meta. labels = Some ( labels. into ( ) ) ,
96+ }
97+
98+ self
99+ }
100+ }
101+
45102/// A specialized implementation of a key/value pair representing Kubernetes
46103/// labels.
47104///
@@ -99,26 +156,28 @@ impl Label {
99156 self . 0
100157 }
101158
102- /// Creates the `app.kubernetes.io/component` label with `role` as the
103- /// value. This function will return an error if `role` violates the required
104- /// Kubernetes restrictions.
159+ /// Creates the `app.kubernetes.io/component` label with `role` as the value.
160+ ///
161+ /// This function will return an error if `role` violates the required Kubernetes restrictions.
105162 pub fn component ( component : & str ) -> Result < Self , LabelError > {
106163 let kvp = KeyValuePair :: try_from ( ( K8S_APP_COMPONENT_KEY , component) ) ?;
107164 Ok ( Self ( kvp) )
108165 }
109166
110- /// Creates the `app.kubernetes.io/role-group` label with `role_group` as
111- /// the value. This function will return an error if `role_group` violates
112- /// the required Kubernetes restrictions.
167+ /// Creates the `app.kubernetes.io/role-group` label with `role_group` as the value.
168+ ///
169+ /// This function will return an error if `role_group` violates the required Kubernetes
170+ /// restrictions.
113171 pub fn role_group ( role_group : & str ) -> Result < Self , LabelError > {
114172 let kvp = KeyValuePair :: try_from ( ( K8S_APP_ROLE_GROUP_KEY , role_group) ) ?;
115173 Ok ( Self ( kvp) )
116174 }
117175
118- /// Creates the `app.kubernetes.io/managed-by` label with the formated
119- /// full controller name based on `operator_name` and `controller_name` as
120- /// the value. This function will return an error if the formatted controller
121- /// name violates the required Kubernetes restrictions.
176+ /// Creates the `app.kubernetes.io/managed-by` label with the formatted full controller name
177+ /// based on `operator_name` and `controller_name` as the value.
178+ ///
179+ /// This function will return an error if the formatted controller name violates the required
180+ /// Kubernetes restrictions.
122181 pub fn managed_by ( operator_name : & str , controller_name : & str ) -> Result < Self , LabelError > {
123182 let kvp = KeyValuePair :: try_from ( (
124183 K8S_APP_MANAGED_BY_KEY ,
@@ -127,14 +186,40 @@ impl Label {
127186 Ok ( Self ( kvp) )
128187 }
129188
130- /// Creates the `app.kubernetes.io/version` label with `version` as the
131- /// value. This function will return an error if `role_group` violates the
132- /// required Kubernetes restrictions.
189+ /// Creates the `app.kubernetes.io/version` label with `version` as the value.
190+ ///
191+ /// This function will return an error if `version` violates the required Kubernetes
192+ /// restrictions.
133193 pub fn version ( version : & str ) -> Result < Self , LabelError > {
134194 // NOTE (Techassi): Maybe use semver::Version
135195 let kvp = KeyValuePair :: try_from ( ( K8S_APP_VERSION_KEY , version) ) ?;
136196 Ok ( Self ( kvp) )
137197 }
198+
199+ /// Creates the `app.kubernetes.io/instance` label with `instance` as the value.
200+ ///
201+ /// This function will return an error if `instance` violates the required Kubernetes
202+ /// restrictions.
203+ pub fn instance ( instance : & str ) -> Result < Self , LabelError > {
204+ let kvp = KeyValuePair :: try_from ( ( K8S_APP_INSTANCE_KEY , instance) ) ?;
205+ Ok ( Self ( kvp) )
206+ }
207+
208+ /// Creates the `app.kubernetes.io/name` label with `name` as the value.
209+ ///
210+ /// This function will return an error if `name` violates the required Kubernetes restrictions.
211+ pub fn name ( name : & str ) -> Result < Self , LabelError > {
212+ let kvp = KeyValuePair :: try_from ( ( K8S_APP_NAME_KEY , name) ) ?;
213+ Ok ( Self ( kvp) )
214+ }
215+
216+ /// Creates the Stackable specific vendor label.
217+ ///
218+ /// See [`STACKABLE_VENDOR_KEY`] and [`STACKABLE_VENDOR_VALUE`].
219+ pub fn stackable_vendor ( ) -> Self {
220+ Self :: try_from ( ( STACKABLE_VENDOR_KEY , STACKABLE_VENDOR_VALUE ) )
221+ . expect ( "constant vendor label must be valid" )
222+ }
138223}
139224
140225/// A validated set/list of Kubernetes labels.
@@ -331,7 +416,7 @@ impl Labels {
331416 labels. insert ( version) ;
332417
333418 // Stackable-specific labels
334- labels. parse_insert ( ( STACKABLE_VENDOR_KEY , STACKABLE_VENDOR_VALUE ) ) ? ;
419+ labels. insert ( Label :: stackable_vendor ( ) ) ;
335420
336421 Ok ( labels)
337422 }
0 commit comments