Skip to content

Commit

Permalink
Fix incorrect split example
Browse files Browse the repository at this point in the history
Also, adds a unit test that combines split and truncate.

Fixes #518

Signed-off-by: Dibyo Mukherjee <dibyo@google.com>
  • Loading branch information
dibyom committed Apr 6, 2020
1 parent b44b004 commit 2b66860
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 48 deletions.
111 changes: 64 additions & 47 deletions docs/eventlisteners.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
<!--
---
linkTitle: "Event Listeners"
weight: 5
## <!--

linkTitle: "Event Listeners" weight: 5

---

-->

# EventListener

EventListener is a Kubernetes custom resource that allows users a declarative
Expand All @@ -24,64 +26,77 @@ using [Event Interceptors](#Interceptors).

## Multi-Tenant Concerns

The EventListener is effectively an additional form of client into Tekton, versus what
example usage via `kubectl` or `tkn` which you have seen elsewhere. In particular, the HTTP based
events bypass the normal Kubernetes authentication path you get via `kubeconfig` files
and the `kubectl config` family of commands.
The EventListener is effectively an additional form of client into Tekton,
versus what example usage via `kubectl` or `tkn` which you have seen elsewhere.
In particular, the HTTP based events bypass the normal Kubernetes authentication
path you get via `kubeconfig` files and the `kubectl config` family of commands.

As such, there are set of items to consider when deciding how to
As such, there are set of items to consider when deciding how to

- best expose (each) EventListener in your cluster to the outside world.
- best control how (each) EventListener and the underlying API Objects described below access, create,
and update Tekton related API Objects in your cluster.
- best control how (each) EventListener and the underlying API Objects described
below access, create, and update Tekton related API Objects in your cluster.

Minimally, each EventListener has its [ServiceAccountName](#serviceAccountName) as noted below and all
events coming over the "Sink" result in any Tekton resource interactions being done with the permissions
assigned to that ServiceAccount.
Minimally, each EventListener has its [ServiceAccountName](#serviceAccountName)
as noted below and all events coming over the "Sink" result in any Tekton
resource interactions being done with the permissions assigned to that
ServiceAccount.

However, if you need differing levels of permissions over a set of Tekton resources across the various
[Triggers](#triggers) and [Interceptors](#Interceptors), where not all Triggers or Interceptors can
manipulate certain Tekton Resources in the same way, a simple, single EventListener will not suffice.
However, if you need differing levels of permissions over a set of Tekton
resources across the various [Triggers](#triggers) and
[Interceptors](#Interceptors), where not all Triggers or Interceptors can
manipulate certain Tekton Resources in the same way, a simple, single
EventListener will not suffice.

Your options at that point are as follows:

### Multiple EventListers (One EventListener Per Namespace)

You can create multiple EventListener objects, where your set of Triggers and Interceptors are spread out across the
EventListeners.
You can create multiple EventListener objects, where your set of Triggers and
Interceptors are spread out across the EventListeners.

If you create each of those EventListeners in their own namespace, it becomes easy to assign
varying permissions to the ServiceAccount of each one to serve your needs. And often times namespace
creation is coupled with a default set of ServiceAccounts and Secrets that are also defined.
So conceivably some administration steps are taken care of. You just update the permissions
of the automatically created ServiceAccounts.
If you create each of those EventListeners in their own namespace, it becomes
easy to assign varying permissions to the ServiceAccount of each one to serve
your needs. And often times namespace creation is coupled with a default set of
ServiceAccounts and Secrets that are also defined. So conceivably some
administration steps are taken care of. You just update the permissions of the
automatically created ServiceAccounts.

Possible drawbacks:
- Namespaces with associated Secrets and ServiceAccounts in an aggregate sense prove to be the most expensive
items in Kubernetes underlying `etcd` store. In larger clusters `etcd` storage capacity can become a concern.
- Multiple EventListeners means multiple HTTP ports that must be exposed to the external entities accessing
the "Sink". If you happen to have a HTTP Firewall between your Cluster and external entities, that means more
administrative cost, opening ports in the firewall for each Service, unless you can employ Kubernetes `Ingress` to
serve as a routing abstraction layer for your set of EventListeners.

- Namespaces with associated Secrets and ServiceAccounts in an aggregate sense
prove to be the most expensive items in Kubernetes underlying `etcd` store. In
larger clusters `etcd` storage capacity can become a concern.
- Multiple EventListeners means multiple HTTP ports that must be exposed to the
external entities accessing the "Sink". If you happen to have a HTTP Firewall
between your Cluster and external entities, that means more administrative
cost, opening ports in the firewall for each Service, unless you can employ
Kubernetes `Ingress` to serve as a routing abstraction layer for your set of
EventListeners.

### Multiple EventListeners (Multiple EventListeners per Namespace)

Multiple EventListeners per namespace will most likely mean more ServiceAccount/Secret/RBAC manipulation for
the administrator, as some of the built in generation of those artifacts as part of namespace creation are not
Multiple EventListeners per namespace will most likely mean more
ServiceAccount/Secret/RBAC manipulation for the administrator, as some of the
built in generation of those artifacts as part of namespace creation are not
applicable.

However you will save some on the `etcd` storage costs by reducing the number of namespaces.
However you will save some on the `etcd` storage costs by reducing the number of
namespaces.

Multiple EventListeners and potential Firewall concerns still apply (again unless you employ `Ingress`).
Multiple EventListeners and potential Firewall concerns still apply (again
unless you employ `Ingress`).

### ServiceAccount per EventListenerTrigger

Being able to set a ServiceAccount on an EventListenerTrigger allows for finer grained permissions as well.
Being able to set a ServiceAccount on an EventListenerTrigger allows for finer
grained permissions as well.

You still have to create the additional ServiceAccounts.

But staying within 1 namespace and minimizing the number of EventListeners with their associated "Sinks" minimizes
concerns around `etcd` storage and port considerations with Firewalls if `Ingress` is not utilized.
But staying within 1 namespace and minimizing the number of EventListeners with
their associated "Sinks" minimizes concerns around `etcd` storage and port
considerations with Firewalls if `Ingress` is not utilized.

## Syntax

Expand Down Expand Up @@ -165,14 +180,15 @@ triggers:
name: pipeline-template
```

Also, to support multi-tenant styled scenarios, where an administrator may not want all triggers to have
the same permissions as the `EventListener`, a service account can optionally be set at the trigger level
and used if present in place of the `EventListener` service account when creating resources:
Also, to support multi-tenant styled scenarios, where an administrator may not
want all triggers to have the same permissions as the `EventListener`, a service
account can optionally be set at the trigger level and used if present in place
of the `EventListener` service account when creating resources:

```yaml
triggers:
- name: trigger-1
serviceAccount:
serviceAccount:
name: trigger-1-sa
namespace: event-listener-namespace
interceptors:
Expand All @@ -183,9 +199,10 @@ triggers:
- name: message-binding
template:
name: pipeline-template
```
```

The default ClusterRole for the EventLister allows for reading ServiceAccounts from any namespace.
The default ClusterRole for the EventLister allows for reading ServiceAccounts
from any namespace.

### ServiceType

Expand Down Expand Up @@ -221,8 +238,8 @@ kubectl get pods --selector eventlistener=my-eventlistener
By default, EventListeners will attach the following labels automatically to all
resources it creates:

| Name | Description |
| ------------------------ | ------------------------------------------------------ |
| Name | Description |
| --------------------------------- | ------------------------------------------------------ |
| triggers.tekton.dev/eventlistener | Name of the EventListener that generated the resource. |
| triggers.tekton.dev/trigger | Name of the Trigger that generated the resource. |
| triggers.tekton.dev/eventid | UID of the incoming event. |
Expand Down Expand Up @@ -498,6 +515,7 @@ processed, and the `overlays` applied.

Optionally, no `filter` expression can be provided, and the `overlays` will be
applied to the incoming body.

<!-- FILE: examples/eventlisteners/cel-eventlistener-no-filter.yaml -->

```YAML
Expand Down Expand Up @@ -542,7 +560,7 @@ spec:
- key: extensions.truncated_sha
expression: "truncate(body.pull_request.head.sha, 7)"
- key: extensions.branch_name
expression: "truncate(body.ref.split, '/')[2]"
expression: "split(body.ref, '/')[2]"
bindings:
- name: pipeline-binding
template:
Expand Down Expand Up @@ -625,7 +643,6 @@ spec:
value: $(body.pull_request.head.short_sha)
```


## Examples

For complete examples, see
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ spec:
- key: extensions.truncated_sha
expression: "truncate(body.pull_request.head.sha, 7)"
- key: extensions.branch_name
expression: "truncate(body.ref.split, '/')[2]"
expression: "split(body.ref, '/')[2]"
bindings:
- name: pipeline-binding
template:
Expand Down
5 changes: 5 additions & 0 deletions pkg/interceptors/cel/cel_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,11 @@ func TestExpressionEvaluation(t *testing.T) {
expr: "split(body.value, '/')",
want: types.NewStringList(types.NewRegistry(), []string{"testing"}),
},
{
name: "combine split and truncate",
expr: "truncate(split(body.value, '/')[0], 2)",
want: types.String("te"),
},
{
name: "exact header lookup",
expr: "header.canonical('X-Test-Header')",
Expand Down

0 comments on commit 2b66860

Please sign in to comment.