Skip to content

Commit

Permalink
Reconciler, event, config, webhook support for CustomRuns
Browse files Browse the repository at this point in the history
This adds a reconciler for `CustomRun`s, and adds support for events and cloud events for `CustomRun`s as well.

It also adds the actual CRD for `CustomRun` to `config/`, along with cluster role changes for `CustomRun`s, and adds support for `CustomRun` to the webhook.

Signed-off-by: Andrew Bayer <andrew.bayer@gmail.com>
  • Loading branch information
abayer committed Oct 21, 2022
1 parent b63c1e2 commit 20eed59
Show file tree
Hide file tree
Showing 23 changed files with 711 additions and 52 deletions.
2 changes: 2 additions & 0 deletions cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/tektoncd/pipeline/pkg/apis/pipeline"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
"github.com/tektoncd/pipeline/pkg/reconciler/customrun"
"github.com/tektoncd/pipeline/pkg/reconciler/pipelinerun"
"github.com/tektoncd/pipeline/pkg/reconciler/resolutionrequest"
"github.com/tektoncd/pipeline/pkg/reconciler/run"
Expand Down Expand Up @@ -108,6 +109,7 @@ func main() {
pipelinerun.NewController(opts, clock.RealClock{}),
run.NewController(),
resolutionrequest.NewController(clock.RealClock{}),
customrun.NewController(),
)
}

