diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go index 93668dcd01d..f62f8b19f13 100644 --- a/cmd/webhook/main.go +++ b/cmd/webhook/main.go @@ -57,6 +57,7 @@ var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{ v1beta1.SchemeGroupVersion.WithKind("ClusterTask"): &v1beta1.ClusterTask{}, v1beta1.SchemeGroupVersion.WithKind("TaskRun"): &v1beta1.TaskRun{}, v1beta1.SchemeGroupVersion.WithKind("PipelineRun"): &v1beta1.PipelineRun{}, + v1beta1.SchemeGroupVersion.WithKind("CustomRun"): &v1beta1.CustomRun{}, // v1 v1.SchemeGroupVersion.WithKind("Task"): &v1.Task{}, v1.SchemeGroupVersion.WithKind("Pipeline"): &v1.Pipeline{}, diff --git a/config/300-customrun.yaml b/config/300-customrun.yaml new file mode 100644 index 00000000000..ecdf773ea1c --- /dev/null +++ b/config/300-customrun.yaml @@ -0,0 +1,66 @@ +# Copyright 2020 The Tekton Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: customruns.tekton.dev + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-pipelines + pipeline.tekton.dev/release: "devel" + version: "devel" +spec: + group: tekton.dev + preserveUnknownFields: false + versions: + - name: v1beta1 + served: false + storage: false + schema: + openAPIV3Schema: + type: object + # One can use x-kubernetes-preserve-unknown-fields: true + # at the root of the schema (and inside any properties, additionalProperties) + # to get the traditional CRD behaviour that nothing is pruned, despite + # setting spec.preserveUnknownProperties: false. + # + # See https://kubernetes.io/blog/2019/06/20/crd-structural-schema/ + # See issue: https://github.com/knative/serving/issues/912 + x-kubernetes-preserve-unknown-fields: true + additionalPrinterColumns: + - name: Succeeded + type: string + jsonPath: ".status.conditions[?(@.type==\"Succeeded\")].status" + - name: Reason + type: string + jsonPath: ".status.conditions[?(@.type==\"Succeeded\")].reason" + - name: StartTime + type: date + jsonPath: .status.startTime + - name: CompletionTime + type: date + jsonPath: .status.completionTime + # Opt into the status subresource so metadata.generation + # starts to increment + subresources: + status: {} + names: + kind: CustomRun + plural: customruns + singular: customrun + categories: + - tekton + - tekton-pipelines + scope: Namespaced diff --git a/pkg/reconciler/pipelinerun/pipelinerun.go b/pkg/reconciler/pipelinerun/pipelinerun.go index cd9d101eb35..2f9816dcd48 100644 --- a/pkg/reconciler/pipelinerun/pipelinerun.go +++ b/pkg/reconciler/pipelinerun/pipelinerun.go @@ -1014,6 +1014,77 @@ func (c *Reconciler) createRun(ctx context.Context, runName string, params []v1b return c.PipelineClientSet.TektonV1alpha1().Runs(pr.Namespace).Create(ctx, r, metav1.CreateOptions{}) } +func (c *Reconciler) createCustomRuns(ctx context.Context, rpt *resources.ResolvedPipelineTask, pr *v1beta1.PipelineRun) ([]*v1beta1.CustomRun, error) { + var runs []*v1beta1.CustomRun + matrixCombinations := matrix.FanOut(rpt.PipelineTask.Matrix.Params).ToMap() + for i, runName := range rpt.RunNames { + params := matrixCombinations[strconv.Itoa(i)] + run, err := c.createCustomRun(ctx, runName, params, rpt, pr) + if err != nil { + return nil, err + } + runs = append(runs, run) + } + return runs, nil +} + +func (c *Reconciler) createCustomRun(ctx context.Context, runName string, params []v1beta1.Param, rpt *resources.ResolvedPipelineTask, pr *v1beta1.PipelineRun) (*v1beta1.CustomRun, error) { + logger := logging.FromContext(ctx) + taskRunSpec := pr.GetTaskRunSpec(rpt.PipelineTask.Name) + params = append(params, rpt.PipelineTask.Params...) + r := &v1beta1.CustomRun{ + ObjectMeta: metav1.ObjectMeta{ + Name: runName, + Namespace: pr.Namespace, + OwnerReferences: []metav1.OwnerReference{*kmeta.NewControllerRef(pr)}, + Labels: getTaskrunLabels(pr, rpt.PipelineTask.Name, true), + Annotations: getTaskrunAnnotations(pr), + }, + Spec: v1beta1.CustomRunSpec{ + Retries: rpt.PipelineTask.Retries, + CustomRef: rpt.PipelineTask.TaskRef, + Params: params, + ServiceAccountName: taskRunSpec.TaskServiceAccountName, + }, + } + + if rpt.PipelineTask.Timeout != nil { + r.Spec.Timeout = rpt.PipelineTask.Timeout + } + + if rpt.PipelineTask.TaskSpec != nil { + j, err := json.Marshal(rpt.PipelineTask.TaskSpec.Spec) + if err != nil { + return nil, err + } + r.Spec.CustomSpec = &v1beta1.EmbeddedCustomRunSpec{ + TypeMeta: runtime.TypeMeta{ + APIVersion: rpt.PipelineTask.TaskSpec.APIVersion, + Kind: rpt.PipelineTask.TaskSpec.Kind, + }, + Metadata: rpt.PipelineTask.TaskSpec.Metadata, + Spec: runtime.RawExtension{ + Raw: j, + }, + } + } + var pipelinePVCWorkspaceName string + var err error + r.Spec.Workspaces, pipelinePVCWorkspaceName, err = getTaskrunWorkspaces(pr, rpt) + if err != nil { + return nil, err + } + + // Set the affinity assistant annotation in case the custom task creates TaskRuns or Pods + // that can take advantage of it. + if !c.isAffinityAssistantDisabled(ctx) && pipelinePVCWorkspaceName != "" { + r.Annotations[workspace.AnnotationAffinityAssistantName] = getAffinityAssistantName(pipelinePVCWorkspaceName, pr.Name) + } + + logger.Infof("Creating a new Run object %s", runName) + return c.PipelineClientSet.TektonV1beta1().CustomRuns(pr.Namespace).Create(ctx, r, metav1.CreateOptions{}) +} + func getTaskrunWorkspaces(pr *v1beta1.PipelineRun, rpt *resources.ResolvedPipelineTask) ([]v1beta1.WorkspaceBinding, string, error) { var workspaces []v1beta1.WorkspaceBinding var pipelinePVCWorkspaceName string