@@ -17,6 +17,8 @@ limitations under the License.
17
17
package tekton
18
18
19
19
import (
20
+ "context"
21
+ "encoding/base64"
20
22
"encoding/json"
21
23
"fmt"
22
24
"strings"
@@ -29,7 +31,15 @@ import (
29
31
"github.com/konflux-ci/integration-service/api/v1beta2"
30
32
"github.com/konflux-ci/operator-toolkit/metadata"
31
33
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
34
+ resolutionv1alpha1 "github.com/tektoncd/resolution/pkg/apis/resolution/v1alpha1"
35
+ yaml "gopkg.in/yaml.v3"
36
+ corev1 "k8s.io/api/core/v1"
32
37
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
38
+ "k8s.io/apimachinery/pkg/types"
39
+ "k8s.io/apimachinery/pkg/util/wait"
40
+ "k8s.io/client-go/util/retry"
41
+ knative "knative.dev/pkg/apis"
42
+ "sigs.k8s.io/controller-runtime/pkg/client"
33
43
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
34
44
)
35
45
@@ -63,6 +73,12 @@ const (
63
73
64
74
// Name of tekton git resolver param revision
65
75
TektonResolverGitParamRevision = "revision"
76
+
77
+ // Value of ResourceKind field for remote pipelines
78
+ ResourceKindPipeline = "pipeline"
79
+
80
+ // Value of ResourceKind field for remote pipelineruns
81
+ ResourceKindPipelineRun = "pipelinerun"
66
82
)
67
83
68
84
var (
@@ -103,18 +119,35 @@ func (r *IntegrationPipelineRun) AsPipelineRun() *tektonv1.PipelineRun {
103
119
104
120
// NewIntegrationPipelineRun creates an empty PipelineRun in the given namespace. The name will be autogenerated,
105
121
// using the prefix passed as an argument to the function.
106
- func NewIntegrationPipelineRun (prefix , namespace string , integrationTestScenario v1beta2.IntegrationTestScenario ) * IntegrationPipelineRun {
107
- resolverParams := []tektonv1.Param {}
122
+ func NewIntegrationPipelineRun (client client.Client , ctx context.Context , prefix , namespace string , integrationTestScenario v1beta2.IntegrationTestScenario ) (* IntegrationPipelineRun , error ) {
123
+ resolverParams := integrationTestScenario .Spec .ResolverRef .Params
124
+
125
+ resolver := integrationTestScenario .Spec .ResolverRef .Resolver
126
+ resourceKind := integrationTestScenario .Spec .ResolverRef .ResourceKind
127
+ if resourceKind == ResourceKindPipeline || resourceKind == "" {
128
+ return generateIntegrationPipelineRunFromPipelineResolver (prefix , namespace , resolver , resolverParams ), nil
129
+ } else if resourceKind == ResourceKindPipelineRun {
130
+ base64plr , err := getPipelineRunYamlFromPipelineRunResolver (client , ctx , prefix , namespace , resolver , resolverParams )
131
+ if err != nil {
132
+ return nil , err
133
+ }
134
+ return generateIntegrationPipelineRunFromBase64 (base64plr )
135
+ } else {
136
+ return nil , fmt .Errorf ("unrecognized resolver type '%s'" , resourceKind )
137
+ }
138
+ }
108
139
109
- for _ , scenarioParam := range integrationTestScenario .Spec .ResolverRef .Params {
110
- resolverParam := tektonv1.Param {
140
+ func generateIntegrationPipelineRunFromPipelineResolver (prefix , namespace , resolver string , resolverParams []v1beta2.ResolverParameter ) * IntegrationPipelineRun {
141
+ tektonResolverParams := []tektonv1.Param {}
142
+ for _ , scenarioParam := range resolverParams {
143
+ tektonResolverParam := tektonv1.Param {
111
144
Name : scenarioParam .Name ,
112
145
Value : tektonv1.ParamValue {
113
146
Type : tektonv1 .ParamTypeString ,
114
147
StringVal : scenarioParam .Value ,
115
148
},
116
149
}
117
- resolverParams = append (resolverParams , resolverParam )
150
+ tektonResolverParams = append (tektonResolverParams , tektonResolverParam )
118
151
}
119
152
120
153
pipelineRun := tektonv1.PipelineRun {
@@ -125,15 +158,92 @@ func NewIntegrationPipelineRun(prefix, namespace string, integrationTestScenario
125
158
Spec : tektonv1.PipelineRunSpec {
126
159
PipelineRef : & tektonv1.PipelineRef {
127
160
ResolverRef : tektonv1.ResolverRef {
128
- Resolver : tektonv1 .ResolverName (integrationTestScenario . Spec . ResolverRef . Resolver ),
129
- Params : resolverParams ,
161
+ Resolver : tektonv1 .ResolverName (resolver ),
162
+ Params : tektonResolverParams ,
130
163
},
131
164
},
132
165
},
133
166
}
167
+
134
168
return & IntegrationPipelineRun {pipelineRun }
135
169
}
136
170
171
+ func getPipelineRunYamlFromPipelineRunResolver (client client.Client , ctx context.Context , prefix , namespace , resolver string , resolverParams []v1beta2.ResolverParameter ) (string , error ) {
172
+ stringResolverParams := map [string ]string {}
173
+
174
+ for _ , scenarioParam := range resolverParams {
175
+ stringResolverParams [scenarioParam .Name ] = scenarioParam .Value
176
+ }
177
+
178
+ request := resolutionv1alpha1.ResolutionRequest {
179
+ ObjectMeta : metav1.ObjectMeta {
180
+ GenerateName : prefix + "-" ,
181
+ Namespace : namespace ,
182
+ Labels : map [string ]string {
183
+ "resolution.tekton.dev/type" : resolver ,
184
+ "konflux-ci.dev/created-by" : "integration-service" , // for backup garbage collection
185
+ },
186
+ },
187
+ Spec : resolutionv1alpha1.ResolutionRequestSpec {
188
+ Parameters : stringResolverParams ,
189
+ },
190
+ }
191
+
192
+ err := retry .OnError (retry .DefaultBackoff , func (e error ) bool { return true }, func () error {
193
+ return client .Create (ctx , & request )
194
+ })
195
+ if err != nil {
196
+ return "" , err
197
+ }
198
+ resolutionRequestName := request .ObjectMeta .Name
199
+ defer func () {
200
+ _ = retry .OnError (retry .DefaultBackoff , func (e error ) bool { return true }, func () error {
201
+ return client .Delete (ctx , & request )
202
+ })
203
+ }()
204
+
205
+ resolverBackoff := wait.Backoff {
206
+ Steps : 60 ,
207
+ Duration : 1 * time .Second ,
208
+ Factor : 1.0 ,
209
+ Jitter : 0.5 ,
210
+ }
211
+ var resolvedRequest resolutionv1alpha1.ResolutionRequest
212
+ err = retry .OnError (resolverBackoff , func (e error ) bool { return true }, func () error {
213
+ err = client .Get (ctx , types.NamespacedName {Namespace : namespace , Name : resolutionRequestName }, & resolvedRequest )
214
+ if err != nil {
215
+ return err
216
+ }
217
+ for _ , cond := range resolvedRequest .Status .Conditions {
218
+ if cond .Type == knative .ConditionSucceeded {
219
+ if cond .Status == corev1 .ConditionTrue {
220
+ // request resolved successfully, we can terminate retry block
221
+ return nil
222
+ }
223
+ }
224
+ }
225
+ return fmt .Errorf ("resolution for '%s' in namespace '%s' did not complete" , namespace , resolutionRequestName )
226
+ })
227
+
228
+ if err != nil {
229
+ return "" , err
230
+ }
231
+ return resolvedRequest .Status .Data , nil
232
+ }
233
+
234
+ func generateIntegrationPipelineRunFromBase64 (base64plr string ) (* IntegrationPipelineRun , error ) {
235
+ plrYaml , err := base64 .StdEncoding .DecodeString (base64plr )
236
+ if err != nil {
237
+ return nil , err
238
+ }
239
+ var pipelineRun tektonv1.PipelineRun
240
+ err = yaml .Unmarshal (plrYaml , & pipelineRun )
241
+ if err != nil {
242
+ return nil , err
243
+ }
244
+ return & IntegrationPipelineRun {pipelineRun }, nil
245
+ }
246
+
137
247
// Updates git resolver values parameters with values of params specified in the input map
138
248
// updates only exsitings parameters, doens't create new ones
139
249
func (iplr * IntegrationPipelineRun ) WithUpdatedTestsGitResolver (params map [string ]string ) * IntegrationPipelineRun {
0 commit comments