@@ -265,6 +265,59 @@ func TestEngine_templateConfigItems(t *testing.T) {
265265 },
266266 },
267267 },
268+ {
269+ name : "graceful failure on template error - returns empty values" ,
270+ config : & kotsv1beta1.Config {
271+ Spec : kotsv1beta1.ConfigSpec {
272+ Groups : []kotsv1beta1.ConfigGroup {
273+ {
274+ Name : "test" ,
275+ Items : []kotsv1beta1.ConfigItem {
276+ {
277+ Name : "valid_item" ,
278+ Value : multitype .FromString ("valid_value" ),
279+ },
280+ {
281+ Name : "invalid_template" ,
282+ Value : multitype .FromString ("repl{{ NonExistentFunc }}" ),
283+ },
284+ {
285+ Name : "another_valid" ,
286+ Value : multitype .FromString ("another_value" ),
287+ },
288+ },
289+ },
290+ },
291+ },
292+ },
293+ expected : & kotsv1beta1.Config {
294+ Spec : kotsv1beta1.ConfigSpec {
295+ Groups : []kotsv1beta1.ConfigGroup {
296+ {
297+ Name : "test" ,
298+ Items : []kotsv1beta1.ConfigItem {
299+ {
300+ Name : "valid_item" ,
301+ Value : multitype .FromString ("valid_value" ),
302+ Default : multitype .FromString ("" ),
303+ },
304+ {
305+ Name : "invalid_template" ,
306+ Value : multitype .FromString ("" ),
307+ Default : multitype .FromString ("" ),
308+ Filename : "" ,
309+ },
310+ {
311+ Name : "another_valid" ,
312+ Value : multitype .FromString ("another_value" ),
313+ Default : multitype .FromString ("" ),
314+ },
315+ },
316+ },
317+ },
318+ },
319+ },
320+ },
268321 }
269322
270323 for _ , tt := range tests {
@@ -544,3 +597,88 @@ func TestEngine_ShouldInvalidateItem(t *testing.T) {
544597 engine .depsTree = map [string ][]string {}
545598 assert .False (t , engine .shouldInvalidateItem ("item1" ), "should not invalidate item1 as it doesn't exist in either config values" )
546599}
600+
601+ // TestEngine_ConfigOption_HandlesFailuresGracefully tests that ConfigOption functions return empty
602+ // strings/false instead of propagating errors, allowing templates to complete successfully
603+ func TestEngine_ConfigOption_HandlesFailuresGracefully (t * testing.T ) {
604+ tests := []struct {
605+ name string
606+ configItem kotsv1beta1.ConfigItem
607+ template string
608+ expectResult string
609+ }{
610+ {
611+ name : "template error in value - ConfigOption returns empty string" ,
612+ configItem : kotsv1beta1.ConfigItem {
613+ Name : "bad_template" ,
614+ Value : multitype .FromString ("repl{{ NonExistentFunc }}" ),
615+ },
616+ template : "value:repl{{ ConfigOption \" bad_template\" }}" ,
617+ expectResult : "value:" ,
618+ },
619+ {
620+ name : "invalid base64 - ConfigOptionData returns empty string" ,
621+ configItem : kotsv1beta1.ConfigItem {
622+ Name : "invalid_base64" ,
623+ Value : multitype .FromString ("not-valid-base64!@#$" ),
624+ },
625+ template : "data:repl{{ ConfigOptionData \" invalid_base64\" }}" ,
626+ expectResult : "data:" ,
627+ },
628+ {
629+ name : "nonexistent item in middle of template" ,
630+ configItem : kotsv1beta1.ConfigItem {
631+ Name : "existing" ,
632+ Value : multitype .FromString ("exists" ),
633+ },
634+ template : "prefix-repl{{ ConfigOption \" nonexistent\" }}-suffix" ,
635+ expectResult : "prefix--suffix" ,
636+ },
637+ {
638+ name : "ConfigOptionEquals with nonexistent returns false" ,
639+ configItem : kotsv1beta1.ConfigItem {
640+ Name : "item" ,
641+ Value : multitype .FromString ("value" ),
642+ },
643+ template : "repl{{ if ConfigOptionEquals \" nonexistent\" \" test\" }}yes repl{{ else }}no repl{{ end }}" ,
644+ expectResult : "no " ,
645+ },
646+ {
647+ name : "ConfigOptionNotEquals with nonexistent returns false" ,
648+ configItem : kotsv1beta1.ConfigItem {
649+ Name : "item" ,
650+ Value : multitype .FromString ("value" ),
651+ },
652+ template : "repl{{ if ConfigOptionNotEquals \" nonexistent\" \" test\" }}yes repl{{ else }}no repl{{ end }}" ,
653+ expectResult : "no " ,
654+ },
655+ {
656+ name : "multiline YAML with failed ConfigOption" ,
657+ configItem : kotsv1beta1.ConfigItem {
658+ Name : "existing" ,
659+ Value : multitype .FromString ("value1" ),
660+ },
661+ template : "line1: repl{{ ConfigOption \" existing\" }}\n line2: repl{{ ConfigOption \" nonexistent\" }}\n line3: value3" ,
662+ expectResult : "line1: value1\n line2: \n line3: value3" ,
663+ },
664+ }
665+
666+ for _ , tt := range tests {
667+ t .Run (tt .name , func (t * testing.T ) {
668+ config := & kotsv1beta1.Config {
669+ Spec : kotsv1beta1.ConfigSpec {
670+ Groups : []kotsv1beta1.ConfigGroup {
671+ {
672+ Name : "test" ,
673+ Items : []kotsv1beta1.ConfigItem {tt .configItem },
674+ },
675+ },
676+ },
677+ }
678+ engine := NewEngine (config )
679+ result , err := engine .processTemplate (tt .template )
680+ require .NoError (t , err , "template execution should not fail" )
681+ assert .Equal (t , tt .expectResult , result )
682+ })
683+ }
684+ }
0 commit comments