Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Namespaced Scope Interceptor #1462

Merged
merged 3 commits into from
Nov 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/controller/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (

"github.com/tektoncd/triggers/pkg/reconciler/clusterinterceptor"
elresources "github.com/tektoncd/triggers/pkg/reconciler/eventlistener/resources"
"github.com/tektoncd/triggers/pkg/reconciler/interceptor"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/labels"
Expand Down Expand Up @@ -95,5 +96,6 @@ func main() {
cfg,
eventlistener.NewController(c),
clusterinterceptor.NewController(),
interceptor.NewController(),
)
}
1 change: 1 addition & 0 deletions cmd/webhook/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
var types = map[schema.GroupVersionKind]resourcesemantics.GenericCRD{
v1alpha1.SchemeGroupVersion.WithKind("ClusterTriggerBinding"): &v1alpha1.ClusterTriggerBinding{},
v1alpha1.SchemeGroupVersion.WithKind("ClusterInterceptor"): &v1alpha1.ClusterInterceptor{},
v1alpha1.SchemeGroupVersion.WithKind("Interceptor"): &v1alpha1.Interceptor{},
v1alpha1.SchemeGroupVersion.WithKind("EventListener"): &v1alpha1.EventListener{},
v1alpha1.SchemeGroupVersion.WithKind("TriggerBinding"): &v1alpha1.TriggerBinding{},
v1alpha1.SchemeGroupVersion.WithKind("TriggerTemplate"): &v1alpha1.TriggerTemplate{},
Expand Down
6 changes: 3 additions & 3 deletions config/200-clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,10 @@ rules:
resources: ["mutatingwebhookconfigurations", "validatingwebhookconfigurations"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["triggers.tekton.dev"]
resources: ["clustertriggerbindings", "clusterinterceptors", "eventlisteners", "triggerbindings", "triggertemplates", "triggers", "eventlisteners/finalizers"]
resources: ["clustertriggerbindings", "clusterinterceptors", "interceptors", "eventlisteners", "triggerbindings", "triggertemplates", "triggers", "eventlisteners/finalizers"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
- apiGroups: ["triggers.tekton.dev"]
resources: ["clustertriggerbindings/status", "clusterinterceptors/status", "eventlisteners/status", "triggerbindings/status", "triggertemplates/status", "triggers/status"]
resources: ["clustertriggerbindings/status", "clusterinterceptors/status", "interceptors/status", "eventlisteners/status", "triggerbindings/status", "triggertemplates/status", "triggers/status"]
verbs: ["get", "list", "create", "update", "delete", "patch", "watch"]
# We uses leases for leaderelection
- apiGroups: ["coordination.k8s.io"]
Expand Down Expand Up @@ -92,7 +92,7 @@ metadata:
app.kubernetes.io/part-of: tekton-triggers
rules:
- apiGroups: ["triggers.tekton.dev"]
resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"]
resources: ["eventlisteners", "triggerbindings", "interceptors", "triggertemplates", "triggers"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps"]
Expand Down
54 changes: 54 additions & 0 deletions config/300-interceptor.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# 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
#
# 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: interceptors.triggers.tekton.dev
labels:
app.kubernetes.io/instance: default
app.kubernetes.io/part-of: tekton-triggers
triggers.tekton.dev/release: "devel"
version: "devel"
spec:
group: triggers.tekton.dev
scope: Namespaced
names:
kind: Interceptor
plural: interceptors
singular: interceptor
shortNames:
- ni
categories:
- tekton
- tekton-triggers
versions:
- name: v1alpha1
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
# Opt into the status subresource so metadata.generation
# starts to increment
subresources:
status: {}
1 change: 1 addition & 0 deletions config/clusterrole-aggregate-edit.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ rules:
- clustertriggerbindings
- clusterinterceptors
- eventlisteners
- interceptors
- triggers
- triggerbindings
- triggertemplates
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 @@ -27,6 +27,7 @@ rules:
- clustertriggerbindings
- clusterinterceptors
- eventlisteners
- interceptors
- triggers
- triggerbindings
- triggertemplates
Expand Down
8 changes: 4 additions & 4 deletions docs/interceptors.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ transformation, define and test trigger conditions, and implement other useful p
the payload data to the `TriggerBinding`. You can also use an `Interceptor` to modify the behavior of the associated `Trigger`.

Tekton Triggers currently supports two distinct `Interceptor` implementations:
- Standalone `Interceptors`, which are instances of the [`ClusterInterceptor`](./clusterinterceptors.md) Custom Resource Definition (CRD). You specify these `Interceptors` by referencing them,
- Standalone `Interceptors`, which are instances of the [`Interceptor`](./namespacedinterceptor) or the [`ClusterInterceptor`](./clusterinterceptors.md) Custom Resource Definition (CRD). You specify these `Interceptors` by referencing them,
along with the desired parameters, within your `EventListener`. You can use the `ClusterInterceptor` CRD to implement your own custom `Interceptors`.
- Legacy `Interceptors`, which you define entirely as part of the `EventListener` definition. This implementation will eventually be deprecated, so please consider
transitioning to standalone `Interceptors` as soon as possible. See [TEP-0026](https://github.com/tektoncd/community/blob/main/teps/0026-interceptor-plugins.md) for more context on this change.
Expand All @@ -42,9 +42,9 @@ Tekton Triggers ships with the following `Interceptors` to help you get started:

To specify an `Interceptor` within your `EventListener`, create an `interceptors:` field with the following sub-fields:
- `name` - (optional) a name that uniquely identifies this `Interceptor` definition
- `ref` - a reference to a [`ClusterInterceptor`](./clusterinterceptors.md) object with the following fields:
- `ref` - a reference to a [`ClusterInterceptor`](./clusterinterceptors.md) or [`Interceptor`](./namespacedinterceptors.md) object with the following fields:
- `name` - the name of the referenced `ClusterInterceptor`
- `kind` - (optional) specifies that the referenced Kubernetes object is a `ClusterInterceptor` object
- `kind` - (optional) specifies that whether the referenced Kubernetes object is a `ClusterInterceptor` object or `NamespacedInterceptor`. Default value is `ClusterInterceptor`
- `apiVersion` - (optional) specifies the target API version, for example `triggers.tekton.dev/v1alpha1`
- `params` - `name`/`value` pairs that specify the parameters you want to pass to the `ClusterInterceptor`
- `params` - (optional) `name`/`value` pairs that specify the desired parameters for the `Interceptor`;
Expand Down Expand Up @@ -565,4 +565,4 @@ field both in the body of the payload as well as via the extra fields added to t

## Implementing custom `Interceptors`

Tekton Triggers ships with the `ClusterInterceptor` Custom Resource Definition (CRD), which you can use to implement custom `Interceptors`. See [`ClusterInterceptors`](./clusterinterceptors.md) for more information.
Tekton Triggers ships with the `ClusterInterceptor`and `Interceptor` Custom Resource Definition (CRD), which you can use to implement custom `Interceptors`. See [`ClusterInterceptors`](./clusterinterceptors.md) and [`NamespacedInterceptors`](./namespacedinterceptors.md) for more information.
76 changes: 76 additions & 0 deletions docs/namespacedinterceptors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<!--
---
linkTitle: "Namespaced Interceptors"
weight: 5
---
-->
# `Interceptors`

Tekton Triggers ships with the `Interceptor` Custom Resource Definition (CRD), which allows you to implement a custom namespaced-scoped Webhook-style `Interceptor`.

A `Interceptor` specifies an external Kubernetes v1 Service running custom business logic that receives the event payload from the
`EventListener` via an HTTP request and returns a processed version of the payload along with an HTTP 200 response. The `Interceptor` can also
halt processing if the event payload does not meet criteria you have configured as well as add extra fields that are accessible in the `EventListener's`
top-level `extensions` field to other [`Interceptors`](interceptors.md) and `Interceptors` chained with it and the associated `TriggerBinding`.

## Structure of a `Interceptor`

A `Interceptor` definition consists of the following fields:

- Required:
- [`apiVersion`][kubernetes-overview] - specifies the target API version, for example `triggers.tekton.dev/v1alpha1`
- [`kind`][kubernetes-overview] - specifies that this Kubernetes resource is a `Interceptor` object
- [`metadata`][kubernetes-overview] - specifies data that uniquely identifies this `Interceptor` object, for example a `name`
- [`spec`][kubernetes-overview] - specifies the configuration information for this `Interceptor` object, including:
- [`clientConfig`] - specifies how a client, such as an `EventListener` communicates with this `Interceptor` object

[kubernetes-overview]:
https://kubernetes.io/docs/concepts/overview/working-with-objects/kubernetes-objects/#required-fields

## Configuring the client of the `Interceptor`

The `clientConfig` field specifies the client, such as an `EventListener` and how it communicates with the `Interceptor` to exchange
event payload and other data. You can configure this field in one of the following ways:

- Specify the `url` field and as its value a URL at which the corresponding Kubernetes service listens for incoming requests from this `Interceptor`
- Specify the `service` field and within it reference the corresponding Kubernetes service that's listening for incoming requests from this `Interceptor`

For example:

```yaml
spec:
clientConfig:
url: "http://interceptor-svc.default.svc/"
---
spec:
clientConfig:
service:
name: "my-interceptor-svc"
namespace: "default"
path: "/optional-path" # optional
port: 8081 # defaults to 80
```

## Configuring a Kubernetes Service for the `Interceptor`

The Kubernetes object running the custom business logic for your `Interceptor` must meet the following criteria:

- Fronted by a regular Kubernetes v1 Service listening on an HTTP port (default port is 80)
- Accepts an HTTP `POST` request that contains an [`InterceptorRequest`](https://pkg.go.dev/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1#InterceptorRequest)
as a JSON body
- Returns an HTTP 200 OK response that contains an [`InterceptorResponse`](https://pkg.go.dev/github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1#InterceptorResponse)
as a JSON body. If the trigger processing should continue, the interceptor should set the `continue` field in the response to `true`. If the processing should be stopped, the interceptor should set the `continue` field to `false` and also provide additional information detailing the error in the `status` field.
- Returns a response other than HTTP 200 OK only if payload processing halts due to a catastrophic failure.

### Running Interceptor as HTTPS

Triggers support writing custom interceptor for both `http` and `https`. Support of `http` for custom interceptor will be removed in future and only `https` will be supported.

End user who write `https` custom interceptor need to pass `caBundle` as well as label
```yaml
labels:
server/type: https
```
to `Interceptor` in order to make secure connection with eventlistener.

Here is the reference for writing [https server for custom interceptor](https://github.com/tektoncd/triggers/blob/main/cmd/interceptors/main.go).
Loading