@@ -17,11 +17,16 @@ limitations under the License.
1717package  resources
1818
1919import  (
20+ 	"context" 
2021	"fmt" 
22+ 	"strconv" 
23+ 	"strings" 
2124
25+ 	"github.com/tektoncd/pipeline/pkg/apis/config" 
2226	"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" 
2327	"github.com/tektoncd/pipeline/pkg/list" 
2428	"github.com/tektoncd/pipeline/pkg/reconciler/taskrun" 
29+ 	"github.com/tektoncd/pipeline/pkg/substitution" 
2530)
2631
2732// ValidateParamTypesMatching validate that parameters in PipelineRun override corresponding parameters in Pipeline of the same type. 
@@ -84,3 +89,110 @@ func ValidateObjectParamRequiredKeys(pipelineParameters []v1beta1.ParamSpec, pip
8489
8590	return  nil 
8691}
92+ 
93+ // ValidateParamArrayIndex validate if the array indexing param reference  target is existent 
94+ func  ValidateParamArrayIndex (ctx  context.Context , p  * v1beta1.PipelineSpec , pr  * v1beta1.PipelineRun ) error  {
95+ 	cfg  :=  config .FromContextOrDefaults (ctx )
96+ 	if  cfg .FeatureFlags .EnableAPIFields  !=  config .AlphaAPIFields  {
97+ 		return  nil 
98+ 	}
99+ 
100+ 	arrayParams  :=  extractParamIndexes (p .Params , pr .Spec .Params )
101+ 
102+ 	var  outofBoundParams  []string 
103+ 
104+ 	// collect all the references 
105+ 	for  i  :=  range  p .Tasks  {
106+ 		outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReferences (p .Tasks [i ].Params , arrayParams )... )
107+ 		outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReferences (p .Tasks [i ].Matrix , arrayParams )... )
108+ 		for  j  :=  range  p .Tasks [i ].Workspaces  {
109+ 			outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (p .Tasks [i ].Workspaces [j ].SubPath , arrayParams )... )
110+ 		}
111+ 		for  _ , wes  :=  range  p .Tasks [i ].WhenExpressions  {
112+ 			for  _ , v  :=  range  wes .Values  {
113+ 				outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (v , arrayParams )... )
114+ 			}
115+ 		}
116+ 	}
117+ 
118+ 	for  i  :=  range  p .Finally  {
119+ 		outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReferences (p .Finally [i ].Params , arrayParams )... )
120+ 		outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReferences (p .Finally [i ].Matrix , arrayParams )... )
121+ 		for  _ , wes  :=  range  p .Finally [i ].WhenExpressions  {
122+ 			for  _ , v  :=  range  wes .Values  {
123+ 				outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (v , arrayParams )... )
124+ 			}
125+ 		}
126+ 	}
127+ 
128+ 	if  len (outofBoundParams ) >  0  {
129+ 		return  fmt .Errorf ("non-existent param references:%v" , outofBoundParams )
130+ 	}
131+ 	return  nil 
132+ }
133+ 
134+ func  extractParamIndexes (defaults  []v1beta1.ParamSpec , params  []v1beta1.Param ) map [string ]int  {
135+ 	// Collect all array params 
136+ 	arrayParams  :=  make (map [string ]int )
137+ 
138+ 	patterns  :=  []string {
139+ 		"$(params.%s)" ,
140+ 		"$(params[%q])" ,
141+ 		"$(params['%s'])" ,
142+ 	}
143+ 
144+ 	// Collect array params lengths from defaults 
145+ 	for  _ , p  :=  range  defaults  {
146+ 		if  p .Default  !=  nil  {
147+ 			if  p .Default .Type  ==  v1beta1 .ParamTypeArray  {
148+ 				for  _ , pattern  :=  range  patterns  {
149+ 					for  i  :=  0 ; i  <  len (p .Default .ArrayVal ); i ++  {
150+ 						arrayParams [fmt .Sprintf (pattern , p .Name )] =  len (p .Default .ArrayVal )
151+ 					}
152+ 				}
153+ 			}
154+ 		}
155+ 	}
156+ 
157+ 	// Collect array params lengths from pipelinerun or taskrun 
158+ 	for  _ , p  :=  range  params  {
159+ 		if  p .Value .Type  ==  v1beta1 .ParamTypeArray  {
160+ 			for  _ , pattern  :=  range  patterns  {
161+ 				for  i  :=  0 ; i  <  len (p .Value .ArrayVal ); i ++  {
162+ 					arrayParams [fmt .Sprintf (pattern , p .Name )] =  len (p .Value .ArrayVal )
163+ 				}
164+ 			}
165+ 		}
166+ 	}
167+ 	return  arrayParams 
168+ }
169+ 
170+ func  findInvalidParamArrayReferences (params  []v1beta1.Param , arrayParams  map [string ]int ) []string  {
171+ 	var  outofBoundParams  []string 
172+ 	for  i  :=  range  params  {
173+ 		outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (params [i ].Value .StringVal , arrayParams )... )
174+ 		for  _ , v  :=  range  params [i ].Value .ArrayVal  {
175+ 			outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (v , arrayParams )... )
176+ 		}
177+ 		for  _ , v  :=  range  params [i ].Value .ObjectVal  {
178+ 			outofBoundParams  =  append (outofBoundParams , findInvalidParamArrayReference (v , arrayParams )... )
179+ 		}
180+ 	}
181+ 	return  outofBoundParams 
182+ }
183+ 
184+ func  findInvalidParamArrayReference (paramReference  string , arrayParams  map [string ]int ) []string  {
185+ 	var  outofBoundParams  []string 
186+ 	list  :=  substitution .ExtractParamsExpressions (paramReference )
187+ 	for  _ , val  :=  range  list  {
188+ 		indexString  :=  substitution .ExtractIntIndex (paramReference )
189+ 		idx , _  :=  strconv .Atoi (strings .TrimSuffix (strings .TrimPrefix (indexString , "[" ), "]" ))
190+ 		v  :=  substitution .TrimArrayIndex (val )
191+ 		if  paramLength , ok  :=  arrayParams [v ]; ok  {
192+ 			if  idx  >=  paramLength  {
193+ 				outofBoundParams  =  append (outofBoundParams , val )
194+ 			}
195+ 		}
196+ 	}
197+ 	return  outofBoundParams 
198+ }
0 commit comments