From f7dcb09ca833e476b1b27e5ef44675be95304256 Mon Sep 17 00:00:00 2001 From: Yumeng Zhang Date: Fri, 30 Oct 2020 17:33:38 +0800 Subject: [PATCH] Use Listers to fetch data in the Sink This commit closes #797. This PR uses Listers to get resources in the Eventlistener Sink, rather than directly making calls to the API server. Currently, multiple informers need to be setup when creating a Sink object. But the Sink in the cmd/triggerrun still makes the direct API calls because it only makes the call once when executed, which means Lister cache is not useful in this case. All examples work under this change. --- cmd/eventlistenersink/main.go | 42 ++++++++++----- cmd/triggerrun/cmd/root.go | 14 +++-- docs/eventlisteners.md | 2 +- examples/README.md | 1 + examples/bitbucket/role.yaml | 32 +++++++++-- examples/cron/binding.yaml | 15 +++++- examples/cron/role.yaml | 17 +++++- examples/github/role.yaml | 30 ++++++++++- examples/gitlab/binding.yaml | 15 +++++- examples/gitlab/role.yaml | 17 +++++- .../clusterbinding.yaml | 1 + .../clusterrole.yaml | 2 +- .../triggerbinding-roles/role.yaml | 2 +- examples/triggers/rbac.yaml | 28 +++++++++- examples/v1alpha1-task/README.md | 1 + pkg/sink/sink.go | 20 ++++--- pkg/sink/sink_test.go | 28 ++++++---- pkg/template/resource.go | 13 +++-- pkg/template/resource_test.go | 7 ++- test/eventlistener_scale_test.go | 53 +++++++++++++++++-- test/eventlistener_test.go | 4 +- 21 files changed, 280 insertions(+), 64 deletions(-) diff --git a/cmd/eventlistenersink/main.go b/cmd/eventlistenersink/main.go index 0a9b22dfc..a82a8e8dc 100644 --- a/cmd/eventlistenersink/main.go +++ b/cmd/eventlistenersink/main.go @@ -17,6 +17,7 @@ limitations under the License. package main import ( + "context" "fmt" "log" "net/http" @@ -26,11 +27,13 @@ import ( dynamicClientset "github.com/tektoncd/triggers/pkg/client/dynamic/clientset" "github.com/tektoncd/triggers/pkg/client/dynamic/clientset/tekton" - "github.com/tektoncd/triggers/pkg/logging" + "github.com/tektoncd/triggers/pkg/client/informers/externalversions" + triggerLogging "github.com/tektoncd/triggers/pkg/logging" "github.com/tektoncd/triggers/pkg/sink" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" "k8s.io/client-go/rest" + "knative.dev/pkg/logging" "knative.dev/pkg/signals" ) @@ -43,7 +46,7 @@ const ( func main() { // set up signals so we handle the first shutdown signal gracefully - stopCh := signals.SetupSignalHandler() + ctx := signals.NewContext() clusterConfig, err := rest.InClusterConfig() if err != nil { @@ -61,7 +64,8 @@ func main() { } dynamicCS := dynamicClientset.New(tekton.WithClient(dynamicClient)) - logger := logging.ConfigureLogging(EventListenerLogKey, ConfigName, stopCh, kubeClient) + logger := triggerLogging.ConfigureLogging(EventListenerLogKey, ConfigName, ctx.Done(), kubeClient) + ctx = logging.WithLogger(ctx, logger) defer func() { err := logger.Sync() if err != nil { @@ -81,17 +85,29 @@ func main() { logger.Fatal(err) } + factory := externalversions.NewSharedInformerFactoryWithOptions(sinkClients.TriggersClient, + 30*time.Second, externalversions.WithNamespace(sinkArgs.ElNamespace)) + go func(ctx context.Context) { + factory.Start(ctx.Done()) + <-ctx.Done() + }(ctx) + // Create EventListener Sink r := sink.Sink{ - KubeClientSet: kubeClient, - DiscoveryClient: sinkClients.DiscoveryClient, - DynamicClient: dynamicCS, - TriggersClient: sinkClients.TriggersClient, - HTTPClient: http.DefaultClient, - EventListenerName: sinkArgs.ElName, - EventListenerNamespace: sinkArgs.ElNamespace, - Logger: logger, - Auth: sink.DefaultAuthOverride{}, + KubeClientSet: kubeClient, + DiscoveryClient: sinkClients.DiscoveryClient, + DynamicClient: dynamicCS, + TriggersClient: sinkClients.TriggersClient, + HTTPClient: http.DefaultClient, + EventListenerName: sinkArgs.ElName, + EventListenerNamespace: sinkArgs.ElNamespace, + Logger: logger, + Auth: sink.DefaultAuthOverride{}, + EventListenerLister: factory.Triggers().V1alpha1().EventListeners().Lister(), + TriggerLister: factory.Triggers().V1alpha1().Triggers().Lister(), + TriggerBindingLister: factory.Triggers().V1alpha1().TriggerBindings().Lister(), + ClusterTriggerBindingLister: factory.Triggers().V1alpha1().ClusterTriggerBindings().Lister(), + TriggerTemplateLister: factory.Triggers().V1alpha1().TriggerTemplates().Lister(), } // Listen and serve @@ -113,6 +129,6 @@ func main() { } if err := srv.ListenAndServe(); err != nil { - logger.Fatalf("faiiled to start eventlistener sink: %v", err) + logger.Fatalf("failed to start eventlistener sink: %v", err) } } diff --git a/cmd/triggerrun/cmd/root.go b/cmd/triggerrun/cmd/root.go index d66041e60..43b2ac276 100644 --- a/cmd/triggerrun/cmd/root.go +++ b/cmd/triggerrun/cmd/root.go @@ -19,6 +19,7 @@ package cmd import ( "bufio" "bytes" + "context" "encoding/json" "errors" "fmt" @@ -37,6 +38,7 @@ import ( "github.com/tektoncd/triggers/pkg/sink" "github.com/tektoncd/triggers/pkg/template" "go.uber.org/zap" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime/serializer/streaming" "k8s.io/client-go/dynamic" @@ -210,9 +212,15 @@ func processTriggerSpec(kubeClient kubernetes.Interface, client triggersclientse } rt, err := template.ResolveTrigger(el, - client.TriggersV1alpha1().TriggerBindings(tri.Namespace).Get, - client.TriggersV1alpha1().ClusterTriggerBindings().Get, - client.TriggersV1alpha1().TriggerTemplates(tri.Namespace).Get) + func(name string) (*triggersv1.TriggerBinding, error) { + return client.TriggersV1alpha1().TriggerBindings(tri.Namespace).Get(context.Background(), name, metav1.GetOptions{}) + }, + func(name string) (*triggersv1.ClusterTriggerBinding, error) { + return client.TriggersV1alpha1().ClusterTriggerBindings().Get(context.Background(), name, metav1.GetOptions{}) + }, + func(name string) (*triggersv1.TriggerTemplate, error) { + return client.TriggersV1alpha1().TriggerTemplates(tri.Namespace).Get(context.Background(), name, metav1.GetOptions{}) + }) if err != nil { log.Error("Failed to resolve Trigger: ", err) return nil, err diff --git a/docs/eventlisteners.md b/docs/eventlisteners.md index 7c99ac0ca..1d728efc9 100644 --- a/docs/eventlisteners.md +++ b/docs/eventlisteners.md @@ -87,7 +87,7 @@ rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] - verbs: ["get"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors resources: ["configmaps", "secrets"] diff --git a/examples/README.md b/examples/README.md index bdc8709ba..3ed2f5c5d 100644 --- a/examples/README.md +++ b/examples/README.md @@ -11,6 +11,7 @@ messages. ```sh kubectl apply -f role-resources/secret.yaml kubectl apply -f role-resources/serviceaccount.yaml +kubectl apply -f role-resources/clustertriggerbinding-roles kubectl apply -f role-resources/triggerbinding-roles kubectl apply -f triggertemplates/triggertemplate.yaml kubectl apply -f triggerbindings/triggerbinding.yaml diff --git a/examples/bitbucket/role.yaml b/examples/bitbucket/role.yaml index 8f64c0f58..80c230e9a 100644 --- a/examples/bitbucket/role.yaml +++ b/examples/bitbucket/role.yaml @@ -12,8 +12,8 @@ metadata: rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] - resources: ["eventlisteners", "triggerbindings", "triggertemplates"] - verbs: ["get"] + resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors, serviceaccounts only for per trigger authorization resources: ["configmaps", "secrets", "serviceaccounts"] @@ -33,4 +33,30 @@ subjects: roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: tekton-triggers-bitbucket-minimal \ No newline at end of file + name: tekton-triggers-bitbucket-minimal +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-triggers-bitbucket-binding +subjects: + - kind: ServiceAccount + name: tekton-triggers-bitbucket-sa + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-bitbucket-minimal +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-triggers-bitbucket-minimal + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-triggers +rules: + # Permissions for every EventListener deployment to function + - apiGroups: ["triggers.tekton.dev"] + resources: ["clustertriggerbindings"] + verbs: ["get", "list", "watch"] diff --git a/examples/cron/binding.yaml b/examples/cron/binding.yaml index 62037c628..b37c219e9 100644 --- a/examples/cron/binding.yaml +++ b/examples/cron/binding.yaml @@ -8,4 +8,17 @@ subjects: roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: tekton-triggers-cron-minimal \ No newline at end of file + name: tekton-triggers-cron-minimal +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-triggers-cron-binding +subjects: + - kind: ServiceAccount + name: tekton-triggers-cron-sa + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-cron-minimal diff --git a/examples/cron/role.yaml b/examples/cron/role.yaml index d8c4cc892..40f461318 100644 --- a/examples/cron/role.yaml +++ b/examples/cron/role.yaml @@ -5,8 +5,8 @@ metadata: rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] - resources: ["eventlisteners", "triggerbindings", "triggertemplates"] - verbs: ["get"] + resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors, serviceaccounts only for per trigger authorization resources: ["configmaps", "secrets", "serviceaccounts"] @@ -15,3 +15,16 @@ rules: - apiGroups: ["tekton.dev"] resources: ["pipelineruns", "pipelineresources", "taskruns"] verbs: ["create"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-triggers-cron-minimal + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-triggers +rules: + # Permissions for every EventListener deployment to function + - apiGroups: ["triggers.tekton.dev"] + resources: ["clustertriggerbindings"] + verbs: ["get", "list", "watch"] diff --git a/examples/github/role.yaml b/examples/github/role.yaml index e6f8e7de2..4cd502228 100644 --- a/examples/github/role.yaml +++ b/examples/github/role.yaml @@ -24,8 +24,8 @@ metadata: rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] - resources: ["eventlisteners", "triggerbindings", "triggertemplates"] - verbs: ["get"] + resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors, serviceaccounts only for per trigger authorization resources: ["configmaps", "secrets", "serviceaccounts"] @@ -34,3 +34,29 @@ rules: - apiGroups: ["tekton.dev"] resources: ["pipelineruns", "pipelineresources", "taskruns"] verbs: ["create"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-triggers-github-binding +subjects: + - kind: ServiceAccount + name: tekton-triggers-github-sa + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-github-minimal +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-triggers-github-minimal + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-triggers +rules: + # Permissions for every EventListener deployment to function + - apiGroups: ["triggers.tekton.dev"] + resources: ["clustertriggerbindings"] + verbs: ["get", "list", "watch"] diff --git a/examples/gitlab/binding.yaml b/examples/gitlab/binding.yaml index 896dde090..11d179b29 100644 --- a/examples/gitlab/binding.yaml +++ b/examples/gitlab/binding.yaml @@ -8,4 +8,17 @@ subjects: roleRef: apiGroup: rbac.authorization.k8s.io kind: Role - name: tekton-triggers-gitlab-minimal \ No newline at end of file + name: tekton-triggers-gitlab-minimal +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-triggers-gitlab-binding +subjects: + - kind: ServiceAccount + name: tekton-triggers-gitlab-sa + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-gitlab-minimal diff --git a/examples/gitlab/role.yaml b/examples/gitlab/role.yaml index 0cff63388..da6c15ab3 100644 --- a/examples/gitlab/role.yaml +++ b/examples/gitlab/role.yaml @@ -5,8 +5,8 @@ metadata: rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] - resources: ["eventlisteners", "triggerbindings", "triggertemplates"] - verbs: ["get"] + resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors, serviceaccounts only for per trigger authorization resources: ["configmaps", "secrets", "serviceaccounts"] @@ -15,3 +15,16 @@ rules: - apiGroups: ["tekton.dev"] resources: ["pipelineruns", "pipelineresources", "taskruns"] verbs: ["create"] +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-triggers-gitlab-minimal + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-triggers +rules: + # Permissions for every EventListener deployment to function + - apiGroups: ["triggers.tekton.dev"] + resources: ["clustertriggerbindings"] + verbs: ["get", "list", "watch"] diff --git a/examples/role-resources/clustertriggerbinding-roles/clusterbinding.yaml b/examples/role-resources/clustertriggerbinding-roles/clusterbinding.yaml index 3ecef78c1..95b92d832 100644 --- a/examples/role-resources/clustertriggerbinding-roles/clusterbinding.yaml +++ b/examples/role-resources/clustertriggerbinding-roles/clusterbinding.yaml @@ -5,6 +5,7 @@ metadata: subjects: - kind: ServiceAccount name: tekton-triggers-example-sa + namespace: default roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole diff --git a/examples/role-resources/clustertriggerbinding-roles/clusterrole.yaml b/examples/role-resources/clustertriggerbinding-roles/clusterrole.yaml index b1f06f2fd..9e1a23a33 100644 --- a/examples/role-resources/clustertriggerbinding-roles/clusterrole.yaml +++ b/examples/role-resources/clustertriggerbinding-roles/clusterrole.yaml @@ -6,7 +6,7 @@ rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] resources: ["clustertriggerbindings", "eventlisteners", "triggerbindings", "triggertemplates", "triggers"] - verbs: ["get"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors resources: ["configmaps", "secrets"] diff --git a/examples/role-resources/triggerbinding-roles/role.yaml b/examples/role-resources/triggerbinding-roles/role.yaml index e7d18f1cc..24d252e4a 100644 --- a/examples/role-resources/triggerbinding-roles/role.yaml +++ b/examples/role-resources/triggerbinding-roles/role.yaml @@ -6,7 +6,7 @@ rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] - verbs: ["get"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors resources: ["configmaps", "secrets"] diff --git a/examples/triggers/rbac.yaml b/examples/triggers/rbac.yaml index cb7e46fa0..01442b4be 100644 --- a/examples/triggers/rbac.yaml +++ b/examples/triggers/rbac.yaml @@ -7,7 +7,7 @@ rules: # Permissions for every EventListener deployment to function - apiGroups: ["triggers.tekton.dev"] resources: ["eventlisteners", "triggerbindings", "triggertemplates", "triggers"] - verbs: ["get"] + verbs: ["get", "list", "watch"] - apiGroups: [""] # secrets are only needed for GitHub/GitLab interceptors resources: ["configmaps", "secrets"] @@ -46,3 +46,29 @@ roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: tekton-triggers-example-minimal +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: tekton-triggers-example-binding +subjects: + - kind: ServiceAccount + name: tekton-triggers-example-sa + namespace: default +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: tekton-triggers-example-minimal +--- +kind: ClusterRole +apiVersion: rbac.authorization.k8s.io/v1 +metadata: + name: tekton-triggers-example-minimal + labels: + app.kubernetes.io/instance: default + app.kubernetes.io/part-of: tekton-triggers +rules: + # Permissions for every EventListener deployment to function + - apiGroups: ["triggers.tekton.dev"] + resources: ["clustertriggerbindings"] + verbs: ["get", "list", "watch"] diff --git a/examples/v1alpha1-task/README.md b/examples/v1alpha1-task/README.md index 85714d82c..f69129c2a 100644 --- a/examples/v1alpha1-task/README.md +++ b/examples/v1alpha1-task/README.md @@ -7,6 +7,7 @@ Creates an EventListener that creates a v1alpha1 TaskRun. 1. Create the service account: ```shell script + kubectl apply -f examples/role-resources/clustertriggerbinding-roles kubectl apply -f examples/role-resources/triggerbinding-roles kubectl apply -f examples/role-resources/ ``` diff --git a/pkg/sink/sink.go b/pkg/sink/sink.go index 426bd3648..3f80be493 100644 --- a/pkg/sink/sink.go +++ b/pkg/sink/sink.go @@ -18,7 +18,6 @@ package sink import ( "bytes" - "context" "encoding/json" "errors" "fmt" @@ -27,6 +26,7 @@ import ( triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1" triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned" + listers "github.com/tektoncd/triggers/pkg/client/listers/triggers/v1alpha1" "github.com/tektoncd/triggers/pkg/interceptors" "github.com/tektoncd/triggers/pkg/interceptors/bitbucket" "github.com/tektoncd/triggers/pkg/interceptors/cel" @@ -37,7 +37,6 @@ import ( "github.com/tektoncd/triggers/pkg/template" "go.uber.org/zap" kerrors "k8s.io/apimachinery/pkg/api/errors" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" discoveryclient "k8s.io/client-go/discovery" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -55,6 +54,13 @@ type Sink struct { EventListenerNamespace string Logger *zap.SugaredLogger Auth AuthOverride + + // listers index properties about resources + EventListenerLister listers.EventListenerLister + TriggerLister listers.TriggerLister + TriggerBindingLister listers.TriggerBindingLister + ClusterTriggerBindingLister listers.ClusterTriggerBindingLister + TriggerTemplateLister listers.TriggerTemplateLister } // Response defines the HTTP body that the Sink responds to events with. @@ -69,7 +75,7 @@ type Response struct { // HandleEvent processes an incoming HTTP event for the event listener. func (r Sink) HandleEvent(response http.ResponseWriter, request *http.Request) { - el, err := r.TriggersClient.TriggersV1alpha1().EventListeners(r.EventListenerNamespace).Get(context.Background(), r.EventListenerName, metav1.GetOptions{}) + el, err := r.EventListenerLister.EventListeners(r.EventListenerNamespace).Get(r.EventListenerName) if err != nil { r.Logger.Errorf("Error getting EventListener %s in Namespace %s: %s", r.EventListenerName, r.EventListenerNamespace, err) response.WriteHeader(http.StatusInternalServerError) @@ -144,7 +150,7 @@ func (r Sink) processTrigger(t *triggersv1.EventListenerTrigger, request *http.R } if t.Template == nil && t.TriggerRef != "" { - trigger, err := r.TriggersClient.TriggersV1alpha1().Triggers(r.EventListenerNamespace).Get(context.Background(), t.TriggerRef, metav1.GetOptions{}) + trigger, err := r.TriggerLister.Triggers(r.EventListenerNamespace).Get(t.TriggerRef) if err != nil { r.Logger.Errorf("Error getting Trigger %s in Namespace %s: %s", t.TriggerRef, r.EventListenerNamespace, err) return err @@ -166,9 +172,9 @@ func (r Sink) processTrigger(t *triggersv1.EventListenerTrigger, request *http.R } rt, err := template.ResolveTrigger(*t, - r.TriggersClient.TriggersV1alpha1().TriggerBindings(r.EventListenerNamespace).Get, - r.TriggersClient.TriggersV1alpha1().ClusterTriggerBindings().Get, - r.TriggersClient.TriggersV1alpha1().TriggerTemplates(r.EventListenerNamespace).Get) + r.TriggerBindingLister.TriggerBindings(r.EventListenerNamespace).Get, + r.ClusterTriggerBindingLister.Get, + r.TriggerTemplateLister.TriggerTemplates(r.EventListenerNamespace).Get) if err != nil { log.Error(err) return err diff --git a/pkg/sink/sink_test.go b/pkg/sink/sink_test.go index ba7e48d09..cdb7e0818 100644 --- a/pkg/sink/sink_test.go +++ b/pkg/sink/sink_test.go @@ -47,6 +47,11 @@ import ( triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1" dynamicclientset "github.com/tektoncd/triggers/pkg/client/dynamic/clientset" "github.com/tektoncd/triggers/pkg/client/dynamic/clientset/tekton" + clustertriggerbindinginformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/clustertriggerbinding" + eventlistenerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/eventlistener" + triggerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/trigger" + triggerbindinginformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/triggerbinding" + triggertemplateinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/triggertemplate" "github.com/tektoncd/triggers/pkg/template" "github.com/tektoncd/triggers/test" bldr "github.com/tektoncd/triggers/test/builder" @@ -96,14 +101,19 @@ func getSinkAssets(t *testing.T, resources test.Resources, elName string, auth A dynamicSet := dynamicclientset.New(tekton.WithClient(dynamicClient)) r := Sink{ - EventListenerName: elName, - EventListenerNamespace: namespace, - DynamicClient: dynamicSet, - DiscoveryClient: clients.Kube.Discovery(), - KubeClientSet: clients.Kube, - TriggersClient: clients.Triggers, - Logger: logger.Sugar(), - Auth: auth, + EventListenerName: elName, + EventListenerNamespace: namespace, + DynamicClient: dynamicSet, + DiscoveryClient: clients.Kube.Discovery(), + KubeClientSet: clients.Kube, + TriggersClient: clients.Triggers, + Logger: logger.Sugar(), + Auth: auth, + EventListenerLister: eventlistenerinformer.Get(ctx).Lister(), + TriggerLister: triggerinformer.Get(ctx).Lister(), + TriggerBindingLister: triggerbindinginformer.Get(ctx).Lister(), + ClusterTriggerBindingLister: clustertriggerbindinginformer.Get(ctx).Lister(), + TriggerTemplateLister: triggertemplateinformer.Get(ctx).Lister(), } return r, dynamicClient } @@ -1241,7 +1251,7 @@ func TestHandleEvent_no_trigger_or_ref(t *testing.T) { t.Fatalf("logged entries got %d, want 2", l) } entry := logged[1] - if entry.Message != "Error getting Trigger unknown in Namespace foo: triggers.triggers.tekton.dev \"unknown\" not found" { + if entry.Message != "Error getting Trigger unknown in Namespace foo: trigger.triggers.tekton.dev \"unknown\" not found" { t.Errorf("entry logged %q", entry.Message) } if entry.Level != zapcore.ErrorLevel { diff --git a/pkg/template/resource.go b/pkg/template/resource.go index 9c61bd6d2..559ab3646 100644 --- a/pkg/template/resource.go +++ b/pkg/template/resource.go @@ -18,7 +18,6 @@ package template import ( "bytes" - "context" "encoding/json" "fmt" "strings" @@ -41,9 +40,9 @@ type ResolvedTrigger struct { BindingParams []triggersv1.Param } -type getTriggerBinding func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.TriggerBinding, error) -type getTriggerTemplate func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.TriggerTemplate, error) -type getClusterTriggerBinding func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.ClusterTriggerBinding, error) +type getTriggerBinding func(name string) (*triggersv1.TriggerBinding, error) +type getTriggerTemplate func(name string) (*triggersv1.TriggerTemplate, error) +type getClusterTriggerBinding func(name string) (*triggersv1.ClusterTriggerBinding, error) // ResolveTrigger takes in a trigger containing object refs to bindings and // templates and resolves them to their underlying values. @@ -68,7 +67,7 @@ func ResolveTrigger(trigger triggersv1.EventListenerTrigger, getTB getTriggerBin // Ignore staticcheck linter as it will complain about using deprecated type ttName = trigger.Template.Name //nolint:staticcheck } - resolvedTT, err = getTT(context.Background(), ttName, metav1.GetOptions{}) + resolvedTT, err = getTT(ttName) if err != nil { return ResolvedTrigger{}, fmt.Errorf("error getting TriggerTemplate %s: %w", ttName, err) } @@ -92,14 +91,14 @@ func resolveBindingsToParams(bindings []*triggersv1.TriggerSpecBinding, getTB ge }) case b.Ref != "" && b.Kind == triggersv1.ClusterTriggerBindingKind: - ctb, err := getCTB(context.Background(), b.Ref, metav1.GetOptions{}) + ctb, err := getCTB(b.Ref) if err != nil { return nil, fmt.Errorf("error getting ClusterTriggerBinding %s: %w", b.Name, err) } bindingParams = append(bindingParams, ctb.Spec.Params...) case b.Ref != "": // if no kind is set, assume NamespacedTriggerBinding - tb, err := getTB(context.Background(), b.Ref, metav1.GetOptions{}) + tb, err := getTB(b.Ref) if err != nil { return nil, fmt.Errorf("error getting TriggerBinding %s: %w", b.Name, err) } diff --git a/pkg/template/resource_test.go b/pkg/template/resource_test.go index f57d12210..a124428a9 100644 --- a/pkg/template/resource_test.go +++ b/pkg/template/resource_test.go @@ -17,7 +17,6 @@ limitations under the License. package template import ( - "context" "encoding/json" "fmt" "testing" @@ -206,19 +205,19 @@ var ( }, }, } - getTB = func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.TriggerBinding, error) { + getTB = func(name string) (*triggersv1.TriggerBinding, error) { if v, ok := triggerBindings[name]; ok { return v, nil } return nil, fmt.Errorf("error invalid name: %s", name) } - getCTB = func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.ClusterTriggerBinding, error) { + getCTB = func(name string) (*triggersv1.ClusterTriggerBinding, error) { if v, ok := clusterTriggerBindings[name]; ok { return v, nil } return nil, fmt.Errorf("error invalid name: %s", name) } - getTT = func(ctx context.Context, name string, options metav1.GetOptions) (*triggersv1.TriggerTemplate, error) { + getTT = func(name string) (*triggersv1.TriggerTemplate, error) { if name == "my-triggertemplate" { return &tt, nil } diff --git a/test/eventlistener_scale_test.go b/test/eventlistener_scale_test.go index 7a56639c9..f52e82266 100644 --- a/test/eventlistener_scale_test.go +++ b/test/eventlistener_scale_test.go @@ -38,8 +38,8 @@ import ( func TestEventListenerScale(t *testing.T) { c, namespace := setup(t) - defer tearDown(t, c, namespace) - knativetest.CleanupOnInterrupt(func() { tearDown(t, c, namespace) }, t.Logf) + defer cleanupResources(t, c, namespace) + knativetest.CleanupOnInterrupt(func() { cleanupResources(t, c, namespace) }, t.Logf) t.Log("Start EventListener Scale e2e test") @@ -107,8 +107,8 @@ func createServiceAccount(t *testing.T, c *clients, namespace, name string) { ObjectMeta: metav1.ObjectMeta{Name: "sa-role"}, Rules: []rbacv1.PolicyRule{{ APIGroups: []string{triggersv1.GroupName}, - Resources: []string{"eventlisteners", "triggerbindings", "triggertemplates"}, - Verbs: []string{"get"}, + Resources: []string{"eventlisteners", "triggerbindings", "triggertemplates", "triggers"}, + Verbs: []string{"get", "list", "watch"}, }, { APIGroups: []string{""}, Resources: []string{"configmaps"}, @@ -138,4 +138,49 @@ func createServiceAccount(t *testing.T, c *clients, namespace, name string) { t.Fatalf("Error creating RoleBinding: %s", err) } + _, err = c.KubeClient.RbacV1().ClusterRoles().Create(context.Background(), + &rbacv1.ClusterRole{ + ObjectMeta: metav1.ObjectMeta{Name: "sa-clusterrole"}, + Rules: []rbacv1.PolicyRule{{ + APIGroups: []string{triggersv1.GroupName}, + Resources: []string{"clustertriggerbindings"}, + Verbs: []string{"get", "list", "watch"}, + }}, + }, metav1.CreateOptions{}, + ) + if err != nil { + t.Fatalf("Error creating ClusterRole: %s", err) + } + _, err = c.KubeClient.RbacV1().ClusterRoleBindings().Create(context.Background(), + &rbacv1.ClusterRoleBinding{ + ObjectMeta: metav1.ObjectMeta{Name: "sa-clusterrolebinding"}, + Subjects: []rbacv1.Subject{{ + Kind: "ServiceAccount", + Name: sa.Name, + Namespace: namespace, + }}, + RoleRef: rbacv1.RoleRef{ + APIGroup: "rbac.authorization.k8s.io", + Kind: "ClusterRole", + Name: "sa-clusterrole", + }, + }, metav1.CreateOptions{}, + ) + if err != nil { + t.Fatalf("Error creating ClusterRoleBinding: %s", err) + } +} + +func cleanupResources(t *testing.T, c *clients, namespace string) { + t.Helper() + tearDown(t, c, namespace) + + // Cleanup cluster-scoped resources + t.Logf("Deleting cluster-scoped resources") + if err := c.KubeClient.RbacV1().ClusterRoles().Delete(context.Background(), "sa-clusterrole", metav1.DeleteOptions{}); err != nil { + t.Errorf("Failed to delete clusterrole sa-clusterrole: %s", err) + } + if err := c.KubeClient.RbacV1().ClusterRoleBindings().Delete(context.Background(), "sa-clusterrolebinding", metav1.DeleteOptions{}); err != nil { + t.Errorf("Failed to delete clusterrolebinding sa-clusterrolebinding: %s", err) + } } diff --git a/test/eventlistener_test.go b/test/eventlistener_test.go index c1c88689f..5e60f5e0a 100644 --- a/test/eventlistener_test.go +++ b/test/eventlistener_test.go @@ -240,8 +240,8 @@ func TestEventListenerCreate(t *testing.T) { ObjectMeta: metav1.ObjectMeta{Name: "my-role"}, Rules: []rbacv1.PolicyRule{{ APIGroups: []string{triggersv1.GroupName}, - Resources: []string{"clustertriggerbindings", "eventlisteners", "triggerbindings", "triggertemplates"}, - Verbs: []string{"get"}, + Resources: []string{"clustertriggerbindings", "eventlisteners", "triggerbindings", "triggertemplates", "triggers"}, + Verbs: []string{"get", "list", "watch"}, }, { APIGroups: []string{"tekton.dev"}, Resources: []string{"pipelineresources"},