@@ -728,60 +728,92 @@ func validateResourceCELExpressions(resources map[string]*Resource, instance *Re
728
728
for _ , resource := range resources {
729
729
// exclude resource from the context
730
730
delete (expressionContext , resource .id )
731
- for _ , resourceVariable := range resource .variables {
732
- for _ , expression := range resourceVariable .Expressions {
733
- _ , err = dryRunExpressions (env , expression , resourceIDs , expressionContext )
734
- if err != nil {
735
- return fmt .Errorf ("failed to dry-run expression %s: %w" , expression , err )
736
- }
737
- }
731
+
732
+ err := ensureResourceExpressions (env , expressionContext , resource )
733
+ if err != nil {
734
+ return fmt .Errorf ("failed to ensure resource %s expressions: %w" , resource .id , err )
738
735
}
739
- // validate readyWhen Expressions for resource
740
- // Only accepting expressions accessing the status and spec for now
741
- // and need to evaluate to a boolean type
742
- for _ , readyWhenExpression := range resource .readyWhenExpressions {
743
- fieldEnv , err := krocel .DefaultEnvironment (krocel .WithResourceIDs ([]string {resource .id }))
744
- if err != nil {
745
- return fmt .Errorf ("failed to create CEL environment: %w" , err )
746
- }
747
736
748
- resourceEmulatedCopy := resource .emulatedObject .DeepCopy ()
749
- if resourceEmulatedCopy != nil && resourceEmulatedCopy .Object != nil {
750
- // ignore apiVersion and kind from readyWhenExpression context
751
- delete (resourceEmulatedCopy .Object , "apiVersion" )
752
- delete (resourceEmulatedCopy .Object , "kind" )
753
- }
754
- context := map [string ]* Resource {}
755
- context [resource .id ] = & Resource {
756
- emulatedObject : resourceEmulatedCopy ,
757
- }
737
+ err = ensureReadyWhenExpressions (resource )
738
+ if err != nil {
739
+ return fmt .Errorf ("failed to ensure resource %s readyWhen expressions: %w" , resource .id , err )
740
+ }
758
741
759
- output , err := dryRunExpressions (fieldEnv , readyWhenExpression , []string {resource .id }, context )
760
- if err != nil {
761
- return fmt .Errorf ("failed to dry-run expression %s: %w" , readyWhenExpression , err )
762
- }
763
- if ! krocel .IsBoolType (output ) {
764
- return fmt .Errorf ("output of readyWhen expression %s can only be of type bool" , readyWhenExpression )
765
- }
742
+ err = ensureIncludeWhenExpressions (env , includeWhenContext , resource )
743
+ if err != nil {
744
+ return fmt .Errorf ("failed to ensure resource %s includeWhen expressions: %w" , resource .id , err )
766
745
}
767
746
768
- for _ , includeWhenExpression := range resource .includeWhenExpressions {
769
- output , err := dryRunExpressions (env , includeWhenExpression , resourceIDs , includeWhenContext )
747
+ // include the resource back to the context
748
+ expressionContext [resource .id ] = resource
749
+ }
750
+
751
+ return nil
752
+ }
753
+
754
+ // ensureResourceExpressions validates the CEL expressions in the resource
755
+ // against the resources defined in the resource graph definition.
756
+ func ensureResourceExpressions (env * cel.Env , context map [string ]* Resource , resource * Resource ) error {
757
+ // We need to validate the CEL expressions in the resource.
758
+ for _ , resourceVariable := range resource .variables {
759
+ for _ , expression := range resourceVariable .Expressions {
760
+ _ , err := ensureExpression (env , expression , []string {resource .id }, context )
770
761
if err != nil {
771
- return fmt .Errorf ("failed to dry-run expression %s: %w" , includeWhenExpression , err )
772
- }
773
- if ! krocel .IsBoolType (output ) {
774
- return fmt .Errorf ("output of includeWhen expression %s can only be of type bool" , includeWhenExpression )
762
+ return fmt .Errorf ("failed to dry-run expression %s: %w" , expression , err )
775
763
}
776
764
}
777
- // include the resource back to the context
778
- expressionContext [resource .id ] = resource
779
765
}
766
+ return nil
767
+ }
768
+
769
+ // ensureReadyWhenExpressions validates the readyWhen expressions in the resource
770
+ // against the resources defined in the resource graph definition.
771
+ func ensureReadyWhenExpressions (resource * Resource ) error {
772
+ env , err := krocel .DefaultEnvironment (krocel .WithResourceIDs ([]string {resource .id }))
773
+ for _ , expression := range resource .readyWhenExpressions {
774
+ if err != nil {
775
+ return fmt .Errorf ("failed to create CEL environment: %w" , err )
776
+ }
777
+
778
+ resourceEmulatedCopy := resource .emulatedObject .DeepCopy ()
779
+ if resourceEmulatedCopy != nil && resourceEmulatedCopy .Object != nil {
780
+ // ignore apiVersion and kind from readyWhenExpression context
781
+ delete (resourceEmulatedCopy .Object , "apiVersion" )
782
+ delete (resourceEmulatedCopy .Object , "kind" )
783
+ }
784
+ context := map [string ]* Resource {}
785
+ context [resource .id ] = & Resource {
786
+ emulatedObject : resourceEmulatedCopy ,
787
+ }
780
788
789
+ output , err := ensureExpression (env , expression , []string {resource .id }, context )
790
+ if err != nil {
791
+ return fmt .Errorf ("failed to dry-run expression %s: %w" , expression , err )
792
+ }
793
+ if ! krocel .IsBoolType (output ) {
794
+ return fmt .Errorf ("output of readyWhen expression %s can only be of type bool" , expression )
795
+ }
796
+ }
797
+ return nil
798
+ }
799
+
800
+ // ensureIncludeWhenExpressions validates the includeWhen expressions in the resource
801
+ func ensureIncludeWhenExpressions (env * cel.Env , context map [string ]* Resource , resource * Resource ) error {
802
+ // We need to validate the CEL expressions in the resource.
803
+ for _ , expression := range resource .includeWhenExpressions {
804
+ output , err := ensureExpression (env , expression , []string {resource .id }, context )
805
+ if err != nil {
806
+ return fmt .Errorf ("failed to dry-run expression %s: %w" , expression , err )
807
+ }
808
+ if ! krocel .IsBoolType (output ) {
809
+ return fmt .Errorf ("output of includeWhen expression %s can only be of type bool" , expression )
810
+ }
811
+ }
781
812
return nil
782
813
}
783
814
784
- func dryRunExpressions (env * cel.Env , expression string , resources []string , context map [string ]* Resource ) (ref.Val , error ) {
815
+ // ensureExpression validates the CEL expression in the context of the resources
816
+ func ensureExpression (env * cel.Env , expression string , resources []string , context map [string ]* Resource ) (ref.Val , error ) {
785
817
err := validateCELExpressionContext (env , expression , resources )
786
818
if err != nil {
787
819
return nil , fmt .Errorf ("failed to validate expression %s: %w" , expression , err )
0 commit comments