1- use std:: collections:: { BTreeMap , HashMap } ;
2- use std:: sync:: OnceLock ;
3-
4- use regex:: Regex ;
5- use tracing:: warn;
6-
71use super :: definition:: Variables ;
82use super :: runtime_config:: Env ;
93use super :: variable:: definition:: VariableDefinition ;
@@ -13,6 +7,10 @@ use super::{
137 restart_policy:: { BackoffStrategyConfig , RestartPolicyConfig } ,
148 runtime_config:: { Deployment , Executable , K8s , K8sObject , K8sObjectMeta , OnHost , Runtime } ,
159} ;
10+ use regex:: Regex ;
11+ use std:: collections:: { BTreeMap , HashMap } ;
12+ use std:: sync:: OnceLock ;
13+ use tracing:: warn;
1614
1715/// Regex that extracts the template values from a string.
1816///
@@ -59,20 +57,18 @@ fn normalized_var<'a>(
5957 . ok_or ( AgentTypeError :: MissingTemplateKey ( name. to_string ( ) ) )
6058}
6159
62- /// Returns a string with the first match of a variable replaced with the corresponding value
63- /// (according to the provided normalized variable).
60+ /// Returns a string with the variable replaced with the corresponding value .
6461fn replace (
65- re : & Regex ,
62+ variable : & str ,
6663 s : & str ,
67- var_name : & str ,
6864 normalized_var : & VariableDefinition ,
6965) -> Result < String , AgentTypeError > {
7066 let value = normalized_var
7167 . get_template_value ( )
72- . ok_or ( AgentTypeError :: MissingTemplateKey ( var_name . to_string ( ) ) ) ?
68+ . ok_or ( AgentTypeError :: MissingTemplateKey ( variable . to_string ( ) ) ) ?
7369 . to_string ( ) ;
7470
75- Ok ( re . replace ( s , value) . to_string ( ) )
71+ Ok ( s . replace ( variable , value. as_str ( ) ) )
7672}
7773
7874pub trait Templateable {
@@ -102,10 +98,10 @@ impl Templateable for String {
10298fn template_string ( s : String , variables : & Variables ) -> Result < String , AgentTypeError > {
10399 let re = template_re ( ) ;
104100 re. find_iter ( & s)
105- . map ( |i| i . as_str ( ) )
106- . try_fold ( s . clone ( ) , |r , i| {
107- let var_name = template_trim ( i ) ;
108- replace ( re , & r, var_name , normalized_var ( var_name , variables ) ? )
101+ . try_fold ( s . clone ( ) , |r , variable_to_substitute| {
102+ let var_name = template_trim ( variable_to_substitute . as_str ( ) ) ;
103+ let normalized_var = normalized_var ( var_name , variables ) ? ;
104+ replace ( variable_to_substitute . as_str ( ) , & r, normalized_var)
109105 } )
110106}
111107
@@ -345,16 +341,23 @@ mod tests {
345341 let variables = Variables :: from ( [
346342 (
347343 "nr-var:name" . to_string ( ) ,
348- VariableDefinition :: new ( String :: default ( ) , true , None , Some ( "Alice" . to_string ( ) ) ) ,
344+ VariableDefinition :: new (
345+ String :: default ( ) ,
346+ true ,
347+ None ,
348+ Some ( "Alice ${UNTOUCHED}" . to_string ( ) ) ,
349+ ) ,
349350 ) ,
350351 (
351352 "nr-var:age" . to_string ( ) ,
352353 VariableDefinition :: new ( String :: default ( ) , true , None , Some ( Number :: from ( 30 ) ) ) ,
353354 ) ,
354355 ] ) ;
355356
356- let input = "Hello ${nr-var:name}! You are ${nr-var:age} years old." . to_string ( ) ;
357- let expected_output = "Hello Alice! You are 30 years old." . to_string ( ) ;
357+ let input =
358+ "Hello ${nr-var:name}! You are ${nr-var:age} years old. ${UNTOUCHED}" . to_string ( ) ;
359+ let expected_output =
360+ "Hello Alice ${UNTOUCHED}! You are 30 years old. ${UNTOUCHED}" . to_string ( ) ;
358361 let actual_output = template_string ( input, & variables) . unwrap ( ) ;
359362 assert_eq ! ( actual_output, expected_output) ;
360363 }
@@ -499,7 +502,7 @@ mod tests {
499502 String :: default ( ) ,
500503 true ,
501504 None ,
502- Some ( "CHANGED-STRING" . to_string ( ) ) ,
505+ Some ( "CHANGED-STRING ${UNTOUCHED} " . to_string ( ) ) ,
503506 ) ,
504507 ) ,
505508 (
@@ -519,17 +522,19 @@ mod tests {
519522 ${nr-var:change.me.string}: "Do not scape me"
520523 ${nr-var:change.me.bool}: "Do not scape me"
521524 ${nr-var:change.me.number}: "Do not scape me"
525+ test: ${UNTOUCHED}
522526 "# ,
523527 )
524528 . unwrap ( ) ;
525529 let expected_output: serde_yaml:: Mapping = serde_yaml:: from_str (
526530 r#"
527- a_string: "CHANGED-STRING"
531+ a_string: "CHANGED-STRING ${UNTOUCHED} "
528532 a_boolean: true
529533 a_number: 42
530534 ${nr-var:change.me.string}: "Do not scape me"
531535 ${nr-var:change.me.bool}: "Do not scape me"
532536 ${nr-var:change.me.number}: "Do not scape me"
537+ test: ${UNTOUCHED}
533538 "# ,
534539 )
535540 . unwrap ( ) ;
@@ -547,7 +552,7 @@ mod tests {
547552 String :: default ( ) ,
548553 true ,
549554 None ,
550- Some ( "CHANGED-STRING" . to_string ( ) ) ,
555+ Some ( "CHANGED-STRING ${UNTOUCHED} " . to_string ( ) ) ,
551556 ) ,
552557 ) ,
553558 (
@@ -564,15 +569,17 @@ mod tests {
564569 - ${nr-var:change.me.string}
565570 - ${nr-var:change.me.bool}
566571 - ${nr-var:change.me.number}
572+ - ${UNTOUCHED}
567573 - Do not scape me
568574 "# ,
569575 )
570576 . unwrap ( ) ;
571577 let expected_output: serde_yaml:: Sequence = serde_yaml:: from_str (
572578 r#"
573- - CHANGED-STRING
579+ - CHANGED-STRING ${UNTOUCHED}
574580 - true
575581 - 42
582+ - ${UNTOUCHED}
576583 - Do not scape me
577584 "# ,
578585 )
@@ -591,7 +598,7 @@ mod tests {
591598 String :: default ( ) ,
592599 true ,
593600 None ,
594- Some ( "CHANGED-STRING" . to_string ( ) ) ,
601+ Some ( "CHANGED-STRING ${UNTOUCHED} " . to_string ( ) ) ,
595602 ) ,
596603 ) ,
597604 (
@@ -651,35 +658,37 @@ mod tests {
651658 a_yaml: ${nr-var:change.me.yaml}
652659 another_yaml: ${nr-var:yaml.with.var.placeholder} # A variable inside another variable value is not expanded
653660 string_key: "here, the value ${nr-var:change.me.yaml} is encoded as string because it is not alone"
661+ last_one: ${UNTOUCHED}
654662 "# ,
655663 )
656664 . unwrap ( ) ;
657665 let expected_output: serde_yaml:: Value = serde_yaml:: from_str (
658666 r#"
659667 an_object:
660- a_string: "CHANGED-STRING"
668+ a_string: "CHANGED-STRING ${UNTOUCHED} "
661669 a_boolean: true
662670 a_number: 42
663671 a_sequence:
664- - "CHANGED-STRING"
672+ - "CHANGED-STRING ${UNTOUCHED} "
665673 - true
666674 - 42
667675 a_nested_object:
668676 with_nested_sequence:
669- - a_string: "CHANGED-STRING"
677+ - a_string: "CHANGED-STRING ${UNTOUCHED} "
670678 - a_boolean: true
671679 - a_number: 42
672680 - a_yaml:
673681 key:
674682 value
675- a_string: "CHANGED-STRING"
683+ a_string: "CHANGED-STRING ${UNTOUCHED} "
676684 a_boolean: true
677685 a_number: 42
678686 a_yaml:
679687 key: value
680688 another_yaml:
681689 "this.will.not.be.expanded": "${nr-var:change.me.string}" # A variable inside another other variable value is not expanded
682690 string_key: "here, the value key: value\n is encoded as string because it is not alone"
691+ last_one: ${UNTOUCHED}
683692 "# , // FIXME? Note line above, the "key: value\n" part was replaced!!
684693 )
685694 . unwrap ( ) ;
@@ -943,19 +952,23 @@ mod tests {
943952 let neither_value_nor_default =
944953 VariableDefinition :: new ( String :: default ( ) , true , None :: < String > , None :: < String > ) ;
945954
946- let re = template_re ( ) ;
947955 assert_eq ! (
948956 "Value-${nr-var:other}" . to_string( ) ,
949- replace( re , "${nr-var:any}-${nr-var:other}" , "any ", & value_var) . unwrap( )
957+ replace( "${nr-var:any}" , "${nr-var:any}-${nr-var:other}" , & value_var) . unwrap( )
950958 ) ;
951959 assert_eq ! (
952960 "Default-${nr-var:other}" . to_string( ) ,
953- replace( re, "${nr-var:any}-${nr-var:other}" , "any" , & default_var) . unwrap( )
961+ replace(
962+ "${nr-var:any}" ,
963+ "${nr-var:any}-${nr-var:other}" ,
964+ & default_var
965+ )
966+ . unwrap( )
954967 ) ;
955968 let key = assert_matches ! (
956- replace( re , "${nr-var:any}-x " , "any" , & neither_value_nor_default) . unwrap_err( ) ,
969+ replace( "${nr-var:any}" , "${nr-var: any}-x " , & neither_value_nor_default) . unwrap_err( ) ,
957970 AgentTypeError :: MissingTemplateKey ( s) => s) ;
958- assert_eq ! ( "any" . to_string( ) , key) ;
971+ assert_eq ! ( "${nr-var: any} " . to_string( ) , key) ;
959972 }
960973
961974 #[ test]
0 commit comments