Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Add interceptor to processTriggerSpec, update readHTTP and trigger function #695

Merged
merged 1 commit into from
Aug 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions cmd/triggerRun/testdata/http.txt

This file was deleted.

10 changes: 0 additions & 10 deletions cmd/triggerRun/testdata/trigger.yaml

This file was deleted.

107 changes: 77 additions & 30 deletions cmd/triggerRun/cmd/root.go → cmd/triggerrun/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ package cmd

import (
"bufio"
"bytes"
"encoding/json"
"errors"
"fmt"
Expand All @@ -30,11 +31,15 @@ import (
"github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
triggersv1 "github.com/tektoncd/triggers/pkg/apis/triggers/v1alpha1"
triggersclientset "github.com/tektoncd/triggers/pkg/client/clientset/versioned"
"github.com/tektoncd/triggers/pkg/sink"
"github.com/tektoncd/triggers/pkg/template"
"go.uber.org/zap"
"k8s.io/apimachinery/pkg/runtime/serializer/streaming"

"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/yaml"
)

var (
Expand All @@ -43,7 +48,7 @@ var (
Use: "triggers-run",
Short: "This is the CLI for tekton trigger.",
Long: "tkn-trigger will allow users easily test out the Trigger config.",
Run: rootRun,
RunE: rootRun,
}

triggerFile string
Expand All @@ -56,23 +61,20 @@ func init() {
rootCmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "k", "", "absolute path to the kubeconfig file")
}

func rootRun(cmd *cobra.Command, args []string) {
func rootRun(cmd *cobra.Command, args []string) error {
err := trigger(triggerFile, httpPath)
if err != nil {
fmt.Printf("fail to call trigger: %v", err)
return fmt.Errorf("fail to call trigger: %v", err)
}

return nil
}

func trigger(triggerFile, httpPath string) error {
// Read HTTP request.
r, err := readHTTP(httpPath)
if err != nil {
return fmt.Errorf("error reading HTTP file: %w", err)
}
defer r.Body.Close()
body, err := ioutil.ReadAll(r.Body)
request, body, err := readHTTP(httpPath)
if err != nil {
return fmt.Errorf("error reading HTTP body: %w", err)
return fmt.Errorf("error reading HTTP txt file: %w", err)
}

// Read triggers.
Expand All @@ -81,23 +83,29 @@ func trigger(triggerFile, httpPath string) error {
return fmt.Errorf("error reading triggers: %w", err)
}

client, err := getKubeClient(kubeconfig)
kubeClient, triggerClient, err := getKubeClient(kubeconfig)
if err != nil {
return fmt.Errorf("fail to get Kubenetes client: %w", err)
return fmt.Errorf("fail to get clients: %w", err)
}

logger, _ := zap.NewProduction()
sugerLogger := logger.Sugar()
eventID := template.UID()
for _, tri := range triggers {
eventLog := sugerLogger.With(zap.String(triggersv1.EventIDLabelKey, eventID))
resources, err := processTriggerSpec(client, tri,
r, body, eventID, eventLog)
resources, err := processTriggerSpec(kubeClient, triggerClient, tri,
request, body, eventID, eventLog)
if err != nil {
return fmt.Errorf("fail to build config from the flags: %w", err)
return fmt.Errorf("fail to create resources: %w", err)
}
for resource := range resources {
fmt.Print(resource)

for _, resource := range resources {
s, err := yaml.Marshal(resource)
if err != nil {
return fmt.Errorf("fail to print out the resource: %w", err)
}
fmt.Println("-----------------------------------")
fmt.Printf("%s", s)
}
}

Expand Down Expand Up @@ -131,55 +139,94 @@ func readTrigger(path string) ([]*v1alpha1.Trigger, error) {
return list, nil
}

func readHTTP(path string) (*http.Request, error) {
func readHTTP(path string) (*http.Request, []byte, error) {
f, err := os.Open(path)

if err != nil {
return nil, fmt.Errorf("error opening file: %w", err)
return nil, nil, fmt.Errorf("error opening file: %w", err)
}
defer f.Close()

return http.ReadRequest(bufio.NewReader(f))
request, err := http.ReadRequest(bufio.NewReader(f))
if err != nil {
return nil, nil, fmt.Errorf("error reading HTTP file: %w", err)
}

body, err := ioutil.ReadAll(request.Body)
defer request.Body.Close()
if err != nil {
return nil, nil, fmt.Errorf("error reading HTTP body: %w", err)
}

request.Body = ioutil.NopCloser(bytes.NewReader(body))

return request, body, err
}

func getKubeClient(kubeconfig string) (triggersclientset.Interface, error) {
func getKubeClient(kubeconfig string) (kubernetes.Interface, triggersclientset.Interface, error) {
// use the current context in kubeconfig
config, err := clientcmd.BuildConfigFromFlags("", kubeconfig)
if err != nil {
return nil, fmt.Errorf("fail to build config from the flags: %w", err)
return nil, nil, fmt.Errorf("Failed to build config from the flags: %w", err)
}

kubeClient, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, nil, fmt.Errorf("Failed to get the Kubernetes client set: %v", err)
}

return triggersclientset.NewForConfig(config)
client, err := triggersclientset.NewForConfig(config)
if err != nil {
return nil, nil, fmt.Errorf("Failed to get the trigger client set: %v", err)
}

return kubeClient, client, nil
}

func processTriggerSpec(client triggersclientset.Interface, tri *triggersv1.Trigger, request *http.Request, event []byte, eventID string, eventLog *zap.SugaredLogger) ([]json.RawMessage, error) {
func processTriggerSpec(kubeClient kubernetes.Interface, client triggersclientset.Interface, tri *triggersv1.Trigger, request *http.Request, body []byte, eventID string, eventLog *zap.SugaredLogger) ([]json.RawMessage, error) {
if tri == nil {
return nil, errors.New("Trigger is not defined")
return nil, errors.New("trigger is not defined")
}

//convert trigger to eventListener
el, err := triggersv1.ToEventListenerTrigger(tri.Spec)
if err != nil {
return nil, fmt.Errorf("fail to convert Trigger to EvenetListener: %w", err)
}

log := eventLog.With(zap.String(triggersv1.TriggerLabelKey, el.Name))

r := sink.Sink{
KubeClientSet: kubeClient,
HTTPClient: http.DefaultClient,
Auth: sink.DefaultAuthOverride{},
}

finalPayload, header, err := r.ExecuteInterceptors(&el, request, body, log)
if err != nil {
log.Error(err)
return nil, err
}

if tri.Namespace == "" {
tri.Namespace = "default"
}

rt, err := template.ResolveTrigger(el,
client.TriggersV1alpha1().TriggerBindings(tri.Namespace).Get,
client.TriggersV1alpha1().ClusterTriggerBindings().Get,
client.TriggersV1alpha1().TriggerTemplates(tri.Namespace).Get)
if err != nil {
log.Error(err)
log.Error("Failed to resolve Trigger", err)
return nil, err
}

params, err := template.ResolveParams(rt, event, request.Header)
params, err := template.ResolveParams(rt, finalPayload, header)
if err != nil {
log.Error(err)
log.Error("Failed to resolve parameters", err)
return nil, err
}

log.Infof("ResolvedParams : %+v", params)

resources := template.ResolveResources(rt.TriggerTemplate, params)

return resources, nil
Expand Down
37 changes: 22 additions & 15 deletions cmd/triggerRun/cmd/root_test.go → cmd/triggerrun/cmd/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import (
"go.uber.org/zap"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/kubernetes"
rtesting "knative.dev/pkg/reconciler/testing"
)

Expand All @@ -45,19 +46,18 @@ func TestReadTrigger(t *testing.T) {

want := []*v1alpha1.Trigger{{
TypeMeta: metav1.TypeMeta{
APIVersion: "tekton.dev/v1alpha1",
APIVersion: "triggers.tekton.dev/v1alpha1",
Kind: "Trigger",
},
ObjectMeta: metav1.ObjectMeta{
Name: "trigger-run",
},
Spec: v1alpha1.TriggerSpec{
Bindings: []*v1alpha1.TriggerSpecBinding{
{Name: "triggerSpecBinding1"},
{Name: "triggerSpecBinding2"},
{Ref: "git-event-binding"},
},
Template: v1alpha1.TriggerSpecTemplate{
Name: "triggerSpecTemplate",
Name: "simple-pipeline-template",
},
},
}}
Expand All @@ -69,7 +69,7 @@ func TestReadTrigger(t *testing.T) {
}

func TestReadHTTP(t *testing.T) {
req, err := readHTTP("../testdata/http.txt")
req, _, err := readHTTP("../testdata/http.txt")
if err != nil {
t.Fatalf("failed to read HTTP: %v", err)
}
Expand All @@ -78,16 +78,23 @@ func TestReadHTTP(t *testing.T) {
if err != nil {
t.Fatalf("failed to read HTTP: %v", err)
}

outStr := string(out)
re := regexp.MustCompile(`\r?\n`)
outStr = re.ReplaceAllString(outStr, "\n")

expect := `POST /foo HTTP/1.1
Content-Length: 16
Content-Length: 135
Content-Type: application/json
X-Gitlab-Event: Push Hook
X-Header: testheader

{"test": "body"}`
{
"checkout_sha": "1a1736ec3d7b03349b31218a2f2c572c7c7206d6",
"repository": {
"url": "git@gitlab.com:dibyom/triggers.git"
}
}`

if diff := cmp.Diff(expect, outStr); diff != "" {
t.Errorf("-want +got: %s", diff)
Expand Down Expand Up @@ -131,7 +138,7 @@ func Test_processTriggerSpec(t *testing.T) {

triggerTemplate := triggersv1.TriggerTemplate{
ObjectMeta: metav1.ObjectMeta{
Name: "triggerSpecTemplate",
Name: "simple-pipeline-template",
Namespace: "default",
},
Spec: triggersv1.TriggerTemplateSpec{
Expand All @@ -146,7 +153,7 @@ func Test_processTriggerSpec(t *testing.T) {

triggerBinding := v1alpha1.TriggerBinding{
ObjectMeta: metav1.ObjectMeta{
Name: "triggerSpecBinding1",
Name: "git-event-binding",
Namespace: "default",
},
Spec: triggersv1.TriggerBindingSpec{
Expand Down Expand Up @@ -196,10 +203,10 @@ func Test_processTriggerSpec(t *testing.T) {
},
Spec: v1alpha1.TriggerSpec{
Bindings: []*v1alpha1.TriggerSpecBinding{
{Name: "triggerSpecBinding1"}, // These should be references to TriggerBindings defined below
{Name: "git-event-binding"}, // These should be references to TriggerBindings defined below
},
Template: v1alpha1.TriggerSpecTemplate{
Name: "triggerSpecTemplate", // This should be a reference to a TriggerTemplate defined below
Name: "simple-pipeline-template", // This should be a reference to a TriggerTemplate defined below
},
},
},
Expand All @@ -221,8 +228,8 @@ func Test_processTriggerSpec(t *testing.T) {
eventID := "some-id"
logger, _ := zap.NewProduction()
eventLog := logger.Sugar()
client := getFakeTriggersClient(t, tt.args.resources)
got, err := processTriggerSpec(client, tt.args.t, tt.args.request, tt.args.event, eventID, eventLog)
kubeClient, triggerClient := getFakeTriggersClient(t, tt.args.resources)
got, err := processTriggerSpec(kubeClient, triggerClient, tt.args.t, tt.args.request, tt.args.event, eventID, eventLog)
if (err != nil) != tt.wantErr {
t.Errorf("processTriggerSpec() error = %v. wantErr %v", err, tt.wantErr)
return
Expand All @@ -234,9 +241,9 @@ func Test_processTriggerSpec(t *testing.T) {
}
}

func getFakeTriggersClient(t *testing.T, resources test.Resources) triggersclientset.Interface {
func getFakeTriggersClient(t *testing.T, resources test.Resources) (kubernetes.Interface, triggersclientset.Interface) {
t.Helper()
ctx, _ := rtesting.SetupFakeContext(t)
clients := test.SeedResources(t, ctx, resources)
return clients.Triggers
return clients.Kube, clients.Triggers
}
3 changes: 2 additions & 1 deletion cmd/triggerRun/main.go → cmd/triggerrun/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ import (
"fmt"
"os"

"github.com/tektoncd/triggers/cmd/triggerRun/cmd"
"github.com/tektoncd/triggers/cmd/triggerrun/cmd"
_ "k8s.io/client-go/plugin/pkg/client/auth"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
_ "k8s.io/client-go/plugin/pkg/client/auth"

Can we remove this import as its not used

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We actually need this one. Its contains auth plugins needed to setup the kubeclients for various k8s providers. See https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go#L33

e.g. https://github.com/kubernetes/client-go/blob/master/examples/out-of-cluster-client-configuration/main.go#L33

It is an interesting pattern, I'll admit 😛

)

func main() {
Expand Down
12 changes: 12 additions & 0 deletions cmd/triggerrun/testdata/http.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
POST /foo HTTP/1.1
Content-Length: 135
Content-Type: application/json
X-Header: testheader
X-Gitlab-Event: Push Hook

{
"checkout_sha": "1a1736ec3d7b03349b31218a2f2c572c7c7206d6",
"repository": {
"url": "git@gitlab.com:dibyom/triggers.git"
}
}
9 changes: 9 additions & 0 deletions cmd/triggerrun/testdata/trigger.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
apiVersion: triggers.tekton.dev/v1alpha1
kind: Trigger
metadata:
name: trigger-run
spec:
bindings:
- ref: git-event-binding
template:
name: simple-pipeline-template
11 changes: 11 additions & 0 deletions cmd/triggerrun/testdata/triggerbinding.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
apiVersion: triggers.tekton.dev/v1alpha1
kind: TriggerBinding
metadata:
name: git-event-binding
spec:
params:
- name: gitrevision
value: $(body.checkout_sha)
- name: gitrepositoryurl
value: $(body.repository.url)
Loading