@@ -100,41 +100,61 @@ func NewPipelinesProvider(opts ...Opt) *PipelinesProvider {
100
100
return pp
101
101
}
102
102
103
- // Run creates a Tekton Pipeline and all necessary resources (PVCs, Secrets, SAs,...) for the input Function.
104
- // It ensures that all needed resources are present on the cluster so the PipelineRun can be initialized.
105
- // After the PipelineRun is being initialized, the progress of the PipelineRun is being watched and printed to the output.
106
- func (pp * PipelinesProvider ) Run (ctx context.Context , f fn.Function ) (string , string , error ) {
107
- fmt .Fprintf (os .Stderr , "Creating Pipeline resources\n " )
103
+ // Run a remote build by creating all necessary resources (PVCs, secrets,
104
+ // SAs, etc) specified by the given Function before generating a pipeline
105
+ // definition, sending it to the cluster to be run via Tekton.
106
+ // Progress is by default piped to stdtout.
107
+ // Returned is the final url, and the input Function with the final results of the run populated
108
+ // (f.Deploy.Image and f.Deploy.Namespace) or an error.
109
+ func (pp * PipelinesProvider ) Run (ctx context.Context , f fn.Function ) (string , fn.Function , error ) {
108
110
var err error
111
+
112
+ // Checks builder and registry:
109
113
if err = validatePipeline (f ); err != nil {
110
- return "" , "" , err
114
+ return "" , f , err
111
115
}
112
116
117
+ // Namespace is either a new namespace, specified as f.Namespace, or
118
+ // the currently deployed namespace, recorded on f.Deploy.Namespace.
119
+ // If neither exist, an error is returned (namespace is required)
113
120
namespace := f .Namespace
114
121
if namespace == "" {
115
122
namespace = f .Deploy .Namespace
116
123
}
124
+ if namespace == "" {
125
+ return "" , f , fn .ErrNamespaceRequired
126
+ }
127
+ f .Deploy .Namespace = namespace
117
128
118
- client , ns2 , err := NewTektonClientAndResolvedNamespace (namespace )
119
- if err != nil {
120
- return "" , "" , err
129
+ // Image is either an explicit image indicated with f.Image, or
130
+ // generated from a name+registry
131
+ image := f .Image
132
+ if image == "" {
133
+ image , err = f .ImageName ()
134
+ if err != nil {
135
+ return "" , f , err
136
+ }
121
137
}
122
- if ns2 != namespace {
123
- panic ("fixme" )
138
+ f .Deploy .Image = image
139
+
140
+ // Client for the given namespace
141
+ client , err := NewTektonClient (namespace )
142
+ if err != nil {
143
+ return "" , f , err
124
144
}
125
145
126
146
// let's specify labels that will be applied to every resource that is created for a Pipeline
127
147
labels , err := f .LabelsMap ()
128
148
if err != nil {
129
- return "" , "" , err
149
+ return "" , f , err
130
150
}
131
151
if pp .decorator != nil {
132
152
labels = pp .decorator .UpdateLabels (f , labels )
133
153
}
134
154
135
155
err = createPipelinePersistentVolumeClaim (ctx , f , namespace , labels )
136
156
if err != nil {
137
- return "" , "" , err
157
+ return "" , f , err
138
158
}
139
159
140
160
if f .Build .Git .URL == "" {
@@ -143,84 +163,88 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) (string, st
143
163
defer content .Close ()
144
164
err = k8s .UploadToVolume (ctx , content , getPipelinePvcName (f ), namespace )
145
165
if err != nil {
146
- return "" , "" , fmt .Errorf ("cannot upload sources to the PVC: %w" , err )
166
+ return "" , f , fmt .Errorf ("cannot upload sources to the PVC: %w" , err )
147
167
}
148
168
}
149
169
150
170
err = createAndApplyPipelineTemplate (f , namespace , labels )
151
171
if err != nil {
152
172
if ! k8serrors .IsAlreadyExists (err ) {
153
173
if k8serrors .IsNotFound (err ) {
154
- return "" , "" , fmt .Errorf ("problem creating pipeline, missing tekton?: %v" , err )
174
+ return "" , f , fmt .Errorf ("problem creating pipeline, missing tekton?: %v" , err )
155
175
}
156
- return "" , "" , fmt .Errorf ("problem creating pipeline: %v" , err )
176
+ return "" , f , fmt .Errorf ("problem creating pipeline: %v" , err )
157
177
}
158
178
}
159
179
160
- registry , err := docker .GetRegistry (f . Deploy . Image )
180
+ registry , err := docker .GetRegistry (image )
161
181
if err != nil {
162
- return "" , "" , fmt .Errorf ("problem in resolving image registry name: %v" , err )
182
+ return "" , f , fmt .Errorf ("problem in resolving image registry name: %v" , err )
163
183
}
164
184
165
- creds , err := pp .credentialsProvider (ctx , f . Deploy . Image )
185
+ creds , err := pp .credentialsProvider (ctx , image )
166
186
if err != nil {
167
- return "" , "" , err
187
+ return "" , f , err
168
188
}
169
189
190
+ // TODO(lkingland): This registry defaulting logic
191
+ // is either incorrect or in the wrong place. At this stage of the
192
+ // process registry should already be defined/defaulted, and this
193
+ // function should be creating resources and deploying. Missing
194
+ // data (like registry) should have failed early in the process
170
195
if registry == name .DefaultRegistry {
171
196
registry = authn .DefaultAuthKey
172
197
}
198
+ if f .Registry == "" {
199
+ f .Registry = registry
200
+ }
173
201
174
202
err = k8s .EnsureDockerRegistrySecretExist (ctx , getPipelineSecretName (f ), namespace , labels , f .Deploy .Annotations , creds .Username , creds .Password , registry )
175
203
if err != nil {
176
- return "" , "" , fmt .Errorf ("problem in creating secret: %v" , err )
177
- }
178
-
179
- if f .Registry == "" {
180
- f .Registry = registry
204
+ return "" , f , fmt .Errorf ("problem in creating secret: %v" , err )
181
205
}
182
206
183
207
err = createAndApplyPipelineRunTemplate (f , namespace , labels )
184
208
if err != nil {
185
- return "" , "" , fmt .Errorf ("problem in creating pipeline run: %v" , err )
209
+ return "" , f , fmt .Errorf ("problem in creating pipeline run: %v" , err )
186
210
}
187
211
188
212
// we need to give k8s time to actually create the Pipeline Run
189
213
time .Sleep (1 * time .Second )
190
214
191
215
newestPipelineRun , err := findNewestPipelineRunWithRetry (ctx , f , namespace , client )
192
216
if err != nil {
193
- return "" , "" , fmt .Errorf ("problem in listing pipeline runs: %v" , err )
217
+ return "" , f , fmt .Errorf ("problem in listing pipeline runs: %v" , err )
194
218
}
195
219
196
220
err = pp .watchPipelineRunProgress (ctx , newestPipelineRun , namespace )
197
221
if err != nil {
198
222
if ! errors .Is (err , context .Canceled ) {
199
- return "" , "" , fmt .Errorf ("problem in watching started pipeline run: %v" , err )
223
+ return "" , f , fmt .Errorf ("problem in watching started pipeline run: %v" , err )
200
224
}
201
225
// TODO replace deletion with pipeline-run cancellation
202
226
_ = client .PipelineRuns (namespace ).Delete (context .TODO (), newestPipelineRun .Name , metav1.DeleteOptions {})
203
- return "" , "" , fmt .Errorf ("pipeline run cancelled: %w" , context .Canceled )
227
+ return "" , f , fmt .Errorf ("pipeline run cancelled: %w" , context .Canceled )
204
228
}
205
229
206
230
newestPipelineRun , err = client .PipelineRuns (namespace ).Get (ctx , newestPipelineRun .Name , metav1.GetOptions {})
207
231
if err != nil {
208
- return "" , "" , fmt .Errorf ("problem in retriving pipeline run status: %v" , err )
232
+ return "" , f , fmt .Errorf ("problem in retriving pipeline run status: %v" , err )
209
233
}
210
234
211
235
if newestPipelineRun .Status .GetCondition (apis .ConditionSucceeded ).Status == corev1 .ConditionFalse {
212
236
message := getFailedPipelineRunLog (ctx , client , newestPipelineRun , namespace )
213
- return "" , "" , fmt .Errorf ("function pipeline run has failed with message: \n \n %s" , message )
237
+ return "" , f , fmt .Errorf ("function pipeline run has failed with message: \n \n %s" , message )
214
238
}
215
239
216
240
kClient , err := knative .NewServingClient (namespace )
217
241
if err != nil {
218
- return "" , "" , fmt .Errorf ("problem in retrieving status of deployed function: %v" , err )
242
+ return "" , f , fmt .Errorf ("problem in retrieving status of deployed function: %v" , err )
219
243
}
220
244
221
245
ksvc , err := kClient .GetService (ctx , f .Name )
222
246
if err != nil {
223
- return "" , "" , fmt .Errorf ("problem in retrieving status of deployed function: %v" , err )
247
+ return "" , f , fmt .Errorf ("problem in retrieving status of deployed function: %v" , err )
224
248
}
225
249
226
250
if ksvc .Generation == 1 {
@@ -230,10 +254,10 @@ func (pp *PipelinesProvider) Run(ctx context.Context, f fn.Function) (string, st
230
254
}
231
255
232
256
if ksvc .Namespace != namespace {
233
- panic ( "fixme 2" )
257
+ fmt . Fprintf ( os . Stderr , "Warning: Final ksvc namespace %q does not match expected %q" , ksvc . Namespace , namespace )
234
258
}
235
259
236
- return ksvc .Status .URL .String (), ksvc . Namespace , nil
260
+ return ksvc .Status .URL .String (), f , nil
237
261
}
238
262
239
263
// Creates tar stream with the function sources as they were in "./source" directory.
0 commit comments