From 036d9afb936d2a2bd2bbfa13e5e688583dfe6391 Mon Sep 17 00:00:00 2001 From: Florian Bauer Date: Thu, 20 Jul 2023 12:19:00 +0200 Subject: [PATCH 1/2] fix: use cloudevents sdk-go for cloudevent handling Signed-off-by: Florian Bauer --- go.mod | 3 +- go.sum | 22 ++++++- pkg/handlers/cloudevent/cloudevent.go | 90 ++++++++++----------------- 3 files changed, 52 insertions(+), 63 deletions(-) diff --git a/go.mod b/go.mod index af0ee280..66bfd174 100755 --- a/go.mod +++ b/go.mod @@ -3,13 +3,13 @@ module github.com/bitnami-labs/kubewatch go 1.14 require ( + github.com/cloudevents/sdk-go/v2 v2.14.0 github.com/fatih/structtag v1.2.0 github.com/google/go-querystring v0.0.0-20170111101155-53e6ce116135 // indirect github.com/hashicorp/hcl v0.0.0-20171017181929-23c074d0eceb // indirect github.com/inconshreveable/mousetrap v1.0.0 // indirect github.com/magiconair/properties v1.7.4 // indirect github.com/mkmik/multierror v0.3.0 - github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect github.com/pelletier/go-toml v1.0.1 // indirect github.com/segmentio/textio v1.2.0 github.com/sirupsen/logrus v1.6.0 @@ -20,7 +20,6 @@ require ( github.com/spf13/viper v1.0.0 github.com/tbruyelle/hipchat-go v0.0.0-20160921153256-749fb9e14beb golang.org/x/crypto v0.8.0 // indirect - gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect gopkg.in/yaml.v2 v2.3.0 // indirect gopkg.in/yaml.v3 v3.0.1 k8s.io/api v0.20.15 diff --git a/go.sum b/go.sum index adbbd5cb..ca7f7125 100755 --- a/go.sum +++ b/go.sum @@ -42,6 +42,9 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudevents/sdk-go/v2 v2.14.0 h1:Nrob4FwVgi5L4tV9lhjzZcjYqFVyJzsA56CwPaPfv6s= +github.com/cloudevents/sdk-go/v2 v2.14.0/go.mod h1:xDmKfzNjM8gBvjaF8ijFjM1VYOVUEeUfapHMUX1T5To= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -155,8 +158,9 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/magiconair/properties v1.7.4 h1:UVo0TkHGd4lQSN1dVDzs9URCIgReuSIcCXpAVB9nZ80= github.com/magiconair/properties v1.7.4/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= @@ -211,13 +215,18 @@ github.com/spf13/viper v1.0.0 h1:RUA/ghS2i64rlnn4ydTfblY8Og8QzcPtCcHvgMn+w/I= github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/tbruyelle/hipchat-go v0.0.0-20160921153256-749fb9e14beb h1:mb7xv0kx9XpGsLy5kCCa6+3HqSj495cEBQNMgljqZ48= github.com/tbruyelle/hipchat-go v0.0.0-20160921153256-749fb9e14beb/go.mod h1:CJEWrlDz1qHCF/nywogFd3AqHUWbKCdpu9pSAdf1OzY= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= @@ -225,6 +234,12 @@ go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= @@ -360,8 +375,9 @@ golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e h1:EHBhcS0mlXEAVwNyO2dLfjToGsyY4j24pTs2ScHnX7s= golang.org/x/time v0.0.0-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac h1:7zkz7BUtwNFFqcowJ+RIgu2MaV/MapERkDIy+mwPyjs= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= diff --git a/pkg/handlers/cloudevent/cloudevent.go b/pkg/handlers/cloudevent/cloudevent.go index f05dd06b..f64869e9 100644 --- a/pkg/handlers/cloudevent/cloudevent.go +++ b/pkg/handlers/cloudevent/cloudevent.go @@ -17,17 +17,15 @@ limitations under the License. package cloudevent import ( + "context" "fmt" - "github.com/sirupsen/logrus" "os" - - "bytes" - "encoding/json" - "net/http" "time" "github.com/bitnami-labs/kubewatch/config" "github.com/bitnami-labs/kubewatch/pkg/event" + cloudevents "github.com/cloudevents/sdk-go/v2" + "github.com/sirupsen/logrus" "k8s.io/apimachinery/pkg/runtime" ) @@ -49,17 +47,8 @@ type CloudEvent struct { Url string StartTime uint64 Counter uint64 -} -type CloudEventMessage struct { - SpecVersion string `json:"specversion"` - Type string `json:"type"` - Source string `json:"source"` - Subject string `json:"subject"` - ID string `json:"id"` - Time time.Time `json:"time"` - DataContentType string `json:"datacontenttype"` - Data CloudEventMessageData `json:"data"` + cloudeventsClient cloudevents.Client } // EventMeta containes the meta data about the event occurred @@ -86,39 +75,46 @@ func (m *CloudEvent) Init(c *config.Config) error { return fmt.Errorf(cloudEventErrMsg, "Missing cloudevent url") } + var err error + m.cloudeventsClient, err = cloudevents.NewClientHTTP() + if err != nil { + return fmt.Errorf("failed to create client, %v", err) + } + return nil } func (m *CloudEvent) Handle(e event.Event) { m.Counter++ // TODO: do we have to worry about threadsafety here? - message := m.prepareMessage(e) - err := m.postMessage(message) - if err != nil { - logrus.Printf("%s\n", err) + event := cloudevents.NewEvent() + event.SetSource("https://github.com/robusta-dev/kubewatch") + event.SetType("KUBERNETES_TOPOLOGY_CHANGE") + event.SetTime(time.Now()) + event.SetID(fmt.Sprintf("%v-%v", m.StartTime, m.Counter)) + if dataAssignmentError := event.SetData(cloudevents.ApplicationJSON, m.prepareMessage(e)); dataAssignmentError != nil { + logrus.Printf("Failed to set data: %v", dataAssignmentError) + return + } + + result := m.cloudeventsClient.Send(cloudevents.ContextWithTarget(context.Background(), m.Url), event) + if result != nil && cloudevents.IsUndelivered(result) { + logrus.Printf("Failed to send: %v", result) return } logrus.Printf("Message successfully sent to %s at %s ", m.Url, time.Now()) } -func (m *CloudEvent) prepareMessage(e event.Event) *CloudEventMessage { - return &CloudEventMessage{ - SpecVersion: "1.0", - Type: "KUBERNETES_TOPOLOGY_CHANGE", - Source: "https://github.com/aantn/kubewatch", - ID: fmt.Sprintf("%v-%v", m.StartTime, m.Counter), - Time: time.Now(), // TODO: verify that time format is correct - note that this is the time of sending not time of event - DataContentType: "application/json", - Data: CloudEventMessageData{ - Operation: m.formatReason(e), - Kind: e.Kind, - ApiVersion: e.ApiVersion, - ClusterUid: "TODO", - Description: e.Message(), - Obj: e.Obj, - OldObj: e.OldObj, - }, +func (m *CloudEvent) prepareMessage(e event.Event) *CloudEventMessageData { + return &CloudEventMessageData{ + Operation: m.formatReason(e), + Kind: e.Kind, + ApiVersion: e.ApiVersion, + ClusterUid: "TODO", + Description: e.Message(), + Obj: e.Obj, + OldObj: e.OldObj, } } @@ -134,25 +130,3 @@ func (m *CloudEvent) formatReason(e event.Event) string { return "unknown" } } - -func (m *CloudEvent) postMessage(webhookMessage *CloudEventMessage) error { - message, err := json.Marshal(webhookMessage) - if err != nil { - return err - } - - req, err := http.NewRequest("POST", m.Url, bytes.NewBuffer(message)) - if err != nil { - return err - } - req.Header.Add("Content-Type", "application/json") - - client := &http.Client{} - resp, err := client.Do(req) - if err != nil { - return err - } - defer resp.Body.Close() - - return nil -} From 0235ce3a42e75b0acf4af6d8b4164aafedd2f957 Mon Sep 17 00:00:00 2001 From: Florian Bauer Date: Fri, 21 Jul 2023 17:14:02 +0200 Subject: [PATCH 2/2] fix: adjust error handling on failed message submission Signed-off-by: Florian Bauer --- pkg/handlers/cloudevent/cloudevent.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/handlers/cloudevent/cloudevent.go b/pkg/handlers/cloudevent/cloudevent.go index f64869e9..7eaa06ed 100644 --- a/pkg/handlers/cloudevent/cloudevent.go +++ b/pkg/handlers/cloudevent/cloudevent.go @@ -98,7 +98,7 @@ func (m *CloudEvent) Handle(e event.Event) { } result := m.cloudeventsClient.Send(cloudevents.ContextWithTarget(context.Background(), m.Url), event) - if result != nil && cloudevents.IsUndelivered(result) { + if cloudevents.IsNACK(result) || cloudevents.IsUndelivered(result) { logrus.Printf("Failed to send: %v", result) return }