Expand Down
1 change: 1 addition & 0 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,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{},
Expand Down
7 changes: 4 additions & 3 deletions config/200-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ rules:
# Controller needs cluster access to all of the CRDs that it is responsible for
# managing.
- apiGroups: ["tekton.dev"]
resources: ["tasks", "clustertasks", "taskruns", "pipelines", "pipelineruns", "pipelineresources", "runs"]
resources: ["tasks", "clustertasks", "taskruns", "pipelines", "pipelineruns", "pipelineresources", "runs", "customruns"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["tekton.dev"]
resources: ["taskruns/finalizers", "pipelineruns/finalizers", "runs/finalizers"]
resources: ["taskruns/finalizers", "pipelineruns/finalizers", "runs/finalizers", "customruns/finalizers"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["tekton.dev"]
resources: ["tasks/status", "clustertasks/status", "taskruns/status", "pipelines/status", "pipelineruns/status", "pipelineresources/status", "runs/status"]
resources: ["tasks/status", "clustertasks/status", "taskruns/status", "pipelines/status", "pipelineruns/status", "pipelineresources/status", "runs/status", "customruns/status"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
# resolution.tekton.dev
- apiGroups: ["resolution.tekton.dev"]
Expand Down Expand Up @@ -91,6 +91,7 @@ rules:
- taskruns.tekton.dev
- pipelineresources.tekton.dev
- resolutionrequests.resolution.tekton.dev
- customruns.tekton.dev
# knative.dev/pkg needs list/watch permissions to set up informers for the webhook.
- apiGroups: ["apiextensions.k8s.io"]
resources: ["customresourcedefinitions"]
Expand Down
69 changes: 69 additions & 0 deletions config/300-customrun.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# 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: true
storage: true
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
shortNames:
- cr
- crs
scope: Namespaced
1 change: 1 addition & 0 deletions config/clusterrole-aggregate-edit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ rules:
- pipelineruns
- pipelineresources
- runs
- customruns
verbs:
- create
- delete
Expand Down
1 change: 1 addition & 0 deletions config/clusterrole-aggregate-view.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ rules:
- pipelineruns
- pipelineresources
- runs
- customruns
verbs:
- get
- list
Expand Down
26 changes: 1 addition & 25 deletions docs/pipeline-api.md
Original file line number Diff line number Diff line change
Expand Up @@ -6753,7 +6753,7 @@ Resource Types:
<div>
<p>ClusterTask is a Task with a cluster scope. ClusterTasks are used to
represent Tasks that should be publicly addressable from any namespace in the
cluster.</p>
cluster. Deprecated: Please use the cluster resolver instead.</p>
</div>
<table>
<thead>
Expand Down Expand Up @@ -7071,18 +7071,6 @@ CustomRunSpecStatusMessage
</tr>
<tr>
<td>
<code>retries</code><br/>
<em>
int
</em>
</td>
<td>
<em>(Optional)</em>
<p>Used for propagating retries count to custom tasks</p>
</td>
</tr>
<tr>
<td>
<code>serviceAccountName</code><br/>
<em>
string
Expand Down Expand Up @@ -8324,18 +8312,6 @@ CustomRunSpecStatusMessage
</tr>
<tr>
<td>
<code>retries</code><br/>
<em>
int
</em>
</td>
<td>
<em>(Optional)</em>
<p>Used for propagating retries count to custom tasks</p>
</td>
</tr>
<tr>
<td>
<code>serviceAccountName</code><br/>
<em>
string
Expand Down
3 changes: 3 additions & 0 deletions pkg/apis/pipeline/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,7 @@ const (

// RunControllerName holds the name of the Custom Task controller
RunControllerName = "Run"

// CustomRunControllerName holds the name of the CustomRun controller
CustomRunControllerName = "CustomRun"
)
4 changes: 0 additions & 4 deletions pkg/apis/pipeline/v1beta1/customrun_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,10 +64,6 @@ type CustomRunSpec struct {
// +optional
StatusMessage CustomRunSpecStatusMessage `json:"statusMessage,omitempty"`

// Used for propagating retries count to custom tasks
// +optional
Retries int `json:"retries,omitempty"`

// +optional
ServiceAccountName string `json:"serviceAccountName"`

Expand Down
2 changes: 0 additions & 2 deletions pkg/apis/pipeline/v1beta1/customrun_types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ kind: CustomRun
metadata:
name: run
spec:
retries: 3
customRef:
apiVersion: example.dev/v0
kind: Example
Expand Down Expand Up @@ -228,7 +227,6 @@ status:
Name: "run",
},
Spec: v1beta1.CustomRunSpec{
Retries: 3,
CustomRef: &v1beta1.TaskRef{
APIVersion: "example.dev/v0",
Kind: "Example",
Expand Down
7 changes: 0 additions & 7 deletions pkg/apis/pipeline/v1beta1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions pkg/apis/pipeline/v1beta1/register.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&TaskRunList{},
&PipelineRun{},
&PipelineRunList{},
&CustomRun{},
&CustomRunList{},
)
// &Condition{},
// &ConditionList{},
Expand Down
5 changes: 0 additions & 5 deletions pkg/apis/pipeline/v1beta1/swagger.json
Original file line number Diff line number Diff line change
Expand Up @@ -525,11 +525,6 @@
},
"x-kubernetes-list-type": "atomic"
},
"retries": {
"description": "Used for propagating retries count to custom tasks",
"type": "integer",
"format": "int32"
},
"serviceAccountName": {
"type": "string",
"default": ""
Expand Down
59 changes: 59 additions & 0 deletions pkg/reconciler/customrun/controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
/*
Copyright 2022 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
http://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.
*/

package customrun

import (
"context"

"github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline"
customruninformer "github.com/tektoncd/pipeline/pkg/client/injection/informers/pipeline/v1beta1/customrun"
customrunreconciler "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1beta1/customrun"
cacheclient "github.com/tektoncd/pipeline/pkg/reconciler/events/cache"
cloudeventclient "github.com/tektoncd/pipeline/pkg/reconciler/events/cloudevent"
"knative.dev/pkg/configmap"
"knative.dev/pkg/controller"
"knative.dev/pkg/logging"
)

// NewController instantiates a new controller.Impl from knative.dev/pkg/controller
// This is a read-only controller, hence the SkipStatusUpdates set to true
func NewController() func(context.Context, configmap.Watcher) *controller.Impl {
return func(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
logger := logging.FromContext(ctx)
customRunInformer := customruninformer.Get(ctx)

configStore := config.NewStore(logger.Named("config-store"))
configStore.WatchConfigs(cmw)

c := &Reconciler{
cloudEventClient: cloudeventclient.Get(ctx),
cacheClient: cacheclient.Get(ctx),
}
impl := customrunreconciler.NewImpl(ctx, c, func(impl *controller.Impl) controller.Options {
return controller.Options{
AgentName: pipeline.CustomRunControllerName,
ConfigStore: configStore,
SkipStatusUpdates: true,
}
})

customRunInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))

return impl
}
}
73 changes: 73 additions & 0 deletions pkg/reconciler/customrun/customrun.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
/*
Copyright 2019 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
http://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.
*/

package customrun

import (
"context"

lru "github.com/hashicorp/golang-lru"
"github.com/tektoncd/pipeline/pkg/apis/config"
"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1"
customrunreconciler "github.com/tektoncd/pipeline/pkg/client/injection/reconciler/pipeline/v1beta1/customrun"
"github.com/tektoncd/pipeline/pkg/reconciler/events"
"github.com/tektoncd/pipeline/pkg/reconciler/events/cache"
"github.com/tektoncd/pipeline/pkg/reconciler/events/cloudevent"
_ "github.com/tektoncd/pipeline/pkg/taskrunmetrics/fake" // Make sure the taskrunmetrics are setup
"knative.dev/pkg/apis"
"knative.dev/pkg/logging"
pkgreconciler "knative.dev/pkg/reconciler"
)

// Reconciler implements controller.Reconciler for Configuration resources.
type Reconciler struct {
cloudEventClient cloudevent.CEClient
cacheClient *lru.Cache
}

// Check that our Reconciler implements customrunreconciler.Interface
var (
_ customrunreconciler.Interface = (*Reconciler)(nil)
)

// ReconcileKind compares the actual state with the desired, and attempts to
// converge the two. It then updates the Status block of the CustomRun
// resource with the current status of the resource.
func (c *Reconciler) ReconcileKind(ctx context.Context, customRun *v1beta1.CustomRun) pkgreconciler.Event {
logger := logging.FromContext(ctx)
configs := config.FromContextOrDefaults(ctx)
ctx = cloudevent.ToContext(ctx, c.cloudEventClient)
ctx = cache.ToContext(ctx, c.cacheClient)
// ctx = cache.ToContext(ctx, c.cacheClient)
logger.Infof("Reconciling %s", customRun.Name)

// Create a copy of the CustomRun object, just in case, to avoid sync'ing changes
customRunEvents := *customRun.DeepCopy()

if configs.FeatureFlags.SendCloudEventsForRuns {
// Custom task controllers may be sending events for "CustomRuns" associated
// to the custom tasks they control. To avoid sending duplicate events,
// CloudEvents for "CustomRuns" are only sent when enabled

// Read and log the condition
condition := customRunEvents.Status.GetCondition(apis.ConditionSucceeded)
logger.Debugf("Emitting cloudevent for %s, condition: %s", customRunEvents.Name, condition)

events.EmitCloudEvents(ctx, &customRunEvents)
}

return nil
}
Loading

0 comments on commit 20eed59

Please sign in to comment.