diff --git a/cmd/controller/main.go b/cmd/controller/main.go
index f2d043665..07f9bff73 100644
--- a/cmd/controller/main.go
+++ b/cmd/controller/main.go
@@ -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"
@@ -95,5 +96,6 @@ func main() {
cfg,
eventlistener.NewController(c),
clusterinterceptor.NewController(),
+ interceptor.NewController(),
)
}
diff --git a/cmd/webhook/main.go b/cmd/webhook/main.go
index b587fe7e8..8ff1bc428 100644
--- a/cmd/webhook/main.go
+++ b/cmd/webhook/main.go
@@ -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{},
diff --git a/config/200-clusterrole.yaml b/config/200-clusterrole.yaml
index ec90481c9..378f16ff6 100644
--- a/config/200-clusterrole.yaml
+++ b/config/200-clusterrole.yaml
@@ -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"]
@@ -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"]
diff --git a/config/300-interceptor.yaml b/config/300-interceptor.yaml
new file mode 100644
index 000000000..9d9368513
--- /dev/null
+++ b/config/300-interceptor.yaml
@@ -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: {}
diff --git a/config/clusterrole-aggregate-edit.yaml b/config/clusterrole-aggregate-edit.yaml
index 7d4498d61..e95ce9445 100644
--- a/config/clusterrole-aggregate-edit.yaml
+++ b/config/clusterrole-aggregate-edit.yaml
@@ -28,6 +28,7 @@ rules:
- clustertriggerbindings
- clusterinterceptors
- eventlisteners
+ - interceptors
- triggers
- triggerbindings
- triggertemplates
diff --git a/config/clusterrole-aggregate-view.yaml b/config/clusterrole-aggregate-view.yaml
index 44e4248ee..439d31ee9 100644
--- a/config/clusterrole-aggregate-view.yaml
+++ b/config/clusterrole-aggregate-view.yaml
@@ -27,6 +27,7 @@ rules:
- clustertriggerbindings
- clusterinterceptors
- eventlisteners
+ - interceptors
- triggers
- triggerbindings
- triggertemplates
diff --git a/docs/triggers-api.md b/docs/triggers-api.md
index d5ee1153e..cfe843701 100644
--- a/docs/triggers-api.md
+++ b/docs/triggers-api.md
@@ -600,7 +600,7 @@ string
ClientConfig
-(Appears on:ClusterInterceptorSpec)
+(Appears on:ClusterInterceptorSpec, InterceptorSpec)
ClientConfig describes how a client can communicate with the Interceptor
@@ -1182,6 +1182,79 @@ SecretRef
+
Interceptor
+
+
+
Interceptor describes a pluggable interceptor including configuration
+such as the fields it accepts and its deployment address. The type is based on
+the Validating/MutatingWebhookConfiguration types for configuring AdmissionWebhooks
+
+
InterceptorInterface
@@ -1204,6 +1277,9 @@ SecretRef
"ClusterInterceptor" |
ClusterInterceptorKind indicates that Interceptor type has a cluster scope.
|
+
"NamespacedInterceptor" |
+NamespacedInterceptorKind indicated that interceptor has a namespaced scope
+ |
InterceptorParams
@@ -1282,9 +1358,7 @@ InterceptorKind
(Optional)
- InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
-Currently only InterceptorKind is ClusterInterceptor, so the only valid value
-is the default one
+InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
|
@@ -1427,6 +1501,85 @@ Status
+InterceptorSpec
+
+
+(Appears on:Interceptor)
+
+
+
InterceptorSpec describes the Spec for an Interceptor
+
+
+
+
+Field |
+Description |
+
+
+
+
+
+clientConfig
+
+
+ClientConfig
+
+
+ |
+
+ |
+
+
+
+
InterceptorStatus
+
+
+(Appears on:Interceptor)
+
+
+
InterceptorStatus holds the status of the Interceptor
+
+
KubernetesResource
@@ -3612,6 +3765,9 @@ SecretRef
"ClusterInterceptor" |
ClusterInterceptorKind indicates that Interceptor type has a cluster scope.
|
+
"NamespacedInterceptor" |
+NamespacedInterceptorKind indicates that Interceptor type has a namespace scope.
+ |
InterceptorParams
@@ -3690,9 +3846,7 @@ InterceptorKind
(Optional)
- InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
-Currently only InterceptorKind is ClusterInterceptor, so the only valid value
-is the default one
+InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
|
diff --git a/examples/v1alpha1/namespace-selector/01_rbac.yaml b/examples/v1alpha1/namespace-selector/01_rbac.yaml
index 09c6ea0f6..2b455d70d 100644
--- a/examples/v1alpha1/namespace-selector/01_rbac.yaml
+++ b/examples/v1alpha1/namespace-selector/01_rbac.yaml
@@ -6,7 +6,7 @@ metadata:
rules:
# Permissions for every EventListener deployment to function
- apiGroups: ["triggers.tekton.dev"]
- resources: ["eventlisteners", "clustertriggerbindings", "clusterinterceptors", "triggerbindings", "triggertemplates", "triggers"]
+ resources: ["eventlisteners", "clustertriggerbindings", "clusterinterceptors", "interceptors", "triggerbindings", "triggertemplates", "triggers"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
diff --git a/examples/v1beta1/namespace-selector/01_rbac.yaml b/examples/v1beta1/namespace-selector/01_rbac.yaml
index 09c6ea0f6..2b455d70d 100644
--- a/examples/v1beta1/namespace-selector/01_rbac.yaml
+++ b/examples/v1beta1/namespace-selector/01_rbac.yaml
@@ -6,7 +6,7 @@ metadata:
rules:
# Permissions for every EventListener deployment to function
- apiGroups: ["triggers.tekton.dev"]
- resources: ["eventlisteners", "clustertriggerbindings", "clusterinterceptors", "triggerbindings", "triggertemplates", "triggers"]
+ resources: ["eventlisteners", "clustertriggerbindings", "clusterinterceptors", "interceptors", "triggerbindings", "triggertemplates", "triggers"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["configmaps", "secrets"]
diff --git a/pkg/adapter/adapter.go b/pkg/adapter/adapter.go
index 02a5d619a..fcad0611f 100644
--- a/pkg/adapter/adapter.go
+++ b/pkg/adapter/adapter.go
@@ -28,6 +28,7 @@ import (
"time"
clusterinterceptorsinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/clusterinterceptor"
+ interceptorsinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor"
clustertriggerbindingsinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/clustertriggerbinding"
eventlistenerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/eventlistener"
triggersinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/trigger"
@@ -108,7 +109,7 @@ func (s *sinker) getHTTPClient() (*http.Client, error) {
certPool := x509.NewCertPool()
- err := s.getCertFromClusterInterceptor(certPool)
+ err := s.getCertFromInterceptor(certPool)
if err != nil {
return &http.Client{}, fmt.Errorf("Timed out waiting on CaBundle to available for clusterInterceptor: %v", err)
}
@@ -119,7 +120,7 @@ func (s *sinker) getHTTPClient() (*http.Client, error) {
go func() {
for {
<-ticker.C
- if err := s.getCertFromClusterInterceptor(certPool); err != nil {
+ if err := s.getCertFromInterceptor(certPool); err != nil {
s.Logger.Fatalf("Timed out waiting on CaBundle to available for clusterInterceptor: %v", err)
}
}
@@ -141,7 +142,7 @@ func (s *sinker) getHTTPClient() (*http.Client, error) {
ExpectContinueTimeout: s.Args.ElHTTPClientExpectContinueTimeout * time.Second}}, nil
}
-func (s *sinker) getCertFromClusterInterceptor(certPool *x509.CertPool) error {
+func (s *sinker) getCertFromInterceptor(certPool *x509.CertPool) error {
var (
caCert []byte
count int
@@ -166,12 +167,38 @@ func (s *sinker) getCertFromClusterInterceptor(certPool *x509.CertPool) error {
}
}
}
- if httpsCILen != 0 && httpsCILen == count {
- return true, nil
+
+ if httpsCILen == 0 || httpsCILen != count {
+ return false, fmt.Errorf("empty caBundle in clusterInterceptor spec")
}
- return false, fmt.Errorf("empty caBundle in clusterInterceptor spec")
+
+ httpsCILen = 0
+ count = 0
+
+ interceptorList, err := interceptorsinformer.Get(s.injCtx).Lister().Interceptors(s.Namespace).List(labels.Everything())
+ if err != nil {
+ return false, err
+ }
+
+ for i := range interceptorList {
+ if v, k := interceptorList[i].Labels["server/type"]; k && v == "https" {
+ httpsCILen++
+ if !bytes.Equal(interceptorList[i].Spec.ClientConfig.CaBundle, []byte{}) {
+ caCert = interceptorList[i].Spec.ClientConfig.CaBundle
+ if ok := certPool.AppendCertsFromPEM(caCert); !ok {
+ return false, fmt.Errorf("unable to parse cert from %s", caCert)
+ }
+ count++
+ }
+ }
+ }
+ if httpsCILen != count {
+ return false, fmt.Errorf("empty caBundle in interceptor spec")
+ }
+
+ return true, nil
}); err != nil {
- return fmt.Errorf("Timed out waiting on CaBundle to available for clusterInterceptor: %v", err)
+ return fmt.Errorf("Timed out waiting on CaBundle to available for Interceptor: %v", err)
}
return nil
}
@@ -206,6 +233,7 @@ func (s *sinker) Start(ctx context.Context) error {
ClusterTriggerBindingLister: clustertriggerbindingsinformer.Get(s.injCtx).Lister(),
TriggerTemplateLister: triggertemplatesinformer.Get(s.injCtx).Lister(),
ClusterInterceptorLister: clusterinterceptorsinformer.Get(s.injCtx).Lister(),
+ InterceptorLister: interceptorsinformer.Get(s.injCtx).Lister(),
}
mux := http.NewServeMux()
diff --git a/pkg/apis/triggers/v1alpha1/interceptor_defaults.go b/pkg/apis/triggers/v1alpha1/interceptor_defaults.go
new file mode 100644
index 000000000..d43eac53a
--- /dev/null
+++ b/pkg/apis/triggers/v1alpha1/interceptor_defaults.go
@@ -0,0 +1,36 @@
+/*
+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 v1alpha1
+
+import (
+ "context"
+
+ "github.com/tektoncd/triggers/pkg/apis/triggers/contexts"
+)
+
+// SetDefaults sets the defaults on the object.
+func (it *Interceptor) SetDefaults(ctx context.Context) {
+ if !contexts.IsUpgradeViaDefaulting(ctx) {
+ return
+ }
+ if _, ok := it.GetLabels()["server/type"]; !ok {
+ // if server type is not set its assumed that running server is http
+ it.Labels = map[string]string{
+ "server/type": "http",
+ }
+ }
+}
diff --git a/pkg/apis/triggers/v1alpha1/interceptor_types.go b/pkg/apis/triggers/v1alpha1/interceptor_types.go
index a87a53e0d..f634dae14 100644
--- a/pkg/apis/triggers/v1alpha1/interceptor_types.go
+++ b/pkg/apis/triggers/v1alpha1/interceptor_types.go
@@ -1,13 +1,94 @@
package v1alpha1
import (
+ "bytes"
"context"
"fmt"
"strings"
"google.golang.org/grpc/codes"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "knative.dev/pkg/apis"
+ duckv1 "knative.dev/pkg/apis/duck/v1"
)
+// Check that Interceptor may be validated and defaulted.
+var _ apis.Validatable = (*Interceptor)(nil)
+var _ apis.Defaultable = (*Interceptor)(nil)
+
+// +genclient
+// +genreconciler:krshapedlogic=false
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// +k8s:openapi-gen=true
+// Interceptor describes a pluggable interceptor including configuration
+// such as the fields it accepts and its deployment address. The type is based on
+// the Validating/MutatingWebhookConfiguration types for configuring AdmissionWebhooks
+type Interceptor struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ObjectMeta `json:"metadata,omitempty"`
+
+ Spec InterceptorSpec `json:"spec"`
+ // +optional
+ Status InterceptorStatus `json:"status"`
+}
+
+// InterceptorSpec describes the Spec for an Interceptor
+type InterceptorSpec struct {
+ ClientConfig ClientConfig `json:"clientConfig"`
+}
+
+// InterceptorStatus holds the status of the Interceptor
+// +k8s:deepcopy-gen=true
+type InterceptorStatus struct {
+ duckv1.Status `json:",inline"`
+
+ // Interceptor is Addressable and exposes the URL where the Interceptor is running
+ duckv1.AddressStatus `json:",inline"`
+}
+
+// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
+// InterceptorList contains a list of Interceptor
+// We don't use this but it's required for certain codegen features.
+type InterceptorList struct {
+ metav1.TypeMeta `json:",inline"`
+ // +optional
+ metav1.ListMeta `json:"metadata,omitempty"`
+ Items []Interceptor `json:"items"`
+}
+
+// ResolveAddress returns the URL where the interceptor is running using its clientConfig
+func (it *Interceptor) ResolveAddress() (*apis.URL, error) {
+ if url := it.Spec.ClientConfig.URL; url != nil {
+ return url, nil
+ }
+ svc := it.Spec.ClientConfig.Service
+ if svc == nil {
+ return nil, ErrNilURL
+ }
+ var (
+ port *int32
+ url *apis.URL
+ )
+
+ if svc.Port != nil {
+ port = svc.Port
+ }
+
+ if bytes.Equal(it.Spec.ClientConfig.CaBundle, []byte{}) {
+ if port == nil {
+ port = &defaultHTTPPort
+ }
+ url = formURL("http", svc, port)
+ } else {
+ if port == nil {
+ port = &defaultHTTPSPort
+ }
+ url = formURL("https", svc, port)
+ }
+ return url, nil
+}
+
type InterceptorInterface interface {
// Process executes the given InterceptorRequest. Simply getting a non-nil InterceptorResponse back is not sufficient
// to determine if the interceptor processing was successful. Instead use the InterceptorResponse.Status.Continue to
diff --git a/pkg/apis/triggers/v1alpha1/interceptor_types_test.go b/pkg/apis/triggers/v1alpha1/interceptor_types_test.go
index dad66ca75..aa3f09e45 100644
--- a/pkg/apis/triggers/v1alpha1/interceptor_types_test.go
+++ b/pkg/apis/triggers/v1alpha1/interceptor_types_test.go
@@ -1,10 +1,14 @@
package v1alpha1_test
import (
+ "errors"
"testing"
"github.com/google/go-cmp/cmp"
"github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "knative.dev/pkg/apis"
+ "knative.dev/pkg/ptr"
)
func TestParseTriggerID(t *testing.T) {
@@ -26,3 +30,111 @@ func TestParseTriggerID(t *testing.T) {
})
}
}
+
+func TestNSResolveAddress(t *testing.T) {
+ tests := []struct {
+ name string
+ it *v1alpha1.Interceptor
+ want string
+ }{{
+ name: "clientConfig.url is specified",
+ it: &v1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: v1alpha1.InterceptorSpec{
+ ClientConfig: v1alpha1.ClientConfig{
+ URL: &apis.URL{
+ Scheme: "http",
+ Host: "foo.bar.com:8081",
+ Path: "abc",
+ },
+ },
+ },
+ },
+ want: "http://foo.bar.com:8081/abc",
+ }, {
+ name: "clientConfig.service with namespace",
+ it: &v1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: v1alpha1.InterceptorSpec{
+ ClientConfig: v1alpha1.ClientConfig{
+ Service: &v1alpha1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "blah",
+ Port: ptr.Int32(8888),
+ },
+ },
+ },
+ },
+ want: "http://my-svc.default.svc:8888/blah",
+ }, {
+ name: "clientConfig.service without port and scheme so it uses defaultHTTPPort",
+ it: &v1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: v1alpha1.InterceptorSpec{
+ ClientConfig: v1alpha1.ClientConfig{
+ Service: &v1alpha1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "blah",
+ },
+ },
+ },
+ },
+ want: "http://my-svc.default.svc:80/blah",
+ }, {
+ name: "clientConfig with provided caBundle",
+ it: &v1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: v1alpha1.InterceptorSpec{
+ ClientConfig: v1alpha1.ClientConfig{
+ CaBundle: []byte("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQXB5Z0F3SUJBZ0lRSllLcEFVeXc2dStvY1JhV1VtRVRoREFLQmdncWhrak9QUVFEQWpCWE1SUXcKRWdZRFZRUUtFd3RyYm1GMGFYWmxMbVJsZGpFL01EMEdBMVVFQXhNMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdgpjbVV0YVc1MFpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpNQ0FYRFRJeU1EUXhOVEUyCk1ERTFPRm9ZRHpJeE1qSXdNekl5TVRZd01UVTRXakJYTVJRd0VnWURWUVFLRXd0cmJtRjBhWFpsTG1SbGRqRS8KTUQwR0ExVUVBeE0yZEdWcmRHOXVMWFJ5YVdkblpYSnpMV052Y21VdGFXNTBaWEpqWlhCMGIzSnpMblJsYTNSdgpiaTF3YVhCbGJHbHVaWE11YzNaak1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUFHcHp1RjlQCjY5VnFhN0xIY0tmNGpWY2JqblJNWDAxYWRnakh0Zy9kZFdIaVBWdXVJZER1WnZzVTREaVp5Smh2WnpmaHQ0ZmsKT3FJc3dJeVlmbkpLRnFPQ0FVWXdnZ0ZDTUE0R0ExVWREd0VCL3dRRUF3SUNoREFkQmdOVkhTVUVGakFVQmdncgpCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVQRXFjCnEvRFJHd2FDUTdmOFc0dmlucGN5a09zd2dlQUdBMVVkRVFTQjJEQ0IxWUloZEdWcmRHOXVMWFJ5YVdkblpYSnoKTFdOdmNtVXRhVzUwWlhKalpYQjBiM0p6Z2pKMFpXdDBiMjR0ZEhKcFoyZGxjbk10WTI5eVpTMXBiblJsY21ObApjSFJ2Y25NdWRHVnJkRzl1TFhCcGNHVnNhVzVsYzRJMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdmNtVXRhVzUwClpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpna1IwWld0MGIyNHRkSEpwWjJkbGNuTXQKWTI5eVpTMXBiblJsY21ObGNIUnZjbk11ZEdWcmRHOXVMWEJwY0dWc2FXNWxjeTV6ZG1NdVkyeDFjM1JsY2k1cwpiMk5oYkRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQTlhWFBtUFZzRVA3R0xTbzI0SnNmNnRGTmpyQWJRbEl0CjRCYXllcjBnaU5jQ0lRQ09XSm1NTXQxQkE1RXgwa0FYTWRtZjlFdXV4LzlyUUkzMm9VNjVSYm9mNEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="),
+ Service: &v1alpha1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "blah",
+ },
+ },
+ },
+ },
+ want: "https://my-svc.default.svc:8443/blah",
+ }}
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ got, err := tc.it.ResolveAddress()
+ if err != nil {
+ t.Fatalf("ResolveAddress() unpexpected error: %v", err)
+ }
+ if diff := cmp.Diff(tc.want, got.String()); diff != "" {
+ t.Fatalf("ResolveAddress -want/+got: %s", diff)
+ }
+ })
+ }
+
+ t.Run("clientConfig with nil url", func(t *testing.T) {
+ it := &v1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: v1alpha1.InterceptorSpec{
+ ClientConfig: v1alpha1.ClientConfig{
+ URL: nil,
+ Service: nil,
+ },
+ },
+ }
+ _, err := it.ResolveAddress()
+ if !errors.Is(err, v1alpha1.ErrNilURL) {
+ t.Fatalf("ResolveToURL expected error to be %s but got %s", v1alpha1.ErrNilURL, err)
+ }
+ })
+}
diff --git a/pkg/apis/triggers/v1alpha1/interceptor_validation.go b/pkg/apis/triggers/v1alpha1/interceptor_validation.go
new file mode 100644
index 000000000..b16f9b4ae
--- /dev/null
+++ b/pkg/apis/triggers/v1alpha1/interceptor_validation.go
@@ -0,0 +1,46 @@
+/*
+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 v1alpha1
+
+import (
+ "context"
+
+ "knative.dev/pkg/apis"
+)
+
+// Validate Interceptor
+func (it *Interceptor) Validate(ctx context.Context) *apis.FieldError {
+ if apis.IsInDelete(ctx) {
+ return nil
+ }
+ return it.Spec.validate(ctx)
+}
+
+func (s *InterceptorSpec) validate(ctx context.Context) (errs *apis.FieldError) {
+ if s.ClientConfig.URL != nil && s.ClientConfig.Service != nil {
+ errs = errs.Also(apis.ErrMultipleOneOf("spec.clientConfig.url", "spec.clientConfig.service"))
+ }
+ if svc := s.ClientConfig.Service; svc != nil {
+ if svc.Namespace == "" {
+ errs = errs.Also(apis.ErrMissingField("spec.clientConfig.service.namespace"))
+ }
+ if svc.Name == "" {
+ errs = errs.Also(apis.ErrMissingField("spec.clientConfig.service.name"))
+ }
+ }
+ return errs
+}
diff --git a/pkg/apis/triggers/v1alpha1/interceptor_validation_test.go b/pkg/apis/triggers/v1alpha1/interceptor_validation_test.go
new file mode 100644
index 000000000..e9b0ace2f
--- /dev/null
+++ b/pkg/apis/triggers/v1alpha1/interceptor_validation_test.go
@@ -0,0 +1,118 @@
+/*
+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 v1alpha1_test
+
+import (
+ "context"
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+
+ triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "knative.dev/pkg/apis"
+)
+
+func TestInterceptorValidate_OnDelete(t *testing.T) {
+ ci := triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "github",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Namespace: "",
+ Name: "github-svc",
+ },
+ },
+ },
+ }
+
+ err := ci.Validate(apis.WithinDelete(context.Background()))
+ if err != nil {
+ t.Errorf("Interceptor.Validate() on Delete expected no error, but got one, Interceptor: %v, error: %v", ci, err)
+ }
+}
+
+func TestInterceptorValidate(t *testing.T) {
+ tests := []struct {
+ name string
+ namespacedInterceptor triggersv1.Interceptor
+ want *apis.FieldError
+ }{{
+ name: "both URL and Service specified",
+ namespacedInterceptor: triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "github",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ URL: &apis.URL{
+ Scheme: "http",
+ Host: "some.host",
+ },
+ Service: &triggersv1.ServiceReference{
+ Name: "github-svc",
+ Namespace: "default",
+ },
+ },
+ },
+ },
+ want: apis.ErrMultipleOneOf("spec.clientConfig.url", "spec.clientConfig.service"),
+ }, {
+ name: "service missing namespace",
+ namespacedInterceptor: triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "github",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Namespace: "",
+ Name: "github-svc",
+ },
+ },
+ },
+ },
+ want: apis.ErrMissingField("spec.clientConfig.service.namespace"),
+ }, {
+ name: "service missing name",
+ namespacedInterceptor: triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "github",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Namespace: "default",
+ Name: "",
+ },
+ },
+ },
+ },
+ want: apis.ErrMissingField("spec.clientConfig.service.name"),
+ }}
+
+ for _, tc := range tests {
+ t.Run(tc.name, func(t *testing.T) {
+ got := tc.namespacedInterceptor.Validate(context.Background())
+ if diff := cmp.Diff(tc.want.Error(), got.Error()); diff != "" {
+ t.Fatalf("Interceptor.Validate() error: %s", diff)
+ }
+ })
+ }
+}
diff --git a/pkg/apis/triggers/v1alpha1/register.go b/pkg/apis/triggers/v1alpha1/register.go
index e9c006a70..ea60ff51a 100644
--- a/pkg/apis/triggers/v1alpha1/register.go
+++ b/pkg/apis/triggers/v1alpha1/register.go
@@ -52,6 +52,8 @@ func addKnownTypes(scheme *runtime.Scheme) error {
&ClusterTriggerBindingList{},
&EventListener{},
&EventListenerList{},
+ &Interceptor{},
+ &InterceptorList{},
&TriggerBinding{},
&TriggerBindingList{},
&TriggerTemplate{},
diff --git a/pkg/apis/triggers/v1alpha1/trigger_types.go b/pkg/apis/triggers/v1alpha1/trigger_types.go
index 135133f74..ecf2ff921 100644
--- a/pkg/apis/triggers/v1alpha1/trigger_types.go
+++ b/pkg/apis/triggers/v1alpha1/trigger_types.go
@@ -118,8 +118,6 @@ type InterceptorRef struct {
// Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names
Name string `json:"name,omitempty"`
// InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
- // Currently only InterceptorKind is ClusterInterceptor, so the only valid value
- // is the default one
// +optional
Kind InterceptorKind `json:"kind,omitempty"`
// API version of the referent
@@ -133,6 +131,8 @@ type InterceptorKind string
const (
// ClusterInterceptorKind indicates that Interceptor type has a cluster scope.
ClusterInterceptorKind InterceptorKind = "ClusterInterceptor"
+ // NamespacedInterceptorKind indicated that interceptor has a namespaced scope
+ NamespacedInterceptorKind InterceptorKind = "NamespacedInterceptor"
)
func (ti *TriggerInterceptor) defaultInterceptorKind() {
diff --git a/pkg/apis/triggers/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/triggers/v1alpha1/zz_generated.deepcopy.go
index 5719284b8..839866033 100644
--- a/pkg/apis/triggers/v1alpha1/zz_generated.deepcopy.go
+++ b/pkg/apis/triggers/v1alpha1/zz_generated.deepcopy.go
@@ -518,6 +518,67 @@ func (in *GitLabInterceptor) DeepCopy() *GitLabInterceptor {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *Interceptor) DeepCopyInto(out *Interceptor) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
+ in.Spec.DeepCopyInto(&out.Spec)
+ in.Status.DeepCopyInto(&out.Status)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Interceptor.
+func (in *Interceptor) DeepCopy() *Interceptor {
+ if in == nil {
+ return nil
+ }
+ out := new(Interceptor)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *Interceptor) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *InterceptorList) DeepCopyInto(out *InterceptorList) {
+ *out = *in
+ out.TypeMeta = in.TypeMeta
+ in.ListMeta.DeepCopyInto(&out.ListMeta)
+ if in.Items != nil {
+ in, out := &in.Items, &out.Items
+ *out = make([]Interceptor, len(*in))
+ for i := range *in {
+ (*in)[i].DeepCopyInto(&(*out)[i])
+ }
+ }
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterceptorList.
+func (in *InterceptorList) DeepCopy() *InterceptorList {
+ if in == nil {
+ return nil
+ }
+ out := new(InterceptorList)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
+func (in *InterceptorList) DeepCopyObject() runtime.Object {
+ if c := in.DeepCopy(); c != nil {
+ return c
+ }
+ return nil
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *InterceptorParams) DeepCopyInto(out *InterceptorParams) {
*out = *in
@@ -551,6 +612,41 @@ func (in *InterceptorRef) DeepCopy() *InterceptorRef {
return out
}
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *InterceptorSpec) DeepCopyInto(out *InterceptorSpec) {
+ *out = *in
+ in.ClientConfig.DeepCopyInto(&out.ClientConfig)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterceptorSpec.
+func (in *InterceptorSpec) DeepCopy() *InterceptorSpec {
+ if in == nil {
+ return nil
+ }
+ out := new(InterceptorSpec)
+ in.DeepCopyInto(out)
+ return out
+}
+
+// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
+func (in *InterceptorStatus) DeepCopyInto(out *InterceptorStatus) {
+ *out = *in
+ in.Status.DeepCopyInto(&out.Status)
+ in.AddressStatus.DeepCopyInto(&out.AddressStatus)
+ return
+}
+
+// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new InterceptorStatus.
+func (in *InterceptorStatus) DeepCopy() *InterceptorStatus {
+ if in == nil {
+ return nil
+ }
+ out := new(InterceptorStatus)
+ in.DeepCopyInto(out)
+ return out
+}
+
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *KubernetesResource) DeepCopyInto(out *KubernetesResource) {
*out = *in
diff --git a/pkg/apis/triggers/v1beta1/openapi_generated.go b/pkg/apis/triggers/v1beta1/openapi_generated.go
index 313e8c1bf..693fa5669 100644
--- a/pkg/apis/triggers/v1beta1/openapi_generated.go
+++ b/pkg/apis/triggers/v1beta1/openapi_generated.go
@@ -827,7 +827,7 @@ func schema_pkg_apis_triggers_v1beta1_InterceptorRef(ref common.ReferenceCallbac
},
"kind": {
SchemaProps: spec.SchemaProps{
- Description: "InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped. Currently only InterceptorKind is ClusterInterceptor, so the only valid value is the default one",
+ Description: "InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.",
Type: []string{"string"},
Format: "",
},
diff --git a/pkg/apis/triggers/v1beta1/trigger_types.go b/pkg/apis/triggers/v1beta1/trigger_types.go
index fd0744524..2eb83d6af 100644
--- a/pkg/apis/triggers/v1beta1/trigger_types.go
+++ b/pkg/apis/triggers/v1beta1/trigger_types.go
@@ -109,8 +109,6 @@ type InterceptorRef struct {
// Name of the referent; More info: http://kubernetes.io/docs/user-guide/identifiers#names
Name string `json:"name,omitempty"`
// InterceptorKind indicates the kind of the Interceptor, namespaced or cluster scoped.
- // Currently only InterceptorKind is ClusterInterceptor, so the only valid value
- // is the default one
// +optional
Kind InterceptorKind `json:"kind,omitempty"`
// API version of the referent
@@ -124,6 +122,8 @@ type InterceptorKind string
const (
// ClusterInterceptorKind indicates that Interceptor type has a cluster scope.
ClusterInterceptorKind InterceptorKind = "ClusterInterceptor"
+ // NamespacedInterceptorKind indicates that Interceptor type has a namespace scope.
+ NamespacedInterceptorKind InterceptorKind = "NamespacedInterceptor"
)
func (ti *TriggerInterceptor) defaultInterceptorKind() {
diff --git a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_interceptor.go b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_interceptor.go
new file mode 100644
index 000000000..4347eba98
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_interceptor.go
@@ -0,0 +1,142 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ "context"
+
+ v1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ schema "k8s.io/apimachinery/pkg/runtime/schema"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ testing "k8s.io/client-go/testing"
+)
+
+// FakeInterceptors implements InterceptorInterface
+type FakeInterceptors struct {
+ Fake *FakeTriggersV1alpha1
+ ns string
+}
+
+var interceptorsResource = schema.GroupVersionResource{Group: "triggers.tekton.dev", Version: "v1alpha1", Resource: "interceptors"}
+
+var interceptorsKind = schema.GroupVersionKind{Group: "triggers.tekton.dev", Version: "v1alpha1", Kind: "Interceptor"}
+
+// Get takes name of the interceptor, and returns the corresponding interceptor object, and an error if there is any.
+func (c *FakeInterceptors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Interceptor, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewGetAction(interceptorsResource, c.ns, name), &v1alpha1.Interceptor{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Interceptor), err
+}
+
+// List takes label and field selectors, and returns the list of Interceptors that match those selectors.
+func (c *FakeInterceptors) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.InterceptorList, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewListAction(interceptorsResource, interceptorsKind, c.ns, opts), &v1alpha1.InterceptorList{})
+
+ if obj == nil {
+ return nil, err
+ }
+
+ label, _, _ := testing.ExtractFromListOptions(opts)
+ if label == nil {
+ label = labels.Everything()
+ }
+ list := &v1alpha1.InterceptorList{ListMeta: obj.(*v1alpha1.InterceptorList).ListMeta}
+ for _, item := range obj.(*v1alpha1.InterceptorList).Items {
+ if label.Matches(labels.Set(item.Labels)) {
+ list.Items = append(list.Items, item)
+ }
+ }
+ return list, err
+}
+
+// Watch returns a watch.Interface that watches the requested interceptors.
+func (c *FakeInterceptors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+ return c.Fake.
+ InvokesWatch(testing.NewWatchAction(interceptorsResource, c.ns, opts))
+
+}
+
+// Create takes the representation of a interceptor and creates it. Returns the server's representation of the interceptor, and an error, if there is any.
+func (c *FakeInterceptors) Create(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.CreateOptions) (result *v1alpha1.Interceptor, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewCreateAction(interceptorsResource, c.ns, interceptor), &v1alpha1.Interceptor{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Interceptor), err
+}
+
+// Update takes the representation of a interceptor and updates it. Returns the server's representation of the interceptor, and an error, if there is any.
+func (c *FakeInterceptors) Update(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (result *v1alpha1.Interceptor, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateAction(interceptorsResource, c.ns, interceptor), &v1alpha1.Interceptor{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Interceptor), err
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *FakeInterceptors) UpdateStatus(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (*v1alpha1.Interceptor, error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewUpdateSubresourceAction(interceptorsResource, "status", c.ns, interceptor), &v1alpha1.Interceptor{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Interceptor), err
+}
+
+// Delete takes name of the interceptor and deletes it. Returns an error if one occurs.
+func (c *FakeInterceptors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+ _, err := c.Fake.
+ Invokes(testing.NewDeleteActionWithOptions(interceptorsResource, c.ns, name, opts), &v1alpha1.Interceptor{})
+
+ return err
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *FakeInterceptors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+ action := testing.NewDeleteCollectionAction(interceptorsResource, c.ns, listOpts)
+
+ _, err := c.Fake.Invokes(action, &v1alpha1.InterceptorList{})
+ return err
+}
+
+// Patch applies the patch and returns the patched interceptor.
+func (c *FakeInterceptors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Interceptor, err error) {
+ obj, err := c.Fake.
+ Invokes(testing.NewPatchSubresourceAction(interceptorsResource, c.ns, name, pt, data, subresources...), &v1alpha1.Interceptor{})
+
+ if obj == nil {
+ return nil, err
+ }
+ return obj.(*v1alpha1.Interceptor), err
+}
diff --git a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_triggers_client.go b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_triggers_client.go
index f766031ca..5419d6b96 100644
--- a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_triggers_client.go
+++ b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/fake/fake_triggers_client.go
@@ -40,6 +40,10 @@ func (c *FakeTriggersV1alpha1) EventListeners(namespace string) v1alpha1.EventLi
return &FakeEventListeners{c, namespace}
}
+func (c *FakeTriggersV1alpha1) Interceptors(namespace string) v1alpha1.InterceptorInterface {
+ return &FakeInterceptors{c, namespace}
+}
+
func (c *FakeTriggersV1alpha1) Triggers(namespace string) v1alpha1.TriggerInterface {
return &FakeTriggers{c, namespace}
}
diff --git a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/generated_expansion.go b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/generated_expansion.go
index c7ab02c6f..8a615d1ca 100644
--- a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/generated_expansion.go
+++ b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/generated_expansion.go
@@ -24,6 +24,8 @@ type ClusterTriggerBindingExpansion interface{}
type EventListenerExpansion interface{}
+type InterceptorExpansion interface{}
+
type TriggerExpansion interface{}
type TriggerBindingExpansion interface{}
diff --git a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/interceptor.go b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/interceptor.go
new file mode 100644
index 000000000..7231dba9a
--- /dev/null
+++ b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/interceptor.go
@@ -0,0 +1,195 @@
+/*
+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.
+*/
+
+// Code generated by client-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ "context"
+ "time"
+
+ v1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ scheme "github.com/tektoncd/triggers/pkg/client/clientset/versioned/scheme"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ rest "k8s.io/client-go/rest"
+)
+
+// InterceptorsGetter has a method to return a InterceptorInterface.
+// A group's client should implement this interface.
+type InterceptorsGetter interface {
+ Interceptors(namespace string) InterceptorInterface
+}
+
+// InterceptorInterface has methods to work with Interceptor resources.
+type InterceptorInterface interface {
+ Create(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.CreateOptions) (*v1alpha1.Interceptor, error)
+ Update(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (*v1alpha1.Interceptor, error)
+ UpdateStatus(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (*v1alpha1.Interceptor, error)
+ Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
+ DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
+ Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.Interceptor, error)
+ List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.InterceptorList, error)
+ Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
+ Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Interceptor, err error)
+ InterceptorExpansion
+}
+
+// interceptors implements InterceptorInterface
+type interceptors struct {
+ client rest.Interface
+ ns string
+}
+
+// newInterceptors returns a Interceptors
+func newInterceptors(c *TriggersV1alpha1Client, namespace string) *interceptors {
+ return &interceptors{
+ client: c.RESTClient(),
+ ns: namespace,
+ }
+}
+
+// Get takes name of the interceptor, and returns the corresponding interceptor object, and an error if there is any.
+func (c *interceptors) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.Interceptor, err error) {
+ result = &v1alpha1.Interceptor{}
+ err = c.client.Get().
+ Namespace(c.ns).
+ Resource("interceptors").
+ Name(name).
+ VersionedParams(&options, scheme.ParameterCodec).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// List takes label and field selectors, and returns the list of Interceptors that match those selectors.
+func (c *interceptors) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.InterceptorList, err error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ result = &v1alpha1.InterceptorList{}
+ err = c.client.Get().
+ Namespace(c.ns).
+ Resource("interceptors").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Watch returns a watch.Interface that watches the requested interceptors.
+func (c *interceptors) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+ var timeout time.Duration
+ if opts.TimeoutSeconds != nil {
+ timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
+ }
+ opts.Watch = true
+ return c.client.Get().
+ Namespace(c.ns).
+ Resource("interceptors").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Watch(ctx)
+}
+
+// Create takes the representation of a interceptor and creates it. Returns the server's representation of the interceptor, and an error, if there is any.
+func (c *interceptors) Create(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.CreateOptions) (result *v1alpha1.Interceptor, err error) {
+ result = &v1alpha1.Interceptor{}
+ err = c.client.Post().
+ Namespace(c.ns).
+ Resource("interceptors").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(interceptor).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Update takes the representation of a interceptor and updates it. Returns the server's representation of the interceptor, and an error, if there is any.
+func (c *interceptors) Update(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (result *v1alpha1.Interceptor, err error) {
+ result = &v1alpha1.Interceptor{}
+ err = c.client.Put().
+ Namespace(c.ns).
+ Resource("interceptors").
+ Name(interceptor.Name).
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(interceptor).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// UpdateStatus was generated because the type contains a Status member.
+// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
+func (c *interceptors) UpdateStatus(ctx context.Context, interceptor *v1alpha1.Interceptor, opts v1.UpdateOptions) (result *v1alpha1.Interceptor, err error) {
+ result = &v1alpha1.Interceptor{}
+ err = c.client.Put().
+ Namespace(c.ns).
+ Resource("interceptors").
+ Name(interceptor.Name).
+ SubResource("status").
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(interceptor).
+ Do(ctx).
+ Into(result)
+ return
+}
+
+// Delete takes name of the interceptor and deletes it. Returns an error if one occurs.
+func (c *interceptors) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+ return c.client.Delete().
+ Namespace(c.ns).
+ Resource("interceptors").
+ Name(name).
+ Body(&opts).
+ Do(ctx).
+ Error()
+}
+
+// DeleteCollection deletes a collection of objects.
+func (c *interceptors) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+ var timeout time.Duration
+ if listOpts.TimeoutSeconds != nil {
+ timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second
+ }
+ return c.client.Delete().
+ Namespace(c.ns).
+ Resource("interceptors").
+ VersionedParams(&listOpts, scheme.ParameterCodec).
+ Timeout(timeout).
+ Body(&opts).
+ Do(ctx).
+ Error()
+}
+
+// Patch applies the patch and returns the patched interceptor.
+func (c *interceptors) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Interceptor, err error) {
+ result = &v1alpha1.Interceptor{}
+ err = c.client.Patch(pt).
+ Namespace(c.ns).
+ Resource("interceptors").
+ Name(name).
+ SubResource(subresources...).
+ VersionedParams(&opts, scheme.ParameterCodec).
+ Body(data).
+ Do(ctx).
+ Into(result)
+ return
+}
diff --git a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/triggers_client.go b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/triggers_client.go
index 7f8fd64c4..28f9ba423 100644
--- a/pkg/client/clientset/versioned/typed/triggers/v1alpha1/triggers_client.go
+++ b/pkg/client/clientset/versioned/typed/triggers/v1alpha1/triggers_client.go
@@ -31,6 +31,7 @@ type TriggersV1alpha1Interface interface {
ClusterInterceptorsGetter
ClusterTriggerBindingsGetter
EventListenersGetter
+ InterceptorsGetter
TriggersGetter
TriggerBindingsGetter
TriggerTemplatesGetter
@@ -53,6 +54,10 @@ func (c *TriggersV1alpha1Client) EventListeners(namespace string) EventListenerI
return newEventListeners(c, namespace)
}
+func (c *TriggersV1alpha1Client) Interceptors(namespace string) InterceptorInterface {
+ return newInterceptors(c, namespace)
+}
+
func (c *TriggersV1alpha1Client) Triggers(namespace string) TriggerInterface {
return newTriggers(c, namespace)
}
diff --git a/pkg/client/dynamic/clientset/tekton/tekton.go b/pkg/client/dynamic/clientset/tekton/tekton.go
index 0b1d501a8..8d88d6fe8 100644
--- a/pkg/client/dynamic/clientset/tekton/tekton.go
+++ b/pkg/client/dynamic/clientset/tekton/tekton.go
@@ -1,3 +1,19 @@
+/*
+Copyright 2021 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 tekton
import (
@@ -14,7 +30,7 @@ var (
"v1beta1": {"pipelineruns", "taskruns", "pipelines", "clustertasks", "tasks"},
}
allowedTriggersTypes = map[string][]string{
- "v1alpha1": {"clusterinterceptors"},
+ "v1alpha1": {"clusterinterceptors", "interceptors"},
"v1beta1": {"clustertriggerbindings", "eventlisteners", "triggerbindings", "triggers", "triggertemplates"},
}
)
diff --git a/pkg/client/informers/externalversions/generic.go b/pkg/client/informers/externalversions/generic.go
index 58ad7f48a..d13e72184 100644
--- a/pkg/client/informers/externalversions/generic.go
+++ b/pkg/client/informers/externalversions/generic.go
@@ -60,6 +60,8 @@ func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource
return &genericInformer{resource: resource.GroupResource(), informer: f.Triggers().V1alpha1().ClusterTriggerBindings().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("eventlisteners"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Triggers().V1alpha1().EventListeners().Informer()}, nil
+ case v1alpha1.SchemeGroupVersion.WithResource("interceptors"):
+ return &genericInformer{resource: resource.GroupResource(), informer: f.Triggers().V1alpha1().Interceptors().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("triggers"):
return &genericInformer{resource: resource.GroupResource(), informer: f.Triggers().V1alpha1().Triggers().Informer()}, nil
case v1alpha1.SchemeGroupVersion.WithResource("triggerbindings"):
diff --git a/pkg/client/informers/externalversions/triggers/v1alpha1/interceptor.go b/pkg/client/informers/externalversions/triggers/v1alpha1/interceptor.go
new file mode 100644
index 000000000..05ff98ac6
--- /dev/null
+++ b/pkg/client/informers/externalversions/triggers/v1alpha1/interceptor.go
@@ -0,0 +1,90 @@
+/*
+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.
+*/
+
+// Code generated by informer-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ "context"
+ time "time"
+
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ versioned "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
+ internalinterfaces "github.com/tektoncd/triggers/pkg/client/informers/externalversions/internalinterfaces"
+ v1alpha1 "github.com/tektoncd/triggers/pkg/client/listers/triggers/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ runtime "k8s.io/apimachinery/pkg/runtime"
+ watch "k8s.io/apimachinery/pkg/watch"
+ cache "k8s.io/client-go/tools/cache"
+)
+
+// InterceptorInformer provides access to a shared informer and lister for
+// Interceptors.
+type InterceptorInformer interface {
+ Informer() cache.SharedIndexInformer
+ Lister() v1alpha1.InterceptorLister
+}
+
+type interceptorInformer struct {
+ factory internalinterfaces.SharedInformerFactory
+ tweakListOptions internalinterfaces.TweakListOptionsFunc
+ namespace string
+}
+
+// NewInterceptorInformer constructs a new informer for Interceptor type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewInterceptorInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
+ return NewFilteredInterceptorInformer(client, namespace, resyncPeriod, indexers, nil)
+}
+
+// NewFilteredInterceptorInformer constructs a new informer for Interceptor type.
+// Always prefer using an informer factory to get a shared informer instead of getting an independent
+// one. This reduces memory footprint and number of connections to the server.
+func NewFilteredInterceptorInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(
+ &cache.ListWatch{
+ ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.TriggersV1alpha1().Interceptors(namespace).List(context.TODO(), options)
+ },
+ WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
+ if tweakListOptions != nil {
+ tweakListOptions(&options)
+ }
+ return client.TriggersV1alpha1().Interceptors(namespace).Watch(context.TODO(), options)
+ },
+ },
+ &triggersv1alpha1.Interceptor{},
+ resyncPeriod,
+ indexers,
+ )
+}
+
+func (f *interceptorInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
+ return NewFilteredInterceptorInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
+}
+
+func (f *interceptorInformer) Informer() cache.SharedIndexInformer {
+ return f.factory.InformerFor(&triggersv1alpha1.Interceptor{}, f.defaultInformer)
+}
+
+func (f *interceptorInformer) Lister() v1alpha1.InterceptorLister {
+ return v1alpha1.NewInterceptorLister(f.Informer().GetIndexer())
+}
diff --git a/pkg/client/informers/externalversions/triggers/v1alpha1/interface.go b/pkg/client/informers/externalversions/triggers/v1alpha1/interface.go
index d993befd9..d1904cc2a 100644
--- a/pkg/client/informers/externalversions/triggers/v1alpha1/interface.go
+++ b/pkg/client/informers/externalversions/triggers/v1alpha1/interface.go
@@ -30,6 +30,8 @@ type Interface interface {
ClusterTriggerBindings() ClusterTriggerBindingInformer
// EventListeners returns a EventListenerInformer.
EventListeners() EventListenerInformer
+ // Interceptors returns a InterceptorInformer.
+ Interceptors() InterceptorInformer
// Triggers returns a TriggerInformer.
Triggers() TriggerInformer
// TriggerBindings returns a TriggerBindingInformer.
@@ -64,6 +66,11 @@ func (v *version) EventListeners() EventListenerInformer {
return &eventListenerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
}
+// Interceptors returns a InterceptorInformer.
+func (v *version) Interceptors() InterceptorInformer {
+ return &interceptorInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
+}
+
// Triggers returns a TriggerInformer.
func (v *version) Triggers() TriggerInformer {
return &triggerInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
diff --git a/pkg/client/injection/client/client.go b/pkg/client/injection/client/client.go
index abfe618bf..4db863625 100644
--- a/pkg/client/injection/client/client.go
+++ b/pkg/client/injection/client/client.go
@@ -498,6 +498,137 @@ func (w *wrapTriggersV1alpha1EventListenerImpl) Watch(ctx context.Context, opts
return nil, errors.New("NYI: Watch")
}
+func (w *wrapTriggersV1alpha1) Interceptors(namespace string) typedtriggersv1alpha1.InterceptorInterface {
+ return &wrapTriggersV1alpha1InterceptorImpl{
+ dyn: w.dyn.Resource(schema.GroupVersionResource{
+ Group: "triggers.tekton.dev",
+ Version: "v1alpha1",
+ Resource: "interceptors",
+ }),
+
+ namespace: namespace,
+ }
+}
+
+type wrapTriggersV1alpha1InterceptorImpl struct {
+ dyn dynamic.NamespaceableResourceInterface
+
+ namespace string
+}
+
+var _ typedtriggersv1alpha1.InterceptorInterface = (*wrapTriggersV1alpha1InterceptorImpl)(nil)
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Create(ctx context.Context, in *v1alpha1.Interceptor, opts v1.CreateOptions) (*v1alpha1.Interceptor, error) {
+ in.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: "triggers.tekton.dev",
+ Version: "v1alpha1",
+ Kind: "Interceptor",
+ })
+ uo := &unstructured.Unstructured{}
+ if err := convert(in, uo); err != nil {
+ return nil, err
+ }
+ uo, err := w.dyn.Namespace(w.namespace).Create(ctx, uo, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.Interceptor{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error {
+ return w.dyn.Namespace(w.namespace).Delete(ctx, name, opts)
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error {
+ return w.dyn.Namespace(w.namespace).DeleteCollection(ctx, opts, listOpts)
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.Interceptor, error) {
+ uo, err := w.dyn.Namespace(w.namespace).Get(ctx, name, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.Interceptor{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.InterceptorList, error) {
+ uo, err := w.dyn.Namespace(w.namespace).List(ctx, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.InterceptorList{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.Interceptor, err error) {
+ uo, err := w.dyn.Namespace(w.namespace).Patch(ctx, name, pt, data, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.Interceptor{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Update(ctx context.Context, in *v1alpha1.Interceptor, opts v1.UpdateOptions) (*v1alpha1.Interceptor, error) {
+ in.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: "triggers.tekton.dev",
+ Version: "v1alpha1",
+ Kind: "Interceptor",
+ })
+ uo := &unstructured.Unstructured{}
+ if err := convert(in, uo); err != nil {
+ return nil, err
+ }
+ uo, err := w.dyn.Namespace(w.namespace).Update(ctx, uo, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.Interceptor{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) UpdateStatus(ctx context.Context, in *v1alpha1.Interceptor, opts v1.UpdateOptions) (*v1alpha1.Interceptor, error) {
+ in.SetGroupVersionKind(schema.GroupVersionKind{
+ Group: "triggers.tekton.dev",
+ Version: "v1alpha1",
+ Kind: "Interceptor",
+ })
+ uo := &unstructured.Unstructured{}
+ if err := convert(in, uo); err != nil {
+ return nil, err
+ }
+ uo, err := w.dyn.Namespace(w.namespace).UpdateStatus(ctx, uo, opts)
+ if err != nil {
+ return nil, err
+ }
+ out := &v1alpha1.Interceptor{}
+ if err := convert(uo, out); err != nil {
+ return nil, err
+ }
+ return out, nil
+}
+
+func (w *wrapTriggersV1alpha1InterceptorImpl) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) {
+ return nil, errors.New("NYI: Watch")
+}
+
func (w *wrapTriggersV1alpha1) Triggers(namespace string) typedtriggersv1alpha1.TriggerInterface {
return &wrapTriggersV1alpha1TriggerImpl{
dyn: w.dyn.Resource(schema.GroupVersionResource{
diff --git a/pkg/client/injection/informers/triggers/v1alpha1/interceptor/fake/fake.go b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/fake/fake.go
new file mode 100644
index 000000000..558119a53
--- /dev/null
+++ b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/fake/fake.go
@@ -0,0 +1,40 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ context "context"
+
+ fake "github.com/tektoncd/triggers/pkg/client/injection/informers/factory/fake"
+ interceptor "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor"
+ controller "knative.dev/pkg/controller"
+ injection "knative.dev/pkg/injection"
+)
+
+var Get = interceptor.Get
+
+func init() {
+ injection.Fake.RegisterInformer(withInformer)
+}
+
+func withInformer(ctx context.Context) (context.Context, controller.Informer) {
+ f := fake.Get(ctx)
+ inf := f.Triggers().V1alpha1().Interceptors()
+ return context.WithValue(ctx, interceptor.Key{}, inf), inf.Informer()
+}
diff --git a/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/fake/fake.go b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/fake/fake.go
new file mode 100644
index 000000000..822b2d869
--- /dev/null
+++ b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/fake/fake.go
@@ -0,0 +1,52 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package fake
+
+import (
+ context "context"
+
+ factoryfiltered "github.com/tektoncd/triggers/pkg/client/injection/informers/factory/filtered"
+ filtered "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered"
+ controller "knative.dev/pkg/controller"
+ injection "knative.dev/pkg/injection"
+ logging "knative.dev/pkg/logging"
+)
+
+var Get = filtered.Get
+
+func init() {
+ injection.Fake.RegisterFilteredInformers(withInformer)
+}
+
+func withInformer(ctx context.Context) (context.Context, []controller.Informer) {
+ untyped := ctx.Value(factoryfiltered.LabelKey{})
+ if untyped == nil {
+ logging.FromContext(ctx).Panic(
+ "Unable to fetch labelkey from context.")
+ }
+ labelSelectors := untyped.([]string)
+ infs := []controller.Informer{}
+ for _, selector := range labelSelectors {
+ f := factoryfiltered.Get(ctx, selector)
+ inf := f.Triggers().V1alpha1().Interceptors()
+ ctx = context.WithValue(ctx, filtered.Key{Selector: selector}, inf)
+ infs = append(infs, inf.Informer())
+ }
+ return ctx, infs
+}
diff --git a/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/interceptor.go b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/interceptor.go
new file mode 100644
index 000000000..177eb7fb7
--- /dev/null
+++ b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/filtered/interceptor.go
@@ -0,0 +1,136 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package filtered
+
+import (
+ context "context"
+
+ apistriggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ versioned "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
+ v1alpha1 "github.com/tektoncd/triggers/pkg/client/informers/externalversions/triggers/v1alpha1"
+ client "github.com/tektoncd/triggers/pkg/client/injection/client"
+ filtered "github.com/tektoncd/triggers/pkg/client/injection/informers/factory/filtered"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/client/listers/triggers/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ cache "k8s.io/client-go/tools/cache"
+ controller "knative.dev/pkg/controller"
+ injection "knative.dev/pkg/injection"
+ logging "knative.dev/pkg/logging"
+)
+
+func init() {
+ injection.Default.RegisterFilteredInformers(withInformer)
+ injection.Dynamic.RegisterDynamicInformer(withDynamicInformer)
+}
+
+// Key is used for associating the Informer inside the context.Context.
+type Key struct {
+ Selector string
+}
+
+func withInformer(ctx context.Context) (context.Context, []controller.Informer) {
+ untyped := ctx.Value(filtered.LabelKey{})
+ if untyped == nil {
+ logging.FromContext(ctx).Panic(
+ "Unable to fetch labelkey from context.")
+ }
+ labelSelectors := untyped.([]string)
+ infs := []controller.Informer{}
+ for _, selector := range labelSelectors {
+ f := filtered.Get(ctx, selector)
+ inf := f.Triggers().V1alpha1().Interceptors()
+ ctx = context.WithValue(ctx, Key{Selector: selector}, inf)
+ infs = append(infs, inf.Informer())
+ }
+ return ctx, infs
+}
+
+func withDynamicInformer(ctx context.Context) context.Context {
+ untyped := ctx.Value(filtered.LabelKey{})
+ if untyped == nil {
+ logging.FromContext(ctx).Panic(
+ "Unable to fetch labelkey from context.")
+ }
+ labelSelectors := untyped.([]string)
+ for _, selector := range labelSelectors {
+ inf := &wrapper{client: client.Get(ctx), selector: selector}
+ ctx = context.WithValue(ctx, Key{Selector: selector}, inf)
+ }
+ return ctx
+}
+
+// Get extracts the typed informer from the context.
+func Get(ctx context.Context, selector string) v1alpha1.InterceptorInformer {
+ untyped := ctx.Value(Key{Selector: selector})
+ if untyped == nil {
+ logging.FromContext(ctx).Panicf(
+ "Unable to fetch github.com/tektoncd/triggers/pkg/client/informers/externalversions/triggers/v1alpha1.InterceptorInformer with selector %s from context.", selector)
+ }
+ return untyped.(v1alpha1.InterceptorInformer)
+}
+
+type wrapper struct {
+ client versioned.Interface
+
+ namespace string
+
+ selector string
+}
+
+var _ v1alpha1.InterceptorInformer = (*wrapper)(nil)
+var _ triggersv1alpha1.InterceptorLister = (*wrapper)(nil)
+
+func (w *wrapper) Informer() cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(nil, &apistriggersv1alpha1.Interceptor{}, 0, nil)
+}
+
+func (w *wrapper) Lister() triggersv1alpha1.InterceptorLister {
+ return w
+}
+
+func (w *wrapper) Interceptors(namespace string) triggersv1alpha1.InterceptorNamespaceLister {
+ return &wrapper{client: w.client, namespace: namespace, selector: w.selector}
+}
+
+func (w *wrapper) List(selector labels.Selector) (ret []*apistriggersv1alpha1.Interceptor, err error) {
+ reqs, err := labels.ParseToRequirements(w.selector)
+ if err != nil {
+ return nil, err
+ }
+ selector = selector.Add(reqs...)
+ lo, err := w.client.TriggersV1alpha1().Interceptors(w.namespace).List(context.TODO(), v1.ListOptions{
+ LabelSelector: selector.String(),
+ // TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria.
+ })
+ if err != nil {
+ return nil, err
+ }
+ for idx := range lo.Items {
+ ret = append(ret, &lo.Items[idx])
+ }
+ return ret, nil
+}
+
+func (w *wrapper) Get(name string) (*apistriggersv1alpha1.Interceptor, error) {
+ // TODO(mattmoor): Check that the fetched object matches the selector.
+ return w.client.TriggersV1alpha1().Interceptors(w.namespace).Get(context.TODO(), name, v1.GetOptions{
+ // TODO(mattmoor): Incorporate resourceVersion bounds based on staleness criteria.
+ })
+}
diff --git a/pkg/client/injection/informers/triggers/v1alpha1/interceptor/interceptor.go b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/interceptor.go
new file mode 100644
index 000000000..eabc4d565
--- /dev/null
+++ b/pkg/client/injection/informers/triggers/v1alpha1/interceptor/interceptor.go
@@ -0,0 +1,116 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package interceptor
+
+import (
+ context "context"
+
+ apistriggersv1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ versioned "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
+ v1alpha1 "github.com/tektoncd/triggers/pkg/client/informers/externalversions/triggers/v1alpha1"
+ client "github.com/tektoncd/triggers/pkg/client/injection/client"
+ factory "github.com/tektoncd/triggers/pkg/client/injection/informers/factory"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/client/listers/triggers/v1alpha1"
+ v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ cache "k8s.io/client-go/tools/cache"
+ controller "knative.dev/pkg/controller"
+ injection "knative.dev/pkg/injection"
+ logging "knative.dev/pkg/logging"
+)
+
+func init() {
+ injection.Default.RegisterInformer(withInformer)
+ injection.Dynamic.RegisterDynamicInformer(withDynamicInformer)
+}
+
+// Key is used for associating the Informer inside the context.Context.
+type Key struct{}
+
+func withInformer(ctx context.Context) (context.Context, controller.Informer) {
+ f := factory.Get(ctx)
+ inf := f.Triggers().V1alpha1().Interceptors()
+ return context.WithValue(ctx, Key{}, inf), inf.Informer()
+}
+
+func withDynamicInformer(ctx context.Context) context.Context {
+ inf := &wrapper{client: client.Get(ctx), resourceVersion: injection.GetResourceVersion(ctx)}
+ return context.WithValue(ctx, Key{}, inf)
+}
+
+// Get extracts the typed informer from the context.
+func Get(ctx context.Context) v1alpha1.InterceptorInformer {
+ untyped := ctx.Value(Key{})
+ if untyped == nil {
+ logging.FromContext(ctx).Panic(
+ "Unable to fetch github.com/tektoncd/triggers/pkg/client/informers/externalversions/triggers/v1alpha1.InterceptorInformer from context.")
+ }
+ return untyped.(v1alpha1.InterceptorInformer)
+}
+
+type wrapper struct {
+ client versioned.Interface
+
+ namespace string
+
+ resourceVersion string
+}
+
+var _ v1alpha1.InterceptorInformer = (*wrapper)(nil)
+var _ triggersv1alpha1.InterceptorLister = (*wrapper)(nil)
+
+func (w *wrapper) Informer() cache.SharedIndexInformer {
+ return cache.NewSharedIndexInformer(nil, &apistriggersv1alpha1.Interceptor{}, 0, nil)
+}
+
+func (w *wrapper) Lister() triggersv1alpha1.InterceptorLister {
+ return w
+}
+
+func (w *wrapper) Interceptors(namespace string) triggersv1alpha1.InterceptorNamespaceLister {
+ return &wrapper{client: w.client, namespace: namespace, resourceVersion: w.resourceVersion}
+}
+
+// SetResourceVersion allows consumers to adjust the minimum resourceVersion
+// used by the underlying client. It is not accessible via the standard
+// lister interface, but can be accessed through a user-defined interface and
+// an implementation check e.g. rvs, ok := foo.(ResourceVersionSetter)
+func (w *wrapper) SetResourceVersion(resourceVersion string) {
+ w.resourceVersion = resourceVersion
+}
+
+func (w *wrapper) List(selector labels.Selector) (ret []*apistriggersv1alpha1.Interceptor, err error) {
+ lo, err := w.client.TriggersV1alpha1().Interceptors(w.namespace).List(context.TODO(), v1.ListOptions{
+ LabelSelector: selector.String(),
+ ResourceVersion: w.resourceVersion,
+ })
+ if err != nil {
+ return nil, err
+ }
+ for idx := range lo.Items {
+ ret = append(ret, &lo.Items[idx])
+ }
+ return ret, nil
+}
+
+func (w *wrapper) Get(name string) (*apistriggersv1alpha1.Interceptor, error) {
+ return w.client.TriggersV1alpha1().Interceptors(w.namespace).Get(context.TODO(), name, v1.GetOptions{
+ ResourceVersion: w.resourceVersion,
+ })
+}
diff --git a/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/controller.go b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/controller.go
new file mode 100644
index 000000000..f98d05f48
--- /dev/null
+++ b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/controller.go
@@ -0,0 +1,162 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package interceptor
+
+import (
+ context "context"
+ fmt "fmt"
+ reflect "reflect"
+ strings "strings"
+
+ versionedscheme "github.com/tektoncd/triggers/pkg/client/clientset/versioned/scheme"
+ client "github.com/tektoncd/triggers/pkg/client/injection/client"
+ interceptor "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor"
+ zap "go.uber.org/zap"
+ corev1 "k8s.io/api/core/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ types "k8s.io/apimachinery/pkg/types"
+ watch "k8s.io/apimachinery/pkg/watch"
+ scheme "k8s.io/client-go/kubernetes/scheme"
+ v1 "k8s.io/client-go/kubernetes/typed/core/v1"
+ record "k8s.io/client-go/tools/record"
+ kubeclient "knative.dev/pkg/client/injection/kube/client"
+ controller "knative.dev/pkg/controller"
+ logging "knative.dev/pkg/logging"
+ logkey "knative.dev/pkg/logging/logkey"
+ reconciler "knative.dev/pkg/reconciler"
+)
+
+const (
+ defaultControllerAgentName = "interceptor-controller"
+ defaultFinalizerName = "interceptors.triggers.tekton.dev"
+)
+
+// NewImpl returns a controller.Impl that handles queuing and feeding work from
+// the queue through an implementation of controller.Reconciler, delegating to
+// the provided Interface and optional Finalizer methods. OptionsFn is used to return
+// controller.ControllerOptions to be used by the internal reconciler.
+func NewImpl(ctx context.Context, r Interface, optionsFns ...controller.OptionsFn) *controller.Impl {
+ logger := logging.FromContext(ctx)
+
+ // Check the options function input. It should be 0 or 1.
+ if len(optionsFns) > 1 {
+ logger.Fatal("Up to one options function is supported, found: ", len(optionsFns))
+ }
+
+ interceptorInformer := interceptor.Get(ctx)
+
+ lister := interceptorInformer.Lister()
+
+ var promoteFilterFunc func(obj interface{}) bool
+
+ rec := &reconcilerImpl{
+ LeaderAwareFuncs: reconciler.LeaderAwareFuncs{
+ PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
+ all, err := lister.List(labels.Everything())
+ if err != nil {
+ return err
+ }
+ for _, elt := range all {
+ if promoteFilterFunc != nil {
+ if ok := promoteFilterFunc(elt); !ok {
+ continue
+ }
+ }
+ enq(bkt, types.NamespacedName{
+ Namespace: elt.GetNamespace(),
+ Name: elt.GetName(),
+ })
+ }
+ return nil
+ },
+ },
+ Client: client.Get(ctx),
+ Lister: lister,
+ reconciler: r,
+ finalizerName: defaultFinalizerName,
+ }
+
+ ctrType := reflect.TypeOf(r).Elem()
+ ctrTypeName := fmt.Sprintf("%s.%s", ctrType.PkgPath(), ctrType.Name())
+ ctrTypeName = strings.ReplaceAll(ctrTypeName, "/", ".")
+
+ logger = logger.With(
+ zap.String(logkey.ControllerType, ctrTypeName),
+ zap.String(logkey.Kind, "triggers.tekton.dev.Interceptor"),
+ )
+
+ impl := controller.NewContext(ctx, rec, controller.ControllerOptions{WorkQueueName: ctrTypeName, Logger: logger})
+ agentName := defaultControllerAgentName
+
+ // Pass impl to the options. Save any optional results.
+ for _, fn := range optionsFns {
+ opts := fn(impl)
+ if opts.ConfigStore != nil {
+ rec.configStore = opts.ConfigStore
+ }
+ if opts.FinalizerName != "" {
+ rec.finalizerName = opts.FinalizerName
+ }
+ if opts.AgentName != "" {
+ agentName = opts.AgentName
+ }
+ if opts.SkipStatusUpdates {
+ rec.skipStatusUpdates = true
+ }
+ if opts.DemoteFunc != nil {
+ rec.DemoteFunc = opts.DemoteFunc
+ }
+ if opts.PromoteFilterFunc != nil {
+ promoteFilterFunc = opts.PromoteFilterFunc
+ }
+ }
+
+ rec.Recorder = createRecorder(ctx, agentName)
+
+ return impl
+}
+
+func createRecorder(ctx context.Context, agentName string) record.EventRecorder {
+ logger := logging.FromContext(ctx)
+
+ recorder := controller.GetEventRecorder(ctx)
+ if recorder == nil {
+ // Create event broadcaster
+ logger.Debug("Creating event broadcaster")
+ eventBroadcaster := record.NewBroadcaster()
+ watches := []watch.Interface{
+ eventBroadcaster.StartLogging(logger.Named("event-broadcaster").Infof),
+ eventBroadcaster.StartRecordingToSink(
+ &v1.EventSinkImpl{Interface: kubeclient.Get(ctx).CoreV1().Events("")}),
+ }
+ recorder = eventBroadcaster.NewRecorder(scheme.Scheme, corev1.EventSource{Component: agentName})
+ go func() {
+ <-ctx.Done()
+ for _, w := range watches {
+ w.Stop()
+ }
+ }()
+ }
+
+ return recorder
+}
+
+func init() {
+ versionedscheme.AddToScheme(scheme.Scheme)
+}
diff --git a/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/reconciler.go b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/reconciler.go
new file mode 100644
index 000000000..6a5677aea
--- /dev/null
+++ b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/reconciler.go
@@ -0,0 +1,429 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package interceptor
+
+import (
+ context "context"
+ json "encoding/json"
+ fmt "fmt"
+
+ v1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ versioned "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
+ triggersv1alpha1 "github.com/tektoncd/triggers/pkg/client/listers/triggers/v1alpha1"
+ zap "go.uber.org/zap"
+ v1 "k8s.io/api/core/v1"
+ equality "k8s.io/apimachinery/pkg/api/equality"
+ errors "k8s.io/apimachinery/pkg/api/errors"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ labels "k8s.io/apimachinery/pkg/labels"
+ types "k8s.io/apimachinery/pkg/types"
+ sets "k8s.io/apimachinery/pkg/util/sets"
+ record "k8s.io/client-go/tools/record"
+ controller "knative.dev/pkg/controller"
+ kmp "knative.dev/pkg/kmp"
+ logging "knative.dev/pkg/logging"
+ reconciler "knative.dev/pkg/reconciler"
+)
+
+// Interface defines the strongly typed interfaces to be implemented by a
+// controller reconciling v1alpha1.Interceptor.
+type Interface interface {
+ // ReconcileKind implements custom logic to reconcile v1alpha1.Interceptor. Any changes
+ // to the objects .Status or .Finalizers will be propagated to the stored
+ // object. It is recommended that implementors do not call any update calls
+ // for the Kind inside of ReconcileKind, it is the responsibility of the calling
+ // controller to propagate those properties. The resource passed to ReconcileKind
+ // will always have an empty deletion timestamp.
+ ReconcileKind(ctx context.Context, o *v1alpha1.Interceptor) reconciler.Event
+}
+
+// Finalizer defines the strongly typed interfaces to be implemented by a
+// controller finalizing v1alpha1.Interceptor.
+type Finalizer interface {
+ // FinalizeKind implements custom logic to finalize v1alpha1.Interceptor. Any changes
+ // to the objects .Status or .Finalizers will be ignored. Returning a nil or
+ // Normal type reconciler.Event will allow the finalizer to be deleted on
+ // the resource. The resource passed to FinalizeKind will always have a set
+ // deletion timestamp.
+ FinalizeKind(ctx context.Context, o *v1alpha1.Interceptor) reconciler.Event
+}
+
+// ReadOnlyInterface defines the strongly typed interfaces to be implemented by a
+// controller reconciling v1alpha1.Interceptor if they want to process resources for which
+// they are not the leader.
+type ReadOnlyInterface interface {
+ // ObserveKind implements logic to observe v1alpha1.Interceptor.
+ // This method should not write to the API.
+ ObserveKind(ctx context.Context, o *v1alpha1.Interceptor) reconciler.Event
+}
+
+type doReconcile func(ctx context.Context, o *v1alpha1.Interceptor) reconciler.Event
+
+// reconcilerImpl implements controller.Reconciler for v1alpha1.Interceptor resources.
+type reconcilerImpl struct {
+ // LeaderAwareFuncs is inlined to help us implement reconciler.LeaderAware.
+ reconciler.LeaderAwareFuncs
+
+ // Client is used to write back status updates.
+ Client versioned.Interface
+
+ // Listers index properties about resources.
+ Lister triggersv1alpha1.InterceptorLister
+
+ // Recorder is an event recorder for recording Event resources to the
+ // Kubernetes API.
+ Recorder record.EventRecorder
+
+ // configStore allows for decorating a context with config maps.
+ // +optional
+ configStore reconciler.ConfigStore
+
+ // reconciler is the implementation of the business logic of the resource.
+ reconciler Interface
+
+ // finalizerName is the name of the finalizer to reconcile.
+ finalizerName string
+
+ // skipStatusUpdates configures whether or not this reconciler automatically updates
+ // the status of the reconciled resource.
+ skipStatusUpdates bool
+}
+
+// Check that our Reconciler implements controller.Reconciler.
+var _ controller.Reconciler = (*reconcilerImpl)(nil)
+
+// Check that our generated Reconciler is always LeaderAware.
+var _ reconciler.LeaderAware = (*reconcilerImpl)(nil)
+
+func NewReconciler(ctx context.Context, logger *zap.SugaredLogger, client versioned.Interface, lister triggersv1alpha1.InterceptorLister, recorder record.EventRecorder, r Interface, options ...controller.Options) controller.Reconciler {
+ // Check the options function input. It should be 0 or 1.
+ if len(options) > 1 {
+ logger.Fatal("Up to one options struct is supported, found: ", len(options))
+ }
+
+ // Fail fast when users inadvertently implement the other LeaderAware interface.
+ // For the typed reconcilers, Promote shouldn't take any arguments.
+ if _, ok := r.(reconciler.LeaderAware); ok {
+ logger.Fatalf("%T implements the incorrect LeaderAware interface. Promote() should not take an argument as genreconciler handles the enqueuing automatically.", r)
+ }
+
+ rec := &reconcilerImpl{
+ LeaderAwareFuncs: reconciler.LeaderAwareFuncs{
+ PromoteFunc: func(bkt reconciler.Bucket, enq func(reconciler.Bucket, types.NamespacedName)) error {
+ all, err := lister.List(labels.Everything())
+ if err != nil {
+ return err
+ }
+ for _, elt := range all {
+ // TODO: Consider letting users specify a filter in options.
+ enq(bkt, types.NamespacedName{
+ Namespace: elt.GetNamespace(),
+ Name: elt.GetName(),
+ })
+ }
+ return nil
+ },
+ },
+ Client: client,
+ Lister: lister,
+ Recorder: recorder,
+ reconciler: r,
+ finalizerName: defaultFinalizerName,
+ }
+
+ for _, opts := range options {
+ if opts.ConfigStore != nil {
+ rec.configStore = opts.ConfigStore
+ }
+ if opts.FinalizerName != "" {
+ rec.finalizerName = opts.FinalizerName
+ }
+ if opts.SkipStatusUpdates {
+ rec.skipStatusUpdates = true
+ }
+ if opts.DemoteFunc != nil {
+ rec.DemoteFunc = opts.DemoteFunc
+ }
+ }
+
+ return rec
+}
+
+// Reconcile implements controller.Reconciler
+func (r *reconcilerImpl) Reconcile(ctx context.Context, key string) error {
+ logger := logging.FromContext(ctx)
+
+ // Initialize the reconciler state. This will convert the namespace/name
+ // string into a distinct namespace and name, determine if this instance of
+ // the reconciler is the leader, and any additional interfaces implemented
+ // by the reconciler. Returns an error is the resource key is invalid.
+ s, err := newState(key, r)
+ if err != nil {
+ logger.Error("Invalid resource key: ", key)
+ return nil
+ }
+
+ // If we are not the leader, and we don't implement either ReadOnly
+ // observer interfaces, then take a fast-path out.
+ if s.isNotLeaderNorObserver() {
+ return controller.NewSkipKey(key)
+ }
+
+ // If configStore is set, attach the frozen configuration to the context.
+ if r.configStore != nil {
+ ctx = r.configStore.ToContext(ctx)
+ }
+
+ // Add the recorder to context.
+ ctx = controller.WithEventRecorder(ctx, r.Recorder)
+
+ // Get the resource with this namespace/name.
+
+ getter := r.Lister.Interceptors(s.namespace)
+
+ original, err := getter.Get(s.name)
+
+ if errors.IsNotFound(err) {
+ // The resource may no longer exist, in which case we stop processing and call
+ // the ObserveDeletion handler if appropriate.
+ logger.Debugf("Resource %q no longer exists", key)
+ if del, ok := r.reconciler.(reconciler.OnDeletionInterface); ok {
+ return del.ObserveDeletion(ctx, types.NamespacedName{
+ Namespace: s.namespace,
+ Name: s.name,
+ })
+ }
+ return nil
+ } else if err != nil {
+ return err
+ }
+
+ // Don't modify the informers copy.
+ resource := original.DeepCopy()
+
+ var reconcileEvent reconciler.Event
+
+ name, do := s.reconcileMethodFor(resource)
+ // Append the target method to the logger.
+ logger = logger.With(zap.String("targetMethod", name))
+ switch name {
+ case reconciler.DoReconcileKind:
+ // Set and update the finalizer on resource if r.reconciler
+ // implements Finalizer.
+ if resource, err = r.setFinalizerIfFinalizer(ctx, resource); err != nil {
+ return fmt.Errorf("failed to set finalizers: %w", err)
+ }
+
+ // Reconcile this copy of the resource and then write back any status
+ // updates regardless of whether the reconciliation errored out.
+ reconcileEvent = do(ctx, resource)
+
+ case reconciler.DoFinalizeKind:
+ // For finalizing reconcilers, if this resource being marked for deletion
+ // and reconciled cleanly (nil or normal event), remove the finalizer.
+ reconcileEvent = do(ctx, resource)
+
+ if resource, err = r.clearFinalizer(ctx, resource, reconcileEvent); err != nil {
+ return fmt.Errorf("failed to clear finalizers: %w", err)
+ }
+
+ case reconciler.DoObserveKind:
+ // Observe any changes to this resource, since we are not the leader.
+ reconcileEvent = do(ctx, resource)
+
+ }
+
+ // Synchronize the status.
+ switch {
+ case r.skipStatusUpdates:
+ // This reconciler implementation is configured to skip resource updates.
+ // This may mean this reconciler does not observe spec, but reconciles external changes.
+ case equality.Semantic.DeepEqual(original.Status, resource.Status):
+ // If we didn't change anything then don't call updateStatus.
+ // This is important because the copy we loaded from the injectionInformer's
+ // cache may be stale and we don't want to overwrite a prior update
+ // to status with this stale state.
+ case !s.isLeader:
+ // High-availability reconcilers may have many replicas watching the resource, but only
+ // the elected leader is expected to write modifications.
+ logger.Warn("Saw status changes when we aren't the leader!")
+ default:
+ if err = r.updateStatus(ctx, original, resource); err != nil {
+ logger.Warnw("Failed to update resource status", zap.Error(err))
+ r.Recorder.Eventf(resource, v1.EventTypeWarning, "UpdateFailed",
+ "Failed to update status for %q: %v", resource.Name, err)
+ return err
+ }
+ }
+
+ // Report the reconciler event, if any.
+ if reconcileEvent != nil {
+ var event *reconciler.ReconcilerEvent
+ if reconciler.EventAs(reconcileEvent, &event) {
+ logger.Infow("Returned an event", zap.Any("event", reconcileEvent))
+ r.Recorder.Event(resource, event.EventType, event.Reason, event.Error())
+
+ // the event was wrapped inside an error, consider the reconciliation as failed
+ if _, isEvent := reconcileEvent.(*reconciler.ReconcilerEvent); !isEvent {
+ return reconcileEvent
+ }
+ return nil
+ }
+
+ if controller.IsSkipKey(reconcileEvent) {
+ // This is a wrapped error, don't emit an event.
+ } else if ok, _ := controller.IsRequeueKey(reconcileEvent); ok {
+ // This is a wrapped error, don't emit an event.
+ } else {
+ logger.Errorw("Returned an error", zap.Error(reconcileEvent))
+ r.Recorder.Event(resource, v1.EventTypeWarning, "InternalError", reconcileEvent.Error())
+ }
+ return reconcileEvent
+ }
+
+ return nil
+}
+
+func (r *reconcilerImpl) updateStatus(ctx context.Context, existing *v1alpha1.Interceptor, desired *v1alpha1.Interceptor) error {
+ existing = existing.DeepCopy()
+ return reconciler.RetryUpdateConflicts(func(attempts int) (err error) {
+ // The first iteration tries to use the injectionInformer's state, subsequent attempts fetch the latest state via API.
+ if attempts > 0 {
+
+ getter := r.Client.TriggersV1alpha1().Interceptors(desired.Namespace)
+
+ existing, err = getter.Get(ctx, desired.Name, metav1.GetOptions{})
+ if err != nil {
+ return err
+ }
+ }
+
+ // If there's nothing to update, just return.
+ if equality.Semantic.DeepEqual(existing.Status, desired.Status) {
+ return nil
+ }
+
+ if diff, err := kmp.SafeDiff(existing.Status, desired.Status); err == nil && diff != "" {
+ logging.FromContext(ctx).Debug("Updating status with: ", diff)
+ }
+
+ existing.Status = desired.Status
+
+ updater := r.Client.TriggersV1alpha1().Interceptors(existing.Namespace)
+
+ _, err = updater.UpdateStatus(ctx, existing, metav1.UpdateOptions{})
+ return err
+ })
+}
+
+// updateFinalizersFiltered will update the Finalizers of the resource.
+// TODO: this method could be generic and sync all finalizers. For now it only
+// updates defaultFinalizerName or its override.
+func (r *reconcilerImpl) updateFinalizersFiltered(ctx context.Context, resource *v1alpha1.Interceptor, desiredFinalizers sets.String) (*v1alpha1.Interceptor, error) {
+ // Don't modify the informers copy.
+ existing := resource.DeepCopy()
+
+ var finalizers []string
+
+ // If there's nothing to update, just return.
+ existingFinalizers := sets.NewString(existing.Finalizers...)
+
+ if desiredFinalizers.Has(r.finalizerName) {
+ if existingFinalizers.Has(r.finalizerName) {
+ // Nothing to do.
+ return resource, nil
+ }
+ // Add the finalizer.
+ finalizers = append(existing.Finalizers, r.finalizerName)
+ } else {
+ if !existingFinalizers.Has(r.finalizerName) {
+ // Nothing to do.
+ return resource, nil
+ }
+ // Remove the finalizer.
+ existingFinalizers.Delete(r.finalizerName)
+ finalizers = existingFinalizers.List()
+ }
+
+ mergePatch := map[string]interface{}{
+ "metadata": map[string]interface{}{
+ "finalizers": finalizers,
+ "resourceVersion": existing.ResourceVersion,
+ },
+ }
+
+ patch, err := json.Marshal(mergePatch)
+ if err != nil {
+ return resource, err
+ }
+
+ patcher := r.Client.TriggersV1alpha1().Interceptors(resource.Namespace)
+
+ resourceName := resource.Name
+ updated, err := patcher.Patch(ctx, resourceName, types.MergePatchType, patch, metav1.PatchOptions{})
+ if err != nil {
+ r.Recorder.Eventf(existing, v1.EventTypeWarning, "FinalizerUpdateFailed",
+ "Failed to update finalizers for %q: %v", resourceName, err)
+ } else {
+ r.Recorder.Eventf(updated, v1.EventTypeNormal, "FinalizerUpdate",
+ "Updated %q finalizers", resource.GetName())
+ }
+ return updated, err
+}
+
+func (r *reconcilerImpl) setFinalizerIfFinalizer(ctx context.Context, resource *v1alpha1.Interceptor) (*v1alpha1.Interceptor, error) {
+ if _, ok := r.reconciler.(Finalizer); !ok {
+ return resource, nil
+ }
+
+ finalizers := sets.NewString(resource.Finalizers...)
+
+ // If this resource is not being deleted, mark the finalizer.
+ if resource.GetDeletionTimestamp().IsZero() {
+ finalizers.Insert(r.finalizerName)
+ }
+
+ // Synchronize the finalizers filtered by r.finalizerName.
+ return r.updateFinalizersFiltered(ctx, resource, finalizers)
+}
+
+func (r *reconcilerImpl) clearFinalizer(ctx context.Context, resource *v1alpha1.Interceptor, reconcileEvent reconciler.Event) (*v1alpha1.Interceptor, error) {
+ if _, ok := r.reconciler.(Finalizer); !ok {
+ return resource, nil
+ }
+ if resource.GetDeletionTimestamp().IsZero() {
+ return resource, nil
+ }
+
+ finalizers := sets.NewString(resource.Finalizers...)
+
+ if reconcileEvent != nil {
+ var event *reconciler.ReconcilerEvent
+ if reconciler.EventAs(reconcileEvent, &event) {
+ if event.EventType == v1.EventTypeNormal {
+ finalizers.Delete(r.finalizerName)
+ }
+ }
+ } else {
+ finalizers.Delete(r.finalizerName)
+ }
+
+ // Synchronize the finalizers filtered by r.finalizerName.
+ return r.updateFinalizersFiltered(ctx, resource, finalizers)
+}
diff --git a/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/state.go b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/state.go
new file mode 100644
index 000000000..d5542df3a
--- /dev/null
+++ b/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor/state.go
@@ -0,0 +1,97 @@
+/*
+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.
+*/
+
+// Code generated by injection-gen. DO NOT EDIT.
+
+package interceptor
+
+import (
+ fmt "fmt"
+
+ v1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ types "k8s.io/apimachinery/pkg/types"
+ cache "k8s.io/client-go/tools/cache"
+ reconciler "knative.dev/pkg/reconciler"
+)
+
+// state is used to track the state of a reconciler in a single run.
+type state struct {
+ // key is the original reconciliation key from the queue.
+ key string
+ // namespace is the namespace split from the reconciliation key.
+ namespace string
+ // name is the name split from the reconciliation key.
+ name string
+ // reconciler is the reconciler.
+ reconciler Interface
+ // roi is the read only interface cast of the reconciler.
+ roi ReadOnlyInterface
+ // isROI (Read Only Interface) the reconciler only observes reconciliation.
+ isROI bool
+ // isLeader the instance of the reconciler is the elected leader.
+ isLeader bool
+}
+
+func newState(key string, r *reconcilerImpl) (*state, error) {
+ // Convert the namespace/name string into a distinct namespace and name.
+ namespace, name, err := cache.SplitMetaNamespaceKey(key)
+ if err != nil {
+ return nil, fmt.Errorf("invalid resource key: %s", key)
+ }
+
+ roi, isROI := r.reconciler.(ReadOnlyInterface)
+
+ isLeader := r.IsLeaderFor(types.NamespacedName{
+ Namespace: namespace,
+ Name: name,
+ })
+
+ return &state{
+ key: key,
+ namespace: namespace,
+ name: name,
+ reconciler: r.reconciler,
+ roi: roi,
+ isROI: isROI,
+ isLeader: isLeader,
+ }, nil
+}
+
+// isNotLeaderNorObserver checks to see if this reconciler with the current
+// state is enabled to do any work or not.
+// isNotLeaderNorObserver returns true when there is no work possible for the
+// reconciler.
+func (s *state) isNotLeaderNorObserver() bool {
+ if !s.isLeader && !s.isROI {
+ // If we are not the leader, and we don't implement the ReadOnly
+ // interface, then take a fast-path out.
+ return true
+ }
+ return false
+}
+
+func (s *state) reconcileMethodFor(o *v1alpha1.Interceptor) (string, doReconcile) {
+ if o.GetDeletionTimestamp().IsZero() {
+ if s.isLeader {
+ return reconciler.DoReconcileKind, s.reconciler.ReconcileKind
+ } else if s.isROI {
+ return reconciler.DoObserveKind, s.roi.ObserveKind
+ }
+ } else if fin, ok := s.reconciler.(Finalizer); s.isLeader && ok {
+ return reconciler.DoFinalizeKind, fin.FinalizeKind
+ }
+ return "unknown", nil
+}
diff --git a/pkg/client/listers/triggers/v1alpha1/expansion_generated.go b/pkg/client/listers/triggers/v1alpha1/expansion_generated.go
index 9581afc7c..6f1ebae38 100644
--- a/pkg/client/listers/triggers/v1alpha1/expansion_generated.go
+++ b/pkg/client/listers/triggers/v1alpha1/expansion_generated.go
@@ -34,6 +34,14 @@ type EventListenerListerExpansion interface{}
// EventListenerNamespaceLister.
type EventListenerNamespaceListerExpansion interface{}
+// InterceptorListerExpansion allows custom methods to be added to
+// InterceptorLister.
+type InterceptorListerExpansion interface{}
+
+// InterceptorNamespaceListerExpansion allows custom methods to be added to
+// InterceptorNamespaceLister.
+type InterceptorNamespaceListerExpansion interface{}
+
// TriggerListerExpansion allows custom methods to be added to
// TriggerLister.
type TriggerListerExpansion interface{}
diff --git a/pkg/client/listers/triggers/v1alpha1/interceptor.go b/pkg/client/listers/triggers/v1alpha1/interceptor.go
new file mode 100644
index 000000000..235b62a32
--- /dev/null
+++ b/pkg/client/listers/triggers/v1alpha1/interceptor.go
@@ -0,0 +1,99 @@
+/*
+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.
+*/
+
+// Code generated by lister-gen. DO NOT EDIT.
+
+package v1alpha1
+
+import (
+ v1alpha1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ "k8s.io/apimachinery/pkg/api/errors"
+ "k8s.io/apimachinery/pkg/labels"
+ "k8s.io/client-go/tools/cache"
+)
+
+// InterceptorLister helps list Interceptors.
+// All objects returned here must be treated as read-only.
+type InterceptorLister interface {
+ // List lists all Interceptors in the indexer.
+ // Objects returned here must be treated as read-only.
+ List(selector labels.Selector) (ret []*v1alpha1.Interceptor, err error)
+ // Interceptors returns an object that can list and get Interceptors.
+ Interceptors(namespace string) InterceptorNamespaceLister
+ InterceptorListerExpansion
+}
+
+// interceptorLister implements the InterceptorLister interface.
+type interceptorLister struct {
+ indexer cache.Indexer
+}
+
+// NewInterceptorLister returns a new InterceptorLister.
+func NewInterceptorLister(indexer cache.Indexer) InterceptorLister {
+ return &interceptorLister{indexer: indexer}
+}
+
+// List lists all Interceptors in the indexer.
+func (s *interceptorLister) List(selector labels.Selector) (ret []*v1alpha1.Interceptor, err error) {
+ err = cache.ListAll(s.indexer, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Interceptor))
+ })
+ return ret, err
+}
+
+// Interceptors returns an object that can list and get Interceptors.
+func (s *interceptorLister) Interceptors(namespace string) InterceptorNamespaceLister {
+ return interceptorNamespaceLister{indexer: s.indexer, namespace: namespace}
+}
+
+// InterceptorNamespaceLister helps list and get Interceptors.
+// All objects returned here must be treated as read-only.
+type InterceptorNamespaceLister interface {
+ // List lists all Interceptors in the indexer for a given namespace.
+ // Objects returned here must be treated as read-only.
+ List(selector labels.Selector) (ret []*v1alpha1.Interceptor, err error)
+ // Get retrieves the Interceptor from the indexer for a given namespace and name.
+ // Objects returned here must be treated as read-only.
+ Get(name string) (*v1alpha1.Interceptor, error)
+ InterceptorNamespaceListerExpansion
+}
+
+// interceptorNamespaceLister implements the InterceptorNamespaceLister
+// interface.
+type interceptorNamespaceLister struct {
+ indexer cache.Indexer
+ namespace string
+}
+
+// List lists all Interceptors in the indexer for a given namespace.
+func (s interceptorNamespaceLister) List(selector labels.Selector) (ret []*v1alpha1.Interceptor, err error) {
+ err = cache.ListAllByNamespace(s.indexer, s.namespace, selector, func(m interface{}) {
+ ret = append(ret, m.(*v1alpha1.Interceptor))
+ })
+ return ret, err
+}
+
+// Get retrieves the Interceptor from the indexer for a given namespace and name.
+func (s interceptorNamespaceLister) Get(name string) (*v1alpha1.Interceptor, error) {
+ obj, exists, err := s.indexer.GetByKey(s.namespace + "/" + name)
+ if err != nil {
+ return nil, err
+ }
+ if !exists {
+ return nil, errors.NewNotFound(v1alpha1.Resource("interceptor"), name)
+ }
+ return obj.(*v1alpha1.Interceptor), nil
+}
diff --git a/pkg/reconciler/interceptor/controller.go b/pkg/reconciler/interceptor/controller.go
new file mode 100644
index 000000000..c98270f2e
--- /dev/null
+++ b/pkg/reconciler/interceptor/controller.go
@@ -0,0 +1,43 @@
+/*
+Copyright 2021 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 interceptor
+
+import (
+ "context"
+
+ interceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor"
+ interceptorreconciler "github.com/tektoncd/triggers/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor"
+ "knative.dev/pkg/configmap"
+ "knative.dev/pkg/controller"
+)
+
+func NewController() func(context.Context, configmap.Watcher) *controller.Impl {
+ return func(ctx context.Context, cmw configmap.Watcher) *controller.Impl {
+ interceptorInformer := interceptorinformer.Get(ctx)
+ reconciler := &Reconciler{}
+
+ impl := interceptorreconciler.NewImpl(ctx, reconciler, func(impl *controller.Impl) controller.Options {
+ return controller.Options{
+ AgentName: ControllerName,
+ }
+ })
+
+ interceptorInformer.Informer().AddEventHandler(controller.HandleAll(impl.Enqueue))
+
+ return impl
+ }
+}
diff --git a/pkg/reconciler/interceptor/interceptor.go b/pkg/reconciler/interceptor/interceptor.go
new file mode 100644
index 000000000..fec0a892d
--- /dev/null
+++ b/pkg/reconciler/interceptor/interceptor.go
@@ -0,0 +1,56 @@
+/*
+Copyright 2021 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 interceptor
+
+import (
+ "context"
+
+ "github.com/tektoncd/triggers/pkg/apis/triggers/contexts"
+ "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ interceptorreconciler "github.com/tektoncd/triggers/pkg/client/injection/reconciler/triggers/v1alpha1/interceptor"
+ v1 "knative.dev/pkg/apis/duck/v1"
+ "knative.dev/pkg/logging"
+ pkgreconciler "knative.dev/pkg/reconciler"
+)
+
+const ControllerName = "Interceptor"
+
+// Reconciler implements controller.Reconciler for Configuration resources.
+type Reconciler struct {
+}
+
+var (
+ // Check that our Reconciler implements interceptorreconciler.Interface
+ _ interceptorreconciler.Interface = (*Reconciler)(nil)
+)
+
+func (r *Reconciler) ReconcileKind(ctx context.Context, it *v1alpha1.Interceptor) pkgreconciler.Event {
+ logger := logging.FromContext(ctx)
+ if it.Status.Address == nil { // Initialize Address if needed
+ it.Status.Address = &v1.Addressable{}
+ }
+ if contexts.IsUpgradeViaDefaulting(ctx) { // Set defaults
+ it.SetDefaults(ctx)
+ }
+ url, err := it.ResolveAddress()
+ logger.Debugf("Resolved Address is %s", url)
+ if err != nil {
+ return err
+ }
+ it.Status.Address.URL = url
+ return nil
+}
diff --git a/pkg/reconciler/interceptor/interceptor_test.go b/pkg/reconciler/interceptor/interceptor_test.go
new file mode 100644
index 000000000..248385967
--- /dev/null
+++ b/pkg/reconciler/interceptor/interceptor_test.go
@@ -0,0 +1,179 @@
+/*
+Copyright 2021 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 interceptor
+
+import (
+ "testing"
+
+ "github.com/google/go-cmp/cmp"
+ "github.com/tektoncd/triggers/pkg/apis/triggers/contexts"
+ triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
+ metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+ "knative.dev/pkg/apis"
+ duckv1 "knative.dev/pkg/apis/duck/v1"
+ logtesting "knative.dev/pkg/logging/testing"
+ "knative.dev/pkg/ptr"
+)
+
+func TestReconcileKind(t *testing.T) {
+ tests := []struct {
+ name string
+ initial *triggersv1.Interceptor // State of the world before we call Reconcile
+ want *triggersv1.Interceptor // Expected State of the world after calling Reconcile
+ }{{
+ name: "initial status is nil",
+ initial: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ Port: ptr.Int32(80),
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{},
+ },
+ want: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ Labels: map[string]string{"server/type": "http"},
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ Port: ptr.Int32(80),
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{
+ AddressStatus: duckv1.AddressStatus{
+ Address: &duckv1.Addressable{
+ URL: &apis.URL{
+ Scheme: "http",
+ Host: "my-svc.default.svc:80",
+ Path: "path",
+ },
+ },
+ },
+ },
+ },
+ }, {
+ name: "defaults are applied",
+ initial: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{},
+ },
+ want: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ Labels: map[string]string{"server/type": "http"},
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{
+ AddressStatus: duckv1.AddressStatus{
+ Address: &duckv1.Addressable{
+ URL: &apis.URL{
+ Scheme: "http",
+ Host: "my-svc.default.svc:80",
+ Path: "path",
+ },
+ },
+ },
+ },
+ },
+ }, {
+ name: "when provided caBundle",
+ initial: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ Labels: map[string]string{"server/type": "https"},
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ CaBundle: []byte("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQXB5Z0F3SUJBZ0lRSllLcEFVeXc2dStvY1JhV1VtRVRoREFLQmdncWhrak9QUVFEQWpCWE1SUXcKRWdZRFZRUUtFd3RyYm1GMGFYWmxMbVJsZGpFL01EMEdBMVVFQXhNMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdgpjbVV0YVc1MFpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpNQ0FYRFRJeU1EUXhOVEUyCk1ERTFPRm9ZRHpJeE1qSXdNekl5TVRZd01UVTRXakJYTVJRd0VnWURWUVFLRXd0cmJtRjBhWFpsTG1SbGRqRS8KTUQwR0ExVUVBeE0yZEdWcmRHOXVMWFJ5YVdkblpYSnpMV052Y21VdGFXNTBaWEpqWlhCMGIzSnpMblJsYTNSdgpiaTF3YVhCbGJHbHVaWE11YzNaak1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUFHcHp1RjlQCjY5VnFhN0xIY0tmNGpWY2JqblJNWDAxYWRnakh0Zy9kZFdIaVBWdXVJZER1WnZzVTREaVp5Smh2WnpmaHQ0ZmsKT3FJc3dJeVlmbkpLRnFPQ0FVWXdnZ0ZDTUE0R0ExVWREd0VCL3dRRUF3SUNoREFkQmdOVkhTVUVGakFVQmdncgpCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVQRXFjCnEvRFJHd2FDUTdmOFc0dmlucGN5a09zd2dlQUdBMVVkRVFTQjJEQ0IxWUloZEdWcmRHOXVMWFJ5YVdkblpYSnoKTFdOdmNtVXRhVzUwWlhKalpYQjBiM0p6Z2pKMFpXdDBiMjR0ZEhKcFoyZGxjbk10WTI5eVpTMXBiblJsY21ObApjSFJ2Y25NdWRHVnJkRzl1TFhCcGNHVnNhVzVsYzRJMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdmNtVXRhVzUwClpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpna1IwWld0MGIyNHRkSEpwWjJkbGNuTXQKWTI5eVpTMXBiblJsY21ObGNIUnZjbk11ZEdWcmRHOXVMWEJwY0dWc2FXNWxjeTV6ZG1NdVkyeDFjM1JsY2k1cwpiMk5oYkRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQTlhWFBtUFZzRVA3R0xTbzI0SnNmNnRGTmpyQWJRbEl0CjRCYXllcjBnaU5jQ0lRQ09XSm1NTXQxQkE1RXgwa0FYTWRtZjlFdXV4LzlyUUkzMm9VNjVSYm9mNEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="),
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{},
+ },
+ want: &triggersv1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "my-interceptor",
+ Labels: map[string]string{"server/type": "https"},
+ },
+ Spec: triggersv1.InterceptorSpec{
+ ClientConfig: triggersv1.ClientConfig{
+ CaBundle: []byte("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM5ekNDQXB5Z0F3SUJBZ0lRSllLcEFVeXc2dStvY1JhV1VtRVRoREFLQmdncWhrak9QUVFEQWpCWE1SUXcKRWdZRFZRUUtFd3RyYm1GMGFYWmxMbVJsZGpFL01EMEdBMVVFQXhNMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdgpjbVV0YVc1MFpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpNQ0FYRFRJeU1EUXhOVEUyCk1ERTFPRm9ZRHpJeE1qSXdNekl5TVRZd01UVTRXakJYTVJRd0VnWURWUVFLRXd0cmJtRjBhWFpsTG1SbGRqRS8KTUQwR0ExVUVBeE0yZEdWcmRHOXVMWFJ5YVdkblpYSnpMV052Y21VdGFXNTBaWEpqWlhCMGIzSnpMblJsYTNSdgpiaTF3YVhCbGJHbHVaWE11YzNaak1Ga3dFd1lIS29aSXpqMENBUVlJS29aSXpqMERBUWNEUWdBRUFHcHp1RjlQCjY5VnFhN0xIY0tmNGpWY2JqblJNWDAxYWRnakh0Zy9kZFdIaVBWdXVJZER1WnZzVTREaVp5Smh2WnpmaHQ0ZmsKT3FJc3dJeVlmbkpLRnFPQ0FVWXdnZ0ZDTUE0R0ExVWREd0VCL3dRRUF3SUNoREFkQmdOVkhTVUVGakFVQmdncgpCZ0VGQlFjREFRWUlLd1lCQlFVSEF3SXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QWRCZ05WSFE0RUZnUVVQRXFjCnEvRFJHd2FDUTdmOFc0dmlucGN5a09zd2dlQUdBMVVkRVFTQjJEQ0IxWUloZEdWcmRHOXVMWFJ5YVdkblpYSnoKTFdOdmNtVXRhVzUwWlhKalpYQjBiM0p6Z2pKMFpXdDBiMjR0ZEhKcFoyZGxjbk10WTI5eVpTMXBiblJsY21ObApjSFJ2Y25NdWRHVnJkRzl1TFhCcGNHVnNhVzVsYzRJMmRHVnJkRzl1TFhSeWFXZG5aWEp6TFdOdmNtVXRhVzUwClpYSmpaWEIwYjNKekxuUmxhM1J2Ymkxd2FYQmxiR2x1WlhNdWMzWmpna1IwWld0MGIyNHRkSEpwWjJkbGNuTXQKWTI5eVpTMXBiblJsY21ObGNIUnZjbk11ZEdWcmRHOXVMWEJwY0dWc2FXNWxjeTV6ZG1NdVkyeDFjM1JsY2k1cwpiMk5oYkRBS0JnZ3Foa2pPUFFRREFnTkpBREJHQWlFQTlhWFBtUFZzRVA3R0xTbzI0SnNmNnRGTmpyQWJRbEl0CjRCYXllcjBnaU5jQ0lRQ09XSm1NTXQxQkE1RXgwa0FYTWRtZjlFdXV4LzlyUUkzMm9VNjVSYm9mNEE9PQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="),
+ Service: &triggersv1.ServiceReference{
+ Name: "my-svc",
+ Namespace: "default",
+ Path: "path",
+ },
+ }},
+ Status: triggersv1.InterceptorStatus{
+ AddressStatus: duckv1.AddressStatus{
+ Address: &duckv1.Addressable{
+ URL: &apis.URL{
+ Scheme: "https",
+ Host: "my-svc.default.svc:8443",
+ Path: "path",
+ },
+ },
+ },
+ },
+ },
+ }}
+
+ for _, tc := range tests {
+ r := Reconciler{}
+ context := contexts.WithUpgradeViaDefaulting(logtesting.TestContextWithLogger(t))
+ err := r.ReconcileKind(context, tc.initial)
+ if err != nil {
+ t.Fatalf("ReconcileKind() unexpected error: %v", err)
+ }
+ got := tc.initial
+ if diff := cmp.Diff(tc.want, got); diff != "" {
+ t.Fatalf("ReconcileKind() diff -want/+got: %s", diff)
+ }
+ }
+}
diff --git a/pkg/sink/sink.go b/pkg/sink/sink.go
index 14424c3f1..82ddf5c26 100644
--- a/pkg/sink/sink.go
+++ b/pkg/sink/sink.go
@@ -51,6 +51,7 @@ import (
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/record"
+ "knative.dev/pkg/apis"
v1 "knative.dev/pkg/apis/duck/v1"
)
@@ -82,6 +83,7 @@ type Sink struct {
ClusterTriggerBindingLister listers.ClusterTriggerBindingLister
TriggerTemplateLister listers.TriggerTemplateLister
ClusterInterceptorLister listersv1alpha1.ClusterInterceptorLister
+ InterceptorLister listersv1alpha1.InterceptorLister
}
// Response defines the HTTP body that the Sink responds to events with.
@@ -503,9 +505,37 @@ func (r Sink) ExecuteInterceptors(trInt []*triggersv1.TriggerInterceptor, in *ht
continue
}
request.InterceptorParams = interceptors.GetInterceptorParams(i)
- url, err := interceptors.ResolveToURL(r.ClusterInterceptorLister.Get, i.GetName())
- if err != nil {
- return nil, nil, nil, fmt.Errorf("could not resolve interceptor URL: %w", err)
+
+ var url *apis.URL
+ if i.Ref.Kind == triggersv1.ClusterInterceptorKind {
+ ic, err := r.ClusterInterceptorLister.Get(i.GetName())
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("url resolution failed for interceptor %s with: %w", i.GetName(), err)
+ }
+ if ic.Status.Address != nil && ic.Status.Address.URL != nil {
+ url = ic.Status.Address.URL
+ } else if url, err = ic.ResolveAddress(); err != nil {
+ return nil, nil, nil, fmt.Errorf("url resolution failed for interceptor %s with: %w", i.GetName(), err)
+ }
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("could not resolve clusterinterceptor URL: %w", err)
+ }
+ } else if i.Ref.Kind == triggersv1.NamespacedInterceptorKind {
+ if r.InterceptorLister == nil {
+ r.Logger.Debugf("nil lister")
+ }
+ ic, err := r.InterceptorLister.Interceptors(r.EventListenerNamespace).Get(i.GetName())
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("url resolution failed for interceptor %s with: %w", i.GetName(), err)
+ }
+ if addr := ic.Status.Address; addr != nil && addr.URL != nil {
+ url = addr.URL
+ } else if url, err = ic.ResolveAddress(); err != nil {
+ return nil, nil, nil, fmt.Errorf("url resolution failed for interceptor %s with: %w", i.GetName(), err)
+ }
+ if err != nil {
+ return nil, nil, nil, fmt.Errorf("could not resolve clusterinterceptor URL: %w", err)
+ }
}
interceptorResponse, err := interceptors.Execute(context.Background(), r.HTTPClient, &request, url.String())
diff --git a/pkg/sink/sink_test.go b/pkg/sink/sink_test.go
index a1e0fb10a..21122a493 100644
--- a/pkg/sink/sink_test.go
+++ b/pkg/sink/sink_test.go
@@ -41,7 +41,8 @@ import (
triggersv1beta1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1beta1"
dynamicclientset "github.com/tektoncd/triggers/pkg/client/dynamic/clientset"
"github.com/tektoncd/triggers/pkg/client/dynamic/clientset/tekton"
- interceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/clusterinterceptor"
+ clusterinterceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/clusterinterceptor"
+ interceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor"
clustertriggerbindinginformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/clustertriggerbinding"
eventlistenerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/eventlistener"
triggerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/trigger"
@@ -123,6 +124,21 @@ var (
},
},
}
+ nsInterceptor = &triggersv1alpha1.Interceptor{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "bitbucket",
+ Namespace: namespace,
+ },
+ Spec: triggersv1alpha1.InterceptorSpec{
+ ClientConfig: triggersv1alpha1.ClientConfig{
+ URL: &apis.URL{
+ Scheme: "http",
+ Host: "tekton-triggers-core-interceptors",
+ Path: "/bitbucket",
+ },
+ },
+ },
+ }
)
// getSinkAssets seeds test resources and returns a testable Sink and a dynamic client. The returned client is used to
@@ -162,7 +178,8 @@ func getSinkAssets(t *testing.T, res test.Resources, elName string, webhookInter
TriggerBindingLister: triggerbindinginformer.Get(ctx).Lister(),
ClusterTriggerBindingLister: clustertriggerbindinginformer.Get(ctx).Lister(),
TriggerTemplateLister: triggertemplateinformer.Get(ctx).Lister(),
- ClusterInterceptorLister: interceptorinformer.Get(ctx).Lister(),
+ ClusterInterceptorLister: clusterinterceptorinformer.Get(ctx).Lister(),
+ InterceptorLister: interceptorinformer.Get(ctx).Lister(),
PayloadValidation: true,
}
return r, dynamicClient
@@ -685,7 +702,7 @@ func TestHandleEvent(t *testing.T) {
},
Spec: triggersv1beta1.TriggerSpec{
Interceptors: []*triggersv1beta1.EventInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "github"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "github", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "secretRef",
Value: test.ToV1JSON(t, &triggersv1beta1.SecretRef{
@@ -740,7 +757,62 @@ func TestHandleEvent(t *testing.T) {
},
Spec: triggersv1beta1.TriggerSpec{
Interceptors: []*triggersv1beta1.EventInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "bitbucket"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "bitbucket", Kind: triggersv1beta1.ClusterInterceptorKind},
+ Params: []triggersv1beta1.InterceptorParams{{
+ Name: "secretRef",
+ Value: test.ToV1JSON(t, &triggersv1beta1.SecretRef{
+ SecretKey: "secretKey",
+ SecretName: "secret",
+ }),
+ }, {
+ Name: "eventTypes",
+ Value: test.ToV1JSON(t, []string{"repo:refs_changed"}),
+ }},
+ }},
+ Bindings: gitCloneTBSpec,
+ Template: triggersv1beta1.TriggerSpecTemplate{Spec: makeGitCloneTTSpec(t, "git-clone-test-run")},
+ },
+ }},
+ EventListeners: []*triggersv1beta1.EventListener{{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: eventListenerName,
+ Namespace: namespace,
+ UID: types.UID(elUID),
+ },
+ Spec: triggersv1beta1.EventListenerSpec{
+ Triggers: []triggersv1beta1.EventListenerTrigger{{
+ TriggerRef: "git-clone-trigger",
+ }},
+ },
+ }},
+ },
+ eventBody: eventBody,
+ headers: map[string][]string{
+ "X-Event-Key": {"repo:refs_changed"},
+ "X-Hub-Signature": {test.HMACHeader(t, "secret", eventBody, "sha1")},
+ },
+ want: []pipelinev1.TaskRun{gitCloneTaskRun},
+ }, {
+ name: "with namespaced interceptor",
+ resources: test.Resources{
+ Secrets: []*corev1.Secret{{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "secret",
+ Namespace: namespace,
+ },
+ Data: map[string][]byte{
+ "secretKey": []byte("secret"),
+ },
+ }},
+ Interceptors: []*triggersv1alpha1.Interceptor{nsInterceptor},
+ Triggers: []*triggersv1beta1.Trigger{{
+ ObjectMeta: metav1.ObjectMeta{
+ Name: "git-clone-trigger",
+ Namespace: namespace,
+ },
+ Spec: triggersv1beta1.TriggerSpec{
+ Interceptors: []*triggersv1beta1.EventInterceptor{{
+ Ref: triggersv1beta1.InterceptorRef{Name: "bitbucket", Kind: triggersv1beta1.NamespacedInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "secretRef",
Value: test.ToV1JSON(t, &triggersv1beta1.SecretRef{
@@ -898,6 +970,7 @@ func TestHandleEvent(t *testing.T) {
Interceptors: []*triggersv1beta1.EventInterceptor{{
Ref: triggersv1beta1.InterceptorRef{
Name: "cel",
+ Kind: triggersv1beta1.ClusterInterceptorKind,
},
Params: []triggersv1beta1.InterceptorParams{
{Name: "filter", Value: test.ToV1JSON(t, "has(body.head_commit)")},
@@ -924,6 +997,7 @@ func TestHandleEvent(t *testing.T) {
Interceptors: []*triggersv1beta1.EventInterceptor{{
Ref: triggersv1beta1.InterceptorRef{
Name: "cel",
+ Kind: triggersv1beta1.ClusterInterceptorKind,
},
Params: []triggersv1beta1.InterceptorParams{
{Name: "filter", Value: test.ToV1JSON(t, "has(body.head_commit)")},
@@ -953,7 +1027,7 @@ func TestHandleEvent(t *testing.T) {
{
TriggerRef: "git-clone-trigger",
Interceptors: []*triggersv1beta1.TriggerInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "filter",
Value: test.ToV1JSON(t, "has(body.head_commit)"),
@@ -963,7 +1037,7 @@ func TestHandleEvent(t *testing.T) {
{
TriggerRef: "git-clone-trigger-2",
Interceptors: []*triggersv1beta1.TriggerInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "filter",
Value: test.ToV1JSON(t, "has(body.head_commit)"),
@@ -1078,7 +1152,7 @@ func TestHandleEvent(t *testing.T) {
TriggerGroups: []triggersv1beta1.EventListenerTriggerGroup{{
Name: "filter-event",
Interceptors: []*triggersv1beta1.TriggerInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "filter",
Value: test.ToV1JSON(t, "has(body.head_commit)"),
@@ -1392,7 +1466,7 @@ func TestExecuteInterceptor_NotContinue(t *testing.T) {
trigger := triggersv1beta1.Trigger{
Spec: triggersv1beta1.TriggerSpec{
Interceptors: []*triggersv1beta1.EventInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "filter",
Value: test.ToV1JSON(t, `body.head == "abcde"`),
@@ -1446,7 +1520,7 @@ func TestExecuteInterceptor_ExtensionChaining(t *testing.T) {
trigger := triggersv1beta1.Trigger{
Spec: triggersv1beta1.TriggerSpec{
Interceptors: []*triggersv1beta1.EventInterceptor{{
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "overlays",
Value: test.ToV1JSON(t, []triggersv1beta1.CELOverlay{{
@@ -1463,7 +1537,7 @@ func TestExecuteInterceptor_ExtensionChaining(t *testing.T) {
},
},
}, {
- Ref: triggersv1beta1.InterceptorRef{Name: "cel"},
+ Ref: triggersv1beta1.InterceptorRef{Name: "cel", Kind: triggersv1beta1.ClusterInterceptorKind},
Params: []triggersv1beta1.InterceptorParams{{
Name: "filter",
Value: test.ToV1JSON(t, "body.extensions.truncated_sha == \"abcde\" && extensions.truncated_sha == \"abcde\""),
diff --git a/test/controller.go b/test/controller.go
index b3e3cd15f..3f46a125e 100644
--- a/test/controller.go
+++ b/test/controller.go
@@ -32,6 +32,7 @@ import (
faketriggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned/fake"
faketriggersclient "github.com/tektoncd/triggers/pkg/client/injection/client/fake"
fakeClusterInterceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/clusterinterceptor/fake"
+ fakeInterceptorinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1alpha1/interceptor/fake"
fakeclustertriggerbindinginformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/clustertriggerbinding/fake"
fakeeventlistenerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/eventlistener/fake"
faketriggerinformer "github.com/tektoncd/triggers/pkg/client/injection/informers/triggers/v1beta1/trigger/fake"
@@ -75,6 +76,7 @@ type Resources struct {
ClusterTriggerBindings []*v1beta1.ClusterTriggerBinding
EventListeners []*v1beta1.EventListener
ClusterInterceptors []*v1alpha1.ClusterInterceptor
+ Interceptors []*v1alpha1.Interceptor
TriggerBindings []*v1beta1.TriggerBinding
TriggerTemplates []*v1beta1.TriggerTemplate
Triggers []*v1beta1.Trigger
@@ -139,6 +141,7 @@ func SeedResources(t *testing.T, ctx context.Context, r Resources) Clients {
ctbInformer := fakeclustertriggerbindinginformer.Get(ctx)
elInformer := fakeeventlistenerinformer.Get(ctx)
icInformer := fakeClusterInterceptorinformer.Get(ctx)
+ nsicInformer := fakeInterceptorinformer.Get(ctx)
ttInformer := faketriggertemplateinformer.Get(ctx)
tbInformer := faketriggerbindinginformer.Get(ctx)
trInformer := faketriggerinformer.Get(ctx)
@@ -180,6 +183,14 @@ func SeedResources(t *testing.T, ctx context.Context, r Resources) Clients {
t.Fatal(err)
}
}
+ for _, ic := range r.Interceptors {
+ if err := nsicInformer.Informer().GetIndexer().Add(ic); err != nil {
+ t.Fatal(err)
+ }
+ if _, err := c.Triggers.TriggersV1alpha1().Interceptors(ic.Namespace).Create(context.Background(), ic, metav1.CreateOptions{}); err != nil {
+ t.Fatal(err)
+ }
+ }
for _, tb := range r.TriggerBindings {
if err := tbInformer.Informer().GetIndexer().Add(tb); err != nil {
t.Fatal(err)
diff --git a/test/eventlistener_scale_test.go b/test/eventlistener_scale_test.go
index f4d717bff..8dc4da3cc 100644
--- a/test/eventlistener_scale_test.go
+++ b/test/eventlistener_scale_test.go
@@ -120,7 +120,7 @@ func createServiceAccount(t *testing.T, c *clients, namespace, name string) {
ObjectMeta: metav1.ObjectMeta{Name: "sa-role"},
Rules: []rbacv1.PolicyRule{{
APIGroups: []string{triggers.GroupName},
- Resources: []string{"eventlisteners", "triggerbindings", "triggertemplates", "triggers"},
+ Resources: []string{"eventlisteners", "interceptors", "triggerbindings", "triggertemplates", "triggers"},
Verbs: []string{"get", "list", "watch"},
}, {
APIGroups: []string{""},
diff --git a/test/eventlistener_test.go b/test/eventlistener_test.go
index c524a1d71..f974fadce 100644
--- a/test/eventlistener_test.go
+++ b/test/eventlistener_test.go
@@ -290,7 +290,7 @@ func TestEventListenerCreate(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{Name: "my-role"},
Rules: []rbacv1.PolicyRule{{
APIGroups: []string{triggers.GroupName},
- Resources: []string{"clustertriggerbindings", "eventlisteners", "clusterinterceptors", "triggerbindings", "triggertemplates", "triggers"},
+ Resources: []string{"clustertriggerbindings", "eventlisteners", "clusterinterceptors", "interceptors", "triggerbindings", "triggertemplates", "triggers"},
Verbs: []string{"get", "list", "watch"},
}, {
APIGroups: []string{"tekton.dev"},