From eaec0ff070d577661a41620d5b845b5296d66ddf Mon Sep 17 00:00:00 2001 From: vpage Date: Tue, 19 Mar 2019 12:42:44 -0400 Subject: [PATCH 01/11] refactor(): webhook route config --- gateways/common/fake.go | 27 +++- gateways/common/webhook.go | 136 +++++++++++-------- gateways/common/webhook_test.go | 10 +- gateways/community/aws-sns/config.go | 25 +++- gateways/community/aws-sns/config_test.go | 2 +- gateways/community/aws-sns/start.go | 85 ++++++------ gateways/community/aws-sns/start_test.go | 47 +++---- gateways/community/aws-sns/validate.go | 2 +- gateways/community/aws-sqs/config.go | 6 +- gateways/community/aws-sqs/config_test.go | 4 +- gateways/community/aws-sqs/start.go | 4 +- gateways/community/aws-sqs/start_test.go | 2 +- gateways/community/aws-sqs/validate.go | 2 +- gateways/community/aws-sqs/validate_test.go | 4 +- gateways/community/gcp-pubsub/config.go | 6 +- gateways/community/gcp-pubsub/config_test.go | 2 +- gateways/community/gcp-pubsub/start.go | 4 +- gateways/community/gcp-pubsub/start_test.go | 2 +- gateways/community/gcp-pubsub/validate.go | 2 +- gateways/community/github/start_test.go | 2 +- gateways/community/gitlab/start_test.go | 2 +- gateways/community/slack/start.go | 2 +- gateways/community/slack/start_test.go | 2 +- gateways/community/storagegrid/start_test.go | 2 +- gateways/community/trello/start_test.go | 2 +- gateways/core/webhook/config.go | 5 + gateways/core/webhook/start.go | 49 ++++--- gateways/core/webhook/start_test.go | 25 ++-- 28 files changed, 270 insertions(+), 193 deletions(-) diff --git a/gateways/common/fake.go b/gateways/common/fake.go index e57811ec3a..a4f5451544 100644 --- a/gateways/common/fake.go +++ b/gateways/common/fake.go @@ -32,16 +32,35 @@ func (f *FakeHttpWriter) WriteHeader(status int) { f.HeaderStatus = status } -func GetFakeRouteConfig() *RouteConfig { - return &RouteConfig{ +type FakeRouteConfig struct { + Route *Route +} + +func (f *FakeRouteConfig) GetRoute() *Route { + return f.Route +} + +func (f *FakeRouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { +} + +func (f *FakeRouteConfig) PostStart() error { + return nil +} + +func (f *FakeRouteConfig) PostStop() error { + return nil +} + +func GetFakeRoute() *Route { + logger := common.GetLoggerContext(common.LoggerConf()).Logger() + return &Route{ Webhook: Hook, EventSource: &gateways.EventSource{ Name: "fake-event-source", Data: "hello", Id: "123", }, - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), - Configs: make(map[string]interface{}), + Logger: &logger, StartCh: make(chan struct{}), } } diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index b8f7578fcc..031c14675c 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -57,9 +57,9 @@ type WebhookHelper struct { // ActiveEndpoints keep track of endpoints that are already registered with server and their status active or inactive ActiveEndpoints map[string]*Endpoint // RouteActivateChan handles assigning new route to server. - RouteActivateChan chan *RouteConfig + RouteActivateChan chan RouteConfig // RouteDeactivateChan handles deactivating existing route - RouteDeactivateChan chan *RouteConfig + RouteDeactivateChan chan RouteConfig } // HTTP Muxer @@ -73,16 +73,20 @@ type activeServer struct { errChan chan error } -// RouteConfig contains configuration about an http route -type RouteConfig struct { - Webhook *Webhook - Configs map[string]interface{} - EventSource *gateways.EventSource - Log zerolog.Logger - StartCh chan struct{} - RouteActiveHandler func(writer http.ResponseWriter, request *http.Request, rc *RouteConfig) - PostActivate func(rc *RouteConfig) error - PostStop func(rc *RouteConfig) error +// Route contains common information for a route +type Route struct { + Webhook *Webhook + Logger *zerolog.Logger + StartCh chan struct{} + EventSource *gateways.EventSource +} + +// RouteConfig is an interface to manage the configuration for a route +type RouteConfig interface { + GetRoute() *Route + RouteHandler(writer http.ResponseWriter, request *http.Request) + PostStart() error + PostStop() error } // endpoint contains state of an http endpoint @@ -93,14 +97,14 @@ type Endpoint struct { DataCh chan []byte } -// NewWebhookHelper returns new webhook helper +// NewWebhookHelper returns new r.Webhook helper func NewWebhookHelper() *WebhookHelper { return &WebhookHelper{ ActiveEndpoints: make(map[string]*Endpoint), ActiveServers: make(map[string]*activeServer), Mutex: sync.Mutex{}, - RouteActivateChan: make(chan *RouteConfig), - RouteDeactivateChan: make(chan *RouteConfig), + RouteActivateChan: make(chan RouteConfig), + RouteDeactivateChan: make(chan RouteConfig), } } @@ -110,11 +114,12 @@ func InitRouteChannels(helper *WebhookHelper) { select { case config := <-helper.RouteActivateChan: // start server if it has not been started on this port - config.startHttpServer(helper) - config.StartCh <- struct{}{} + startHttpServer(config, helper) + startCh := config.GetRoute().StartCh + startCh <- struct{}{} case config := <-helper.RouteDeactivateChan: - webhook := config.Webhook + webhook := config.GetRoute().Webhook _, ok := helper.ActiveServers[webhook.Port] if ok { helper.ActiveEndpoints[webhook.Endpoint].Active = false @@ -129,20 +134,21 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // starts a http server -func (rc *RouteConfig) startHttpServer(helper *WebhookHelper) { +func startHttpServer(rc RouteConfig, helper *WebhookHelper) { // start a http server only if no other configuration previously started the server on given port helper.Mutex.Lock() - if _, ok := helper.ActiveServers[rc.Webhook.Port]; !ok { + r := rc.GetRoute() + if _, ok := helper.ActiveServers[r.Webhook.Port]; !ok { s := &server{ mux: http.NewServeMux(), } - rc.Webhook.mux = s.mux - rc.Webhook.srv = &http.Server{ - Addr: ":" + fmt.Sprintf("%s", rc.Webhook.Port), + r.Webhook.mux = s.mux + r.Webhook.srv = &http.Server{ + Addr: ":" + fmt.Sprintf("%s", r.Webhook.Port), Handler: s, } errChan := make(chan error, 1) - helper.ActiveServers[rc.Webhook.Port] = &activeServer{ + helper.ActiveServers[r.Webhook.Port] = &activeServer{ srv: s.mux, errChan: errChan, } @@ -150,12 +156,12 @@ func (rc *RouteConfig) startHttpServer(helper *WebhookHelper) { // start http server go func() { var err error - if rc.Webhook.ServerCertPath == "" || rc.Webhook.ServerKeyPath == "" { - err = rc.Webhook.srv.ListenAndServe() + if r.Webhook.ServerCertPath == "" || r.Webhook.ServerKeyPath == "" { + err = r.Webhook.srv.ListenAndServe() } else { - err = rc.Webhook.srv.ListenAndServeTLS(rc.Webhook.ServerCertPath, rc.Webhook.ServerKeyPath) + err = r.Webhook.srv.ListenAndServeTLS(r.Webhook.ServerCertPath, r.Webhook.ServerKeyPath) } - rc.Log.Error().Err(err).Str("event-source", rc.EventSource.Name).Str("port", rc.Webhook.Port).Msg("http server stopped") + r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Str("port", r.Webhook.Port).Msg("http server stopped") if err != nil { errChan <- err } @@ -165,53 +171,54 @@ func (rc *RouteConfig) startHttpServer(helper *WebhookHelper) { } // activateRoute activates route -func (rc *RouteConfig) activateRoute(helper *WebhookHelper) { +func activateRoute(rc RouteConfig, helper *WebhookHelper) { + r := rc.GetRoute() helper.RouteActivateChan <- rc - <-rc.StartCh + <-r.StartCh - if rc.Webhook.mux == nil { + if r.Webhook.mux == nil { helper.Mutex.Lock() - rc.Webhook.mux = helper.ActiveServers[rc.Webhook.Port].srv + r.Webhook.mux = helper.ActiveServers[r.Webhook.Port].srv helper.Mutex.Unlock() } - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Str("port", rc.Webhook.Port).Str("endpoint", rc.Webhook.Endpoint).Msg("adding route handler") - if _, ok := helper.ActiveEndpoints[rc.Webhook.Endpoint]; !ok { - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &Endpoint{ + r.Logger.Info().Str("event-source-name", r.EventSource.Name).Str("port", r.Webhook.Port).Str("endpoint", r.Webhook.Endpoint).Msg("adding route handler") + if _, ok := helper.ActiveEndpoints[r.Webhook.Endpoint]; !ok { + helper.ActiveEndpoints[r.Webhook.Endpoint] = &Endpoint{ Active: true, DataCh: make(chan []byte), } - rc.Webhook.mux.HandleFunc(rc.Webhook.Endpoint, func(writer http.ResponseWriter, request *http.Request) { - rc.RouteActiveHandler(writer, request, rc) - }) + r.Webhook.mux.HandleFunc(r.Webhook.Endpoint, rc.RouteHandler) } - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true + helper.ActiveEndpoints[r.Webhook.Endpoint].Active = true - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Str("port", rc.Webhook.Port).Str("endpoint", rc.Webhook.Endpoint).Msg("route handler added") + r.Logger.Info().Str("event-source-name", r.EventSource.Name).Str("port", r.Webhook.Port).Str("endpoint", r.Webhook.Endpoint).Msg("route handler added") } -func (rc *RouteConfig) processChannels(helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { +func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { + r := rc.GetRoute() + for { select { - case data := <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh: - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Msg("new event received, dispatching to gateway client") + case data := <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh: + r.Logger.Info().Str("event-source-name", r.EventSource.Name).Msg("new event received, dispatching to gateway client") err := eventStream.Send(&gateways.Event{ - Name: rc.EventSource.Name, + Name: r.EventSource.Name, Payload: data, }) if err != nil { - rc.Log.Error().Err(err).Str("event-source-name", rc.EventSource.Name).Msg("failed to send event") + r.Logger.Error().Err(err).Str("event-source-name", r.EventSource.Name).Msg("failed to send event") return err } case <-eventStream.Context().Done(): - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Msg("connection is closed by client") + r.Logger.Info().Str("event-source-name", r.EventSource.Name).Msg("connection is closed by client") helper.RouteDeactivateChan <- rc return nil // this error indicates that the server has stopped running - case err := <-helper.ActiveServers[rc.Webhook.Port].errChan: + case err := <-helper.ActiveServers[r.Webhook.Port].errChan: return err } } @@ -225,16 +232,19 @@ func DefaultPostStop(rc *RouteConfig) error { return nil } -func ProcessRoute(rc *RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { - rc.activateRoute(helper) - if err := rc.PostActivate(rc); err != nil { +func ProcessRoute(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { + if err := validateRouteConfig(rc); err != nil { return err } - if err := rc.processChannels(helper, eventStream); err != nil { + activateRoute(rc, helper) + if err := rc.PostStart(); err != nil { return err } - if err := rc.PostStop(rc); err != nil { - rc.Log.Error().Err(err).Msg("error occurred while executing post stop logic") + if err := processChannels(rc, helper, eventStream); err != nil { + return err + } + if err := rc.PostStop(); err != nil { + rc.GetRoute().Logger.Error().Err(err).Msg("error occurred while executing post stop logic") } return nil } @@ -258,6 +268,26 @@ func ValidateWebhook(w *Webhook) error { return nil } +func validateRouteConfig(rc RouteConfig) error { + r := rc.GetRoute() + if r == nil { + return fmt.Errorf("route can't be nil") + } + if r.Webhook == nil { + return fmt.Errorf("webhook can't be nil") + } + if r.StartCh == nil { + return fmt.Errorf("start channel can't be nil") + } + if r.EventSource == nil { + return fmt.Errorf("event source can't be nil") + } + if r.Logger == nil { + return fmt.Errorf("logger can't be nil") + } + return nil +} + func FormatWebhookEndpoint(endpoint string) string { if !strings.HasPrefix(endpoint, "/") { return fmt.Sprintf("/%s", endpoint) diff --git a/gateways/common/webhook_test.go b/gateways/common/webhook_test.go index d0c79c0b3a..f5ce248b55 100644 --- a/gateways/common/webhook_test.go +++ b/gateways/common/webhook_test.go @@ -28,7 +28,7 @@ import ( func TestDefaultPostActivate(t *testing.T) { convey.Convey("Given a route configuration, default post activate should be a no-op", t, func() { - rc := GetFakeRouteConfig() + rc := GetFakeRoute() err := DefaultPostActivate(rc) convey.So(err, convey.ShouldBeNil) }) @@ -36,7 +36,7 @@ func TestDefaultPostActivate(t *testing.T) { func TestDefaultPostStop(t *testing.T) { convey.Convey("Given a route configuration, default post stop should be a no-op", t, func() { - rc := GetFakeRouteConfig() + rc := GetFakeRoute() err := DefaultPostStop(rc) convey.So(err, convey.ShouldBeNil) }) @@ -45,7 +45,7 @@ func TestDefaultPostStop(t *testing.T) { func TestProcessRoute(t *testing.T) { convey.Convey("Given a route configuration", t, func() { convey.Convey("Activate the route configuration", func() { - rc := GetFakeRouteConfig() + rc := GetFakeRoute() rc.Webhook.mux = http.NewServeMux() rc.PostActivate = DefaultPostActivate @@ -93,7 +93,7 @@ func TestProcessRoute(t *testing.T) { func TestProcessRouteChannels(t *testing.T) { convey.Convey("Given a route configuration", t, func() { convey.Convey("Stop server stream", func() { - rc := GetFakeRouteConfig() + rc := GetFakeRoute() ctx, cancel := context.WithCancel(context.Background()) fgs := &FakeGRPCStream{ Ctx: ctx, @@ -117,7 +117,7 @@ func TestProcessRouteChannels(t *testing.T) { convey.So(err, convey.ShouldBeNil) }) convey.Convey("Handle error", func() { - rc := GetFakeRouteConfig() + rc := GetFakeRoute() fgs := &FakeGRPCStream{ Ctx: context.Background(), } diff --git a/gateways/community/aws-sns/config.go b/gateways/community/aws-sns/config.go index 64c2832336..be6241abb7 100644 --- a/gateways/community/aws-sns/config.go +++ b/gateways/community/aws-sns/config.go @@ -20,11 +20,12 @@ import ( "time" "github.com/argoproj/argo-events/gateways/common" - "k8s.io/client-go/kubernetes" - + gwcommon "github.com/argoproj/argo-events/gateways/common" + snslib "github.com/aws/aws-sdk-go/service/sns" "github.com/ghodss/yaml" "github.com/rs/zerolog" corev1 "k8s.io/api/core/v1" + "k8s.io/client-go/kubernetes" ) const ( @@ -45,6 +46,16 @@ type SNSEventSourceExecutor struct { Namespace string } +// RouteConfig contains information for a route +type RouteConfig struct { + Route *gwcommon.Route + snses *snsEventSource + session *snslib.SNS + subscriptionArn *string + clientset kubernetes.Interface + namespace string +} + // Json http notifications // SNS posts those to your http url endpoint if http is selected as delivery method. // http://docs.aws.amazon.com/sns/latest/dg/json-formats.html#http-subscription-confirmation-json @@ -65,8 +76,8 @@ type httpNotification struct { UnsubscribeURL string `json:"UnsubscribeURL,omitempty"` // Only for notifications } -// snsConfig contains configuration to subscribe to SNS topic -type snsConfig struct { +// snses contains configuration to subscribe to SNS topic +type snsEventSource struct { // Hook defines a webhook. Hook *common.Webhook `json:"hook"` TopicArn string `json:"topicArn"` @@ -76,10 +87,10 @@ type snsConfig struct { } func parseEventSource(es string) (interface{}, error) { - var n *snsConfig - err := yaml.Unmarshal([]byte(es), &n) + var ses *snsEventSource + err := yaml.Unmarshal([]byte(es), &ses) if err != nil { return nil, err } - return n, nil + return ses, nil } diff --git a/gateways/community/aws-sns/config_test.go b/gateways/community/aws-sns/config_test.go index e1c07c570f..22a39fe169 100644 --- a/gateways/community/aws-sns/config_test.go +++ b/gateways/community/aws-sns/config_test.go @@ -41,7 +41,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*snsConfig) + _, ok := ps.(*snsEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/aws-sns/start.go b/gateways/community/aws-sns/start.go index 7d1723e69b..781996fb0e 100644 --- a/gateways/community/aws-sns/start.go +++ b/gateways/community/aws-sns/start.go @@ -28,12 +28,6 @@ import ( "github.com/ghodss/yaml" ) -const ( - labelSNSConfig = "snsConfig" - labelSNSSession = "snsSession" - labelSubscriptionArn = "subscriptionArn" -) - var ( helper = gwcommon.NewWebhookHelper() ) @@ -42,17 +36,22 @@ func init() { go gwcommon.InitRouteChannels(helper) } -// RouteActiveHandler handles new routes -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.Route +} + +// RouteHandler handles new routes +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { var response string - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). + r := rc.Route + logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port). Str("http-method", request.Method).Logger() logger.Info().Msg("request received") - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { + response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", r.Webhook.Endpoint, r.Webhook.Method) logger.Info().Msg("endpoint is not active") common.SendErrorResponse(writer, response) return @@ -68,16 +67,16 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g var snspayload *httpNotification err = yaml.Unmarshal(body, &snspayload) if err != nil { - logger.Error().Err(err).Msg("failed to convert request payload into snsConfig payload") + logger.Error().Err(err).Msg("failed to convert request payload into snses payload") common.SendErrorResponse(writer, "failed to marshal request") return } - sc := rc.Configs[labelSNSConfig].(*snsConfig) + sc := rc.snses switch snspayload.Type { case messageTypeSubscriptionConfirmation: - awsSession := rc.Configs[labelSNSSession].(*snslib.SNS) + awsSession := rc.session out, err := awsSession.ConfirmSubscription(&snslib.ConfirmSubscriptionInput{ TopicArn: &sc.TopicArn, Token: &snspayload.Token, @@ -87,10 +86,10 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g common.SendErrorResponse(writer, "failed to confirm subscription") return } - rc.Configs[labelSubscriptionArn] = out.SubscriptionArn + rc.subscriptionArn = out.SubscriptionArn case messageTypeNotification: - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- body + helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body } response = "request successfully processed" @@ -98,14 +97,14 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g common.SendSuccessResponse(writer, response) } -// PostActivate subscribes to the sns topic -func (ese *SNSEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error { - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port).Logger() +// PostStart subscribes to the sns topic +func (rc *RouteConfig) PostStart() error { + r := rc.Route + logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port).Logger() - sc := rc.Configs[labelSNSConfig].(*snsConfig) - - creds, err := gwcommon.GetAWSCreds(ese.Clientset, ese.Namespace, sc.AccessKey, sc.SecretKey) + sc := rc.snses + creds, err := gwcommon.GetAWSCreds(rc.clientset, rc.namespace, sc.AccessKey, sc.SecretKey) if err != nil { logger.Error().Err(err).Msg("failed to get aws credentials") } @@ -117,12 +116,10 @@ func (ese *SNSEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error } logger.Info().Msg("subscribing to sns topic") - - snsSession := snslib.New(awsSession) - rc.Configs[labelSNSSession] = snsSession + rc.session = snslib.New(awsSession) formattedUrl := gwcommon.GenerateFormattedURL(sc.Hook) - if _, err := snsSession.Subscribe(&snslib.SubscribeInput{ + if _, err := rc.session.Subscribe(&snslib.SubscribeInput{ Endpoint: &formattedUrl, Protocol: &snsProtocol, TopicArn: &sc.TopicArn, @@ -135,12 +132,11 @@ func (ese *SNSEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error } // PostStop unsubscribes from the sns topic -func PostStop(rc *gwcommon.RouteConfig) error { - awsSession := rc.Configs[labelSNSSession].(*snslib.SNS) - if _, err := awsSession.Unsubscribe(&snslib.UnsubscribeInput{ - SubscriptionArn: rc.Configs[labelSubscriptionArn].(*string), +func (rc *RouteConfig) PostStop() error { + if _, err := rc.session.Unsubscribe(&snslib.UnsubscribeInput{ + SubscriptionArn: rc.subscriptionArn, }); err != nil { - rc.Log.Error().Err(err).Str("event-source-name", rc.EventSource.Name).Msg("failed to unsubscribe") + rc.Route.Logger.Error().Err(err).Str("event-source-name", rc.Route.EventSource.Name).Msg("failed to unsubscribe") return err } return nil @@ -156,18 +152,17 @@ func (ese *SNSEventSourceExecutor) StartEventSource(eventSource *gateways.EventS ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") return err } - sc := config.(*snsConfig) - - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: sc.Hook, - Configs: map[string]interface{}{ - labelSNSConfig: sc, + sc := config.(*snsEventSource) + + return gwcommon.ProcessRoute(&RouteConfig{ + Route: &gwcommon.Route{ + Logger: &ese.Log, + EventSource: eventSource, + StartCh: make(chan struct{}), + Webhook: sc.Hook, }, - Log: ese.Log, - EventSource: eventSource, - PostActivate: ese.PostActivate, - PostStop: PostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + snses: sc, + namespace: ese.Namespace, + clientset: ese.Clientset, }, helper, eventStream) } diff --git a/gateways/community/aws-sns/start_test.go b/gateways/community/aws-sns/start_test.go index 46dd2f0c97..93fa4bccb3 100644 --- a/gateways/community/aws-sns/start_test.go +++ b/gateways/community/aws-sns/start_test.go @@ -18,22 +18,28 @@ package aws_sns import ( "bytes" - "github.com/argoproj/argo-events/common" + "io/ioutil" + "net/http" + "testing" + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/aws/aws-sdk-go/aws/credentials" snslib "github.com/aws/aws-sdk-go/service/sns" "github.com/ghodss/yaml" "github.com/smartystreets/goconvey/convey" - "io/ioutil" "k8s.io/client-go/kubernetes/fake" - "net/http" - "testing" ) func TestAWSSNS(t *testing.T) { convey.Convey("Given an route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + rc := &RouteConfig{ + Route: gwcommon.GetFakeRoute(), + namespace: "fake", + clientset: fake.NewSimpleClientset(), + } + r := rc.Route + + helper.ActiveEndpoints[r.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } writer := &gwcommon.FakeHttpWriter{} @@ -46,19 +52,19 @@ func TestAWSSNS(t *testing.T) { convey.So(err, convey.ShouldBeNil) snsSession := snslib.New(awsSession) - rc.Configs[labelSNSSession] = snsSession - rc.Configs[labelSubscriptionArn] = &subscriptionArn + rc.session = snsSession + rc.subscriptionArn = &subscriptionArn convey.Convey("handle the inactive route", func() { - RouteActiveHandler(writer, &http.Request{}, rc) + rc.RouteHandler(writer, &http.Request{}) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) }) ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true - rc.Configs[labelSNSConfig] = ps.(*snsConfig) + helper.ActiveEndpoints[r.Webhook.Endpoint].Active = true + rc.snses = ps.(*snsEventSource) convey.Convey("handle the active route", func() { payload := httpNotification{ @@ -69,37 +75,32 @@ func TestAWSSNS(t *testing.T) { payloadBytes, err := yaml.Marshal(payload) convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewBuffer(payloadBytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) convey.So(string(writer.Payload), convey.ShouldEqual, "failed to confirm subscription") go func() { - <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh + <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh }() payload.Type = messageTypeNotification payloadBytes, err = yaml.Marshal(payload) convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewBuffer(payloadBytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) }) convey.Convey("Run post activate", func() { - ese := SNSEventSourceExecutor{ - Namespace: "fake", - Clientset: fake.NewSimpleClientset(), - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), - } - err := ese.PostActivate(rc) + err := rc.PostStart() convey.So(err, convey.ShouldNotBeNil) }) convey.Convey("Run post stop", func() { - err = PostStop(rc) + err = rc.PostStop() convey.So(err, convey.ShouldNotBeNil) }) }) diff --git a/gateways/community/aws-sns/validate.go b/gateways/community/aws-sns/validate.go index 63b79e2ba0..9c3dac5938 100644 --- a/gateways/community/aws-sns/validate.go +++ b/gateways/community/aws-sns/validate.go @@ -29,7 +29,7 @@ func (ese *SNSEventSourceExecutor) ValidateEventSource(ctx context.Context, es * } func validateSNSConfig(config interface{}) error { - sc := config.(*snsConfig) + sc := config.(*snsEventSource) if sc == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/aws-sqs/config.go b/gateways/community/aws-sqs/config.go index a83dd2bcac..80eca23ac7 100644 --- a/gateways/community/aws-sqs/config.go +++ b/gateways/community/aws-sqs/config.go @@ -32,8 +32,8 @@ type SQSEventSourceExecutor struct { Namespace string } -// sqs contains information to listen to AWS SQS -type sqs struct { +// sqsEventSource contains information to listen to AWS SQS +type sqsEventSource struct { // AccessKey refers K8 secret containing aws access key AccessKey *corev1.SecretKeySelector `json:"accessKey"` @@ -52,7 +52,7 @@ type sqs struct { } func parseEventSource(es string) (interface{}, error) { - var n *sqs + var n *sqsEventSource err := yaml.Unmarshal([]byte(es), &n) if err != nil { return nil, err diff --git a/gateways/community/aws-sqs/config_test.go b/gateways/community/aws-sqs/config_test.go index 5d6929dfe8..aab41b8735 100644 --- a/gateways/community/aws-sqs/config_test.go +++ b/gateways/community/aws-sqs/config_test.go @@ -35,11 +35,11 @@ waitTimeSeconds: 10 ` func TestParseConfig(t *testing.T) { - convey.Convey("Given a aws-sqs event source, parse it", t, func() { + convey.Convey("Given a aws-sqsEventSource event source, parse it", t, func() { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*sqs) + _, ok := ps.(*sqsEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/aws-sqs/start.go b/gateways/community/aws-sqs/start.go index df44dfdee4..dfeff38374 100644 --- a/gateways/community/aws-sqs/start.go +++ b/gateways/community/aws-sqs/start.go @@ -37,13 +37,13 @@ func (ese *SQSEventSourceExecutor) StartEventSource(eventSource *gateways.EventS errorCh := make(chan error) doneCh := make(chan struct{}, 1) - go ese.listenEvents(config.(*sqs), eventSource, dataCh, errorCh, doneCh) + go ese.listenEvents(config.(*sqsEventSource), eventSource, dataCh, errorCh, doneCh) return gateways.HandleEventsFromEventSource(eventSource.Name, eventStream, dataCh, errorCh, doneCh, &ese.Log) } // listenEvents fires an event when interval completes and item is processed from queue. -func (ese *SQSEventSourceExecutor) listenEvents(s *sqs, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { +func (ese *SQSEventSourceExecutor) listenEvents(s *sqsEventSource, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { defer gateways.Recover(eventSource.Name) creds, err := gwcommon.GetAWSCreds(ese.Clientset, ese.Namespace, s.AccessKey, s.SecretKey) diff --git a/gateways/community/aws-sqs/start_test.go b/gateways/community/aws-sqs/start_test.go index 499b311f5d..b7f992aa5d 100644 --- a/gateways/community/aws-sqs/start_test.go +++ b/gateways/community/aws-sqs/start_test.go @@ -47,7 +47,7 @@ func TestListenEvents(t *testing.T) { errorCh2 <- err }() - ese.listenEvents(ps.(*sqs), &gateways.EventSource{ + ese.listenEvents(ps.(*sqsEventSource), &gateways.EventSource{ Name: "fake", Data: es, Id: "1234", diff --git a/gateways/community/aws-sqs/validate.go b/gateways/community/aws-sqs/validate.go index 75de366fe5..5f5043dd68 100644 --- a/gateways/community/aws-sqs/validate.go +++ b/gateways/community/aws-sqs/validate.go @@ -30,7 +30,7 @@ func (ese *SQSEventSourceExecutor) ValidateEventSource(ctx context.Context, es * } func validateSQSConfig(config interface{}) error { - sc := config.(*sqs) + sc := config.(*sqsEventSource) if sc == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/aws-sqs/validate_test.go b/gateways/community/aws-sqs/validate_test.go index 0d34145e5d..31cf0538c6 100644 --- a/gateways/community/aws-sqs/validate_test.go +++ b/gateways/community/aws-sqs/validate_test.go @@ -50,7 +50,7 @@ secretKey: ) func TestSQSEventSourceExecutor_ValidateEventSource(t *testing.T) { - convey.Convey("Given a valid sqs event source spec, parse it and make sure no error occurs", t, func() { + convey.Convey("Given a valid sqsEventSource event source spec, parse it and make sure no error occurs", t, func() { ese := &SQSEventSourceExecutor{} valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ Name: configKey, @@ -61,7 +61,7 @@ func TestSQSEventSourceExecutor_ValidateEventSource(t *testing.T) { convey.So(valid.IsValid, convey.ShouldBeTrue) }) - convey.Convey("Given an invalid sqs event source spec, parse it and make sure error occurs", t, func() { + convey.Convey("Given an invalid sqsEventSource event source spec, parse it and make sure error occurs", t, func() { ese := &SQSEventSourceExecutor{} valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ Data: invalidConfig, diff --git a/gateways/community/gcp-pubsub/config.go b/gateways/community/gcp-pubsub/config.go index 68c8564b18..7021dbdbb6 100644 --- a/gateways/community/gcp-pubsub/config.go +++ b/gateways/community/gcp-pubsub/config.go @@ -26,8 +26,8 @@ type GcpPubSubEventSourceExecutor struct { Log zerolog.Logger } -// pubSubConfig contains configuration to subscribe to GCP PubSub topic -type pubSubConfig struct { +// pubSubEventSource contains configuration to subscribe to GCP PubSub topic +type pubSubEventSource struct { // ProjectID is the unique identifier for your project on GCP ProjectID string `json:"projectID"` // Topic on which a subscription will be created @@ -37,7 +37,7 @@ type pubSubConfig struct { } func parseEventSource(es string) (interface{}, error) { - var n *pubSubConfig + var n *pubSubEventSource err := yaml.Unmarshal([]byte(es), &n) if err != nil { return nil, err diff --git a/gateways/community/gcp-pubsub/config_test.go b/gateways/community/gcp-pubsub/config_test.go index 2eb280bf48..f816c79722 100644 --- a/gateways/community/gcp-pubsub/config_test.go +++ b/gateways/community/gcp-pubsub/config_test.go @@ -31,7 +31,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*pubSubConfig) + _, ok := ps.(*pubSubEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/gcp-pubsub/start.go b/gateways/community/gcp-pubsub/start.go index 14f00aa9f6..d2934ade04 100644 --- a/gateways/community/gcp-pubsub/start.go +++ b/gateways/community/gcp-pubsub/start.go @@ -34,7 +34,7 @@ func (ese *GcpPubSubEventSourceExecutor) StartEventSource(eventSource *gateways. ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") return err } - sc := config.(*pubSubConfig) + sc := config.(*pubSubEventSource) ctx := eventStream.Context() @@ -47,7 +47,7 @@ func (ese *GcpPubSubEventSourceExecutor) StartEventSource(eventSource *gateways. return gateways.HandleEventsFromEventSource(eventSource.Name, eventStream, dataCh, errorCh, doneCh, &ese.Log) } -func (ese *GcpPubSubEventSourceExecutor) listenEvents(ctx context.Context, sc *pubSubConfig, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { +func (ese *GcpPubSubEventSourceExecutor) listenEvents(ctx context.Context, sc *pubSubEventSource, eventSource *gateways.EventSource, dataCh chan []byte, errorCh chan error, doneCh chan struct{}) { // Create a new topic with the given name. logger := ese.Log.With().Str("event-source", eventSource.Name).Str("topic", sc.Topic).Logger() diff --git a/gateways/community/gcp-pubsub/start_test.go b/gateways/community/gcp-pubsub/start_test.go index ea21d8c23c..be06b0ebe1 100644 --- a/gateways/community/gcp-pubsub/start_test.go +++ b/gateways/community/gcp-pubsub/start_test.go @@ -29,7 +29,7 @@ func TestListenEvents(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - psc := ps.(*pubSubConfig) + psc := ps.(*pubSubEventSource) ese := &GcpPubSubEventSourceExecutor{ Log: common.GetLoggerContext(common.LoggerConf()).Logger(), diff --git a/gateways/community/gcp-pubsub/validate.go b/gateways/community/gcp-pubsub/validate.go index 1d87719451..f81c167e43 100644 --- a/gateways/community/gcp-pubsub/validate.go +++ b/gateways/community/gcp-pubsub/validate.go @@ -31,7 +31,7 @@ func (ese *GcpPubSubEventSourceExecutor) ValidateEventSource(ctx context.Context } func validatePubSubConfig(config interface{}) error { - sc := config.(*pubSubConfig) + sc := config.(*pubSubEventSource) if sc == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/github/start_test.go b/gateways/community/github/start_test.go index 04751467c4..7cbe77b247 100644 --- a/gateways/community/github/start_test.go +++ b/gateways/community/github/start_test.go @@ -70,7 +70,7 @@ func TestGetCredentials(t *testing.T) { func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() + rc := gwcommon.GetFakeRoute() helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } diff --git a/gateways/community/gitlab/start_test.go b/gateways/community/gitlab/start_test.go index b75716ffdf..88aa3e6cc8 100644 --- a/gateways/community/gitlab/start_test.go +++ b/gateways/community/gitlab/start_test.go @@ -69,7 +69,7 @@ func TestGetCredentials(t *testing.T) { func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() + rc := gwcommon.GetFakeRoute() helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } diff --git a/gateways/community/slack/start.go b/gateways/community/slack/start.go index a1048b66c4..c104f5ddd5 100644 --- a/gateways/community/slack/start.go +++ b/gateways/community/slack/start.go @@ -41,7 +41,7 @@ func init() { go gwcommon.InitRouteChannels(helper) } -// RouteActiveHandler handles new route +// RouteHandler handles new route func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { var response string diff --git a/gateways/community/slack/start_test.go b/gateways/community/slack/start_test.go index 1443654074..da6cf61eb6 100644 --- a/gateways/community/slack/start_test.go +++ b/gateways/community/slack/start_test.go @@ -31,7 +31,7 @@ import ( func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() + rc := gwcommon.GetFakeRoute() helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), diff --git a/gateways/community/storagegrid/start_test.go b/gateways/community/storagegrid/start_test.go index 9a6cec6a43..24e97492f3 100644 --- a/gateways/community/storagegrid/start_test.go +++ b/gateways/community/storagegrid/start_test.go @@ -73,7 +73,7 @@ var notification = ` func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() + rc := gwcommon.GetFakeRoute() helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } diff --git a/gateways/community/trello/start_test.go b/gateways/community/trello/start_test.go index 488caae8c0..60ffb00bdd 100644 --- a/gateways/community/trello/start_test.go +++ b/gateways/community/trello/start_test.go @@ -33,7 +33,7 @@ import ( func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() + rc := gwcommon.GetFakeRoute() helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } diff --git a/gateways/core/webhook/config.go b/gateways/core/webhook/config.go index 2290331502..08729beab6 100644 --- a/gateways/core/webhook/config.go +++ b/gateways/core/webhook/config.go @@ -18,6 +18,7 @@ package webhook import ( "github.com/argoproj/argo-events/gateways/common" + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/rs/zerolog" ) @@ -27,6 +28,10 @@ type WebhookEventSourceExecutor struct { Log zerolog.Logger } +type RouteConfig struct { + Route *gwcommon.Route +} + func parseEventSource(es string) (interface{}, error) { var n *common.Webhook err := yaml.Unmarshal([]byte(es), &n) diff --git a/gateways/core/webhook/start.go b/gateways/core/webhook/start.go index a7d3e88d9e..03f337045c 100644 --- a/gateways/core/webhook/start.go +++ b/gateways/core/webhook/start.go @@ -34,25 +34,31 @@ func init() { go gwcommon.InitRouteChannels(helper) } -// routeActiveHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.Route +} + +// RouteHandler handles new route +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { var response string - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). + r := rc.Route + + logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port). Str("http-method", request.Method).Logger() logger.Info().Msg("request received") - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { + response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", r.Webhook.Endpoint, r.Webhook.Method) logger.Info().Msg("endpoint is not active") common.SendErrorResponse(writer, response) return } - if rc.Webhook.Method != request.Method { - logger.Warn().Str("expected", rc.Webhook.Method).Str("actual", request.Method).Msg("method mismatch") - common.SendErrorResponse(writer, fmt.Sprintf("the method %s is not defined for endpoint %s", rc.Webhook.Method, rc.Webhook.Endpoint)) + if r.Webhook.Method != request.Method { + logger.Warn().Str("expected", r.Webhook.Method).Str("actual", request.Method).Msg("method mismatch") + common.SendErrorResponse(writer, fmt.Sprintf("the method %s is not defined for endpoint %s", r.Webhook.Method, r.Webhook.Endpoint)) return } @@ -63,12 +69,20 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g return } - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- body + helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body response = "request successfully processed" logger.Info().Msg(response) common.SendSuccessResponse(writer, response) } +func (rc *RouteConfig) PostStart() error { + return nil +} + +func (rc *RouteConfig) PostStop() error { + return nil +} + // StartEventSource starts a event source func (ese *WebhookEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) @@ -82,13 +96,12 @@ func (ese *WebhookEventSourceExecutor) StartEventSource(eventSource *gateways.Ev h := config.(*gwcommon.Webhook) h.Endpoint = gwcommon.FormatWebhookEndpoint(h.Endpoint) - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: h, - Log: ese.Log, - EventSource: eventSource, - PostActivate: gwcommon.DefaultPostActivate, - PostStop: gwcommon.DefaultPostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + return gwcommon.ProcessRoute(&RouteConfig{ + Route: &gwcommon.Route{ + Logger: &ese.Log, + EventSource: eventSource, + StartCh: make(chan struct{}), + Webhook: h, + }, }, helper, eventStream) } diff --git a/gateways/core/webhook/start_test.go b/gateways/core/webhook/start_test.go index 2758a1e485..3c1025b692 100644 --- a/gateways/core/webhook/start_test.go +++ b/gateways/core/webhook/start_test.go @@ -27,44 +27,47 @@ import ( func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRouteConfig() - rc.Webhook.Method = http.MethodGet - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + rc := &RouteConfig{ + Route: gwcommon.GetFakeRoute(), + } + r := rc.Route + r.Webhook.Method = http.MethodGet + helper.ActiveEndpoints[r.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } writer := &gwcommon.FakeHttpWriter{} convey.Convey("Inactive route should return error", func() { - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader([]byte("hello"))), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) }) - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true + helper.ActiveEndpoints[r.Webhook.Endpoint].Active = true convey.Convey("Active route with correct method should return success", func() { dataCh := make(chan []byte) go func() { - resp := <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh + resp := <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh dataCh <- resp }() - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader([]byte("fake notification"))), Method: http.MethodGet, - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) data := <-dataCh convey.So(string(data), convey.ShouldEqual, "fake notification") }) convey.Convey("Active route with incorrect method should return failure", func() { - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader([]byte("fake notification"))), Method: http.MethodHead, - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) }) }) From 0d1e58d0f8b547f6250b1bf58cab3ce93cd7954c Mon Sep 17 00:00:00 2001 From: vpage Date: Tue, 19 Mar 2019 16:03:27 -0400 Subject: [PATCH 02/11] refactor(): webhook route config and removing trello gateway --- examples/gateways/calendar.yaml | 4 +- gateways/common/fake.go | 4 +- gateways/common/webhook.go | 24 ++-- gateways/common/webhook_test.go | 43 ++---- gateways/community/github/config.go | 17 ++- gateways/community/github/config_test.go | 2 +- gateways/community/github/start.go | 84 +++++------ gateways/community/github/start_test.go | 38 ++--- gateways/community/github/validate.go | 2 +- gateways/community/gitlab/config.go | 18 ++- gateways/community/gitlab/config_test.go | 2 +- gateways/community/gitlab/start.go | 102 ++++++------- gateways/community/gitlab/start_test.go | 43 +++--- gateways/community/gitlab/validate.go | 2 +- gateways/community/slack/config.go | 16 ++- gateways/community/slack/config_test.go | 2 +- gateways/community/slack/start.go | 75 ++++++---- gateways/community/slack/start_test.go | 29 ++-- gateways/community/slack/validate.go | 2 +- gateways/community/storagegrid/config.go | 13 +- gateways/community/storagegrid/config_test.go | 2 +- gateways/community/storagegrid/start.go | 61 ++++---- gateways/community/storagegrid/start_test.go | 31 ++-- gateways/community/storagegrid/validate.go | 2 +- gateways/community/trello/Dockerfile | 3 - gateways/community/trello/cmd/main.go | 44 ------ gateways/community/trello/config.go | 54 ------- gateways/community/trello/config_test.go | 47 ------ gateways/community/trello/start.go | 134 ------------------ gateways/community/trello/start_test.go | 95 ------------- gateways/community/trello/validate.go | 44 ------ gateways/community/trello/validate_test.go | 74 ---------- 32 files changed, 331 insertions(+), 782 deletions(-) delete mode 100644 gateways/community/trello/Dockerfile delete mode 100644 gateways/community/trello/cmd/main.go delete mode 100644 gateways/community/trello/config.go delete mode 100644 gateways/community/trello/config_test.go delete mode 100644 gateways/community/trello/start.go delete mode 100644 gateways/community/trello/start_test.go delete mode 100644 gateways/community/trello/validate.go delete mode 100644 gateways/community/trello/validate_test.go diff --git a/examples/gateways/calendar.yaml b/examples/gateways/calendar.yaml index 9a9d04f93b..a6604323be 100644 --- a/examples/gateways/calendar.yaml +++ b/examples/gateways/calendar.yaml @@ -19,11 +19,11 @@ spec: spec: containers: - name: "gateway-client" - image: "argoproj/gateway-client" + image: "argoproj/gateway-client:v0.8.3" imagePullPolicy: "Always" command: ["/bin/gateway-client"] - name: "calendar-events" - image: "argoproj/calendar-gateway" + image: "argoproj/calendar-gateway:v0.8.3" imagePullPolicy: "Always" command: ["/bin/calendar-gateway"] serviceAccountName: "argo-events-sa" diff --git a/gateways/common/fake.go b/gateways/common/fake.go index a4f5451544..918c3a67f2 100644 --- a/gateways/common/fake.go +++ b/gateways/common/fake.go @@ -33,11 +33,11 @@ func (f *FakeHttpWriter) WriteHeader(status int) { } type FakeRouteConfig struct { - Route *Route + route *Route } func (f *FakeRouteConfig) GetRoute() *Route { - return f.Route + return f.route } func (f *FakeRouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index 031c14675c..36205d8117 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -224,27 +224,28 @@ func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways } } -func DefaultPostActivate(rc *RouteConfig) error { - return nil -} - -func DefaultPostStop(rc *RouteConfig) error { - return nil -} - func ProcessRoute(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { - if err := validateRouteConfig(rc); err != nil { + r := rc.GetRoute() + + if err := validateRoute(rc.GetRoute()); err != nil { + r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred validating route") return err } + activateRoute(rc, helper) + if err := rc.PostStart(); err != nil { + r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post start") return err } + if err := processChannels(rc, helper, eventStream); err != nil { + r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in process channel") return err } + if err := rc.PostStop(); err != nil { - rc.GetRoute().Logger.Error().Err(err).Msg("error occurred while executing post stop logic") + r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post stop") } return nil } @@ -268,8 +269,7 @@ func ValidateWebhook(w *Webhook) error { return nil } -func validateRouteConfig(rc RouteConfig) error { - r := rc.GetRoute() +func validateRoute(r *Route) error { if r == nil { return fmt.Errorf("route can't be nil") } diff --git a/gateways/common/webhook_test.go b/gateways/common/webhook_test.go index f5ce248b55..931a0c86b6 100644 --- a/gateways/common/webhook_test.go +++ b/gateways/common/webhook_test.go @@ -26,30 +26,15 @@ import ( "github.com/smartystreets/goconvey/convey" ) -func TestDefaultPostActivate(t *testing.T) { - convey.Convey("Given a route configuration, default post activate should be a no-op", t, func() { - rc := GetFakeRoute() - err := DefaultPostActivate(rc) - convey.So(err, convey.ShouldBeNil) - }) -} - -func TestDefaultPostStop(t *testing.T) { - convey.Convey("Given a route configuration, default post stop should be a no-op", t, func() { - rc := GetFakeRoute() - err := DefaultPostStop(rc) - convey.So(err, convey.ShouldBeNil) - }) +var rc = &FakeRouteConfig{ + route: GetFakeRoute(), } func TestProcessRoute(t *testing.T) { convey.Convey("Given a route configuration", t, func() { convey.Convey("Activate the route configuration", func() { - rc := GetFakeRoute() - rc.Webhook.mux = http.NewServeMux() - rc.PostActivate = DefaultPostActivate - rc.PostStop = DefaultPostStop + rc.route.Webhook.mux = http.NewServeMux() ctx, cancel := context.WithCancel(context.Background()) fgs := &FakeGRPCStream{ @@ -57,10 +42,10 @@ func TestProcessRoute(t *testing.T) { } helper := NewWebhookHelper() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &Endpoint{ DataCh: make(chan []byte), } - helper.ActiveServers[rc.Webhook.Port] = &activeServer{ + helper.ActiveServers[rc.route.Webhook.Port] = &activeServer{ errChan: make(chan error), } @@ -73,7 +58,7 @@ func TestProcessRoute(t *testing.T) { <-helper.RouteActivateChan }() go func() { - rc.StartCh <- struct{}{} + rc.route.StartCh <- struct{}{} }() go func() { time.Sleep(3 * time.Second) @@ -93,16 +78,15 @@ func TestProcessRoute(t *testing.T) { func TestProcessRouteChannels(t *testing.T) { convey.Convey("Given a route configuration", t, func() { convey.Convey("Stop server stream", func() { - rc := GetFakeRoute() ctx, cancel := context.WithCancel(context.Background()) fgs := &FakeGRPCStream{ Ctx: ctx, } helper := NewWebhookHelper() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &Endpoint{ DataCh: make(chan []byte), } - helper.ActiveServers[rc.Webhook.Port] = &activeServer{ + helper.ActiveServers[rc.route.Webhook.Port] = &activeServer{ errChan: make(chan error), } errCh := make(chan error) @@ -110,31 +94,30 @@ func TestProcessRouteChannels(t *testing.T) { <-helper.RouteDeactivateChan }() go func() { - errCh <- rc.processChannels(helper, fgs) + errCh <- processChannels(rc, helper, fgs) }() cancel() err := <-errCh convey.So(err, convey.ShouldBeNil) }) convey.Convey("Handle error", func() { - rc := GetFakeRoute() fgs := &FakeGRPCStream{ Ctx: context.Background(), } helper := NewWebhookHelper() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &Endpoint{ DataCh: make(chan []byte), } - helper.ActiveServers[rc.Webhook.Port] = &activeServer{ + helper.ActiveServers[rc.route.Webhook.Port] = &activeServer{ errChan: make(chan error), } errCh := make(chan error) err := fmt.Errorf("error") go func() { - helper.ActiveServers[rc.Webhook.Port].errChan <- err + helper.ActiveServers[rc.route.Webhook.Port].errChan <- err }() go func() { - errCh <- rc.processChannels(helper, fgs) + errCh <- processChannels(rc, helper, fgs) }() newErr := <-errCh convey.So(newErr.Error(), convey.ShouldEqual, err.Error()) diff --git a/gateways/community/github/config.go b/gateways/community/github/config.go index 22a5610089..32a216be05 100644 --- a/gateways/community/github/config.go +++ b/gateways/community/github/config.go @@ -18,7 +18,9 @@ package github import ( "github.com/argoproj/argo-events/gateways/common" + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" + "github.com/google/go-github/github" "github.com/rs/zerolog" corev1 "k8s.io/api/core/v1" "k8s.io/client-go/kubernetes" @@ -33,8 +35,17 @@ type GithubEventSourceExecutor struct { Namespace string } -// githubConfig contains information to setup a github project integration -type githubConfig struct { +type RouteConfig struct { + route *gwcommon.Route + ges *githubEventSource + client *github.Client + hook *github.Hook + clientset kubernetes.Interface + namespace string +} + +// githubEventSource contains information to setup a github project integration +type githubEventSource struct { // Webhook Hook *common.Webhook `json:"hook"` // GitHub owner name i.e. argoproj @@ -66,7 +77,7 @@ type cred struct { // parseEventSource parses a configuration of gateway func parseEventSource(config string) (interface{}, error) { - var g *githubConfig + var g *githubEventSource err := yaml.Unmarshal([]byte(config), &g) if err != nil { return nil, err diff --git a/gateways/community/github/config_test.go b/gateways/community/github/config_test.go index dde443535d..688ee574f0 100644 --- a/gateways/community/github/config_test.go +++ b/gateways/community/github/config_test.go @@ -40,7 +40,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*githubConfig) + _, ok := ps.(*githubEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/github/start.go b/gateways/community/github/start.go index 3d6b035ace..1609f861c2 100644 --- a/gateways/community/github/start.go +++ b/gateways/community/github/start.go @@ -32,12 +32,6 @@ import ( corev1 "k8s.io/api/core/v1" ) -const ( - labelGithubConfig = "config" - labelGithubClient = "client" - labelWebhook = "hook" -) - const ( githubEventHeader = "X-GitHub-Event" githubDeliveryHeader = "X-GitHub-Delivery" @@ -52,8 +46,8 @@ func init() { } // getCredentials for github -func (ese *GithubEventSourceExecutor) getCredentials(gs *corev1.SecretKeySelector) (*cred, error) { - token, err := store.GetSecrets(ese.Clientset, ese.Namespace, gs.Name, gs.Key) +func (rc *RouteConfig) getCredentials(gs *corev1.SecretKeySelector) (*cred, error) { + token, err := store.GetSecrets(rc.clientset, rc.namespace, gs.Name, gs.Key) if err != nil { return nil, err } @@ -62,10 +56,14 @@ func (ese *GithubEventSourceExecutor) getCredentials(gs *corev1.SecretKeySelecto }, nil } -func (ese *GithubEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error { - gc := rc.Configs[labelGithubConfig].(*githubConfig) +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.route +} - c, err := ese.getCredentials(gc.APIToken) +func (rc *RouteConfig) PostStart() error { + gc := rc.ges + + c, err := rc.getCredentials(gc.APIToken) if err != nil { return fmt.Errorf("failed to rtrieve github credentials. err: %+v", err) } @@ -90,40 +88,38 @@ func (ese *GithubEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) err } if gc.WebHookSecret != nil { - sc, err := ese.getCredentials(gc.WebHookSecret) + sc, err := rc.getCredentials(gc.WebHookSecret) if err != nil { return fmt.Errorf("failed to retrieve webhook secret. err: %+v", err) } hookConfig["secret"] = sc.secret } - hookSetup := &gh.Hook{ + rc.hook = &gh.Hook{ Events: gc.Events, Active: gh.Bool(gc.Active), Config: hookConfig, } - rc.Configs[labelWebhook] = hookSetup - client := gh.NewClient(PATTransport.Client()) + rc.client = gh.NewClient(PATTransport.Client()) if gc.GithubBaseURL != "" { baseURL, err := url.Parse(gc.GithubBaseURL) if err != nil { return fmt.Errorf("failed to parse github base url. err: %s", err) } - client.BaseURL = baseURL + rc.client.BaseURL = baseURL } if gc.GithubUploadURL != "" { uploadURL, err := url.Parse(gc.GithubUploadURL) if err != nil { return fmt.Errorf("failed to parse github upload url. err: %s", err) } - client.UploadURL = uploadURL + rc.client.UploadURL = uploadURL } - rc.Configs[labelGithubClient] = client ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - hook, _, err := client.Repositories.CreateHook(ctx, gc.Owner, gc.Repository, hookSetup) + hook, _, err := rc.client.Repositories.CreateHook(ctx, gc.Owner, gc.Repository, rc.hook) if err != nil { // Continue if error is because hook already exists er, ok := err.(*gh.ErrorResponse) @@ -132,22 +128,23 @@ func (ese *GithubEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) err } } - ese.Log.Info().Str("event-source-name", rc.EventSource.Name).Interface("hook-id", *hook.ID).Msg("github hook created") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int64("hook-id", *hook.ID).Msg("github hook created") return nil } -func PostStop(rc *gwcommon.RouteConfig) error { - gc := rc.Configs[labelGithubConfig].(*githubConfig) - client := rc.Configs[labelGithubClient].(*gh.Client) - hook := rc.Configs[labelWebhook].(*gh.Hook) +func (rc *RouteConfig) PostStop() error { + r := rc.route + gc := rc.ges + client := rc.client + hook := rc.hook ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() if _, err := client.Repositories.DeleteHook(ctx, gc.Owner, gc.Repository, *hook.ID); err != nil { - rc.Log.Error().Err(err).Str("event-source-name", rc.EventSource.Name).Msg("failed to delete github hook") + r.Logger.Error().Err(err).Str("event-source-name", r.EventSource.Name).Msg("failed to delete github hook") return err } - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Interface("hook-id", *hook.ID).Msg("github hook deleted") + r.Logger.Info().Str("event-source-name", r.EventSource.Name).Int64("hook-id", *hook.ID).Msg("github hook deleted") return nil } @@ -160,19 +157,12 @@ func (ese *GithubEventSourceExecutor) StartEventSource(eventSource *gateways.Eve if err != nil { ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") } - gc := config.(*githubConfig) - - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: gc.Hook, - Configs: map[string]interface{}{ - labelGithubConfig: gc, - }, - Log: ese.Log, - EventSource: eventSource, - PostActivate: ese.PostActivate, - PostStop: PostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + gc := config.(*githubEventSource) + + return gwcommon.ProcessRoute(&RouteConfig{ + clientset: ese.Clientset, + namespace: ese.Namespace, + ges: gc, }, helper, eventStream) } @@ -196,22 +186,24 @@ func parseValidateRequest(r *http.Request, secret []byte) ([]byte, error) { } // routeActiveHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { var response string - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). + r := rc.route + + logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port). Str("http-method", request.Method).Logger() logger.Info().Msg("request received") - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { + response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", r.Webhook.Endpoint, r.Webhook.Method) logger.Info().Msg("endpoint is not active") common.SendErrorResponse(writer, response) return } - hook := rc.Configs[labelWebhook].(*gh.Hook) + hook := rc.hook secret := "" if s, ok := hook.Config["secret"]; ok { secret = s.(string) @@ -223,7 +215,7 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g return } - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- body + helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body response = "request successfully processed" logger.Info().Msg(response) common.SendSuccessResponse(writer, response) diff --git a/gateways/community/github/start_test.go b/gateways/community/github/start_test.go index 7cbe77b247..9206c8d5bf 100644 --- a/gateways/community/github/start_test.go +++ b/gateways/community/github/start_test.go @@ -23,7 +23,6 @@ import ( "net/http" "testing" - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/google/go-github/github" @@ -34,10 +33,10 @@ import ( ) var ( - ese = &GithubEventSourceExecutor{ - Clientset: fake.NewSimpleClientset(), - Namespace: "fake", - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), + rc = &RouteConfig{ + route: gwcommon.GetFakeRoute(), + clientset: fake.NewSimpleClientset(), + namespace: "fake", } secretName = "githab-access" @@ -47,10 +46,11 @@ var ( func TestGetCredentials(t *testing.T) { convey.Convey("Given a kubernetes secret, get credentials", t, func() { - secret, err := ese.Clientset.CoreV1().Secrets(ese.Namespace).Create(&corev1.Secret{ + + secret, err := rc.clientset.CoreV1().Secrets(rc.namespace).Create(&corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: secretName, - Namespace: ese.Namespace, + Namespace: rc.namespace, }, Data: map[string][]byte{ LabelAccessKey: []byte(accessKey), @@ -61,7 +61,7 @@ func TestGetCredentials(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) - creds, err := ese.getCredentials(ps.(*githubConfig).APIToken) + creds, err := rc.getCredentials(ps.(*githubEventSource).APIToken) convey.So(err, convey.ShouldBeNil) convey.So(creds, convey.ShouldNotBeNil) convey.So(creds.secret, convey.ShouldEqual, "YWNjZXNz") @@ -70,8 +70,8 @@ func TestGetCredentials(t *testing.T) { func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRoute() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + r := rc.route + helper.ActiveEndpoints[r.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } @@ -79,26 +79,26 @@ func TestRouteActiveHandler(t *testing.T) { writer := &gwcommon.FakeHttpWriter{} ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) - pbytes, err := yaml.Marshal(ps.(*githubConfig)) + pbytes, err := yaml.Marshal(ps.(*githubEventSource)) convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) convey.Convey("Active route should return success", func() { - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true - rc.Configs[labelWebhook] = &github.Hook{ + helper.ActiveEndpoints[r.Webhook.Endpoint].Active = true + rc.hook = &github.Hook{ Config: make(map[string]interface{}), } - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) - rc.Configs[labelGithubConfig] = ps.(*githubConfig) - err = ese.PostActivate(rc) + rc.ges = ps.(*githubEventSource) + err = rc.PostStart() convey.So(err, convey.ShouldNotBeNil) }) }) diff --git a/gateways/community/github/validate.go b/gateways/community/github/validate.go index 722fd05498..24342d8a27 100644 --- a/gateways/community/github/validate.go +++ b/gateways/community/github/validate.go @@ -26,7 +26,7 @@ func (ese *GithubEventSourceExecutor) ValidateEventSource(ctx context.Context, e } func validateGithub(config interface{}) error { - g := config.(*githubConfig) + g := config.(*githubEventSource) if g == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/gitlab/config.go b/gateways/community/gitlab/config.go index f74aeedd91..a514e1c430 100644 --- a/gateways/community/gitlab/config.go +++ b/gateways/community/gitlab/config.go @@ -18,8 +18,10 @@ package gitlab import ( "github.com/argoproj/argo-events/gateways/common" + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/rs/zerolog" + "github.com/xanzy/go-gitlab" "k8s.io/client-go/kubernetes" ) @@ -32,8 +34,18 @@ type GitlabEventSourceExecutor struct { Namespace string } -// glab contains information to setup a gitlab project integration -type glab struct { +// RouteConfig contains the configuration information for a route +type RouteConfig struct { + route *gwcommon.Route + clientset kubernetes.Interface + client *gitlab.Client + hook *gitlab.ProjectHook + namespace string + ges *gitlabEventSource +} + +// gitlabEventSource contains information to setup a gitlab project integration +type gitlabEventSource struct { // Webhook Hook *common.Webhook `json:"hook"` // ProjectId is the id of project for which integration needs to setup @@ -65,7 +77,7 @@ type cred struct { // parseEventSource parses an event sources of gateway func parseEventSource(config string) (interface{}, error) { - var g *glab + var g *gitlabEventSource err := yaml.Unmarshal([]byte(config), &g) if err != nil { return nil, err diff --git a/gateways/community/gitlab/config_test.go b/gateways/community/gitlab/config_test.go index 6f88cdef76..25a761a0dc 100644 --- a/gateways/community/gitlab/config_test.go +++ b/gateways/community/gitlab/config_test.go @@ -41,7 +41,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*glab) + _, ok := ps.(*gitlabEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/gitlab/start.go b/gateways/community/gitlab/start.go index f771806620..8536f3e5ed 100644 --- a/gateways/community/gitlab/start.go +++ b/gateways/community/gitlab/start.go @@ -29,12 +29,6 @@ import ( "github.com/xanzy/go-gitlab" ) -const ( - labelGitlabConfig = "config" - labelGitlabClient = "client" - labelWebhook = "hook" -) - var ( helper = gwcommon.NewWebhookHelper() ) @@ -44,8 +38,8 @@ func init() { } // getCredentials for gitlab -func (ese *GitlabEventSourceExecutor) getCredentials(gs *GitlabSecret) (*cred, error) { - token, err := store.GetSecrets(ese.Clientset, ese.Namespace, gs.Name, gs.Key) +func (rc *RouteConfig) getCredentials(gs *GitlabSecret) (*cred, error) { + token, err := store.GetSecrets(rc.clientset, rc.namespace, gs.Name, gs.Key) if err != nil { return nil, err } @@ -54,72 +48,85 @@ func (ese *GitlabEventSourceExecutor) getCredentials(gs *GitlabSecret) (*cred, e }, nil } -func (ese *GitlabEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error { - gl := rc.Configs[labelGitlabConfig].(*glab) +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.route +} - c, err := ese.getCredentials(gl.AccessToken) +func (rc *RouteConfig) PostStart() error { + c, err := rc.getCredentials(rc.ges.AccessToken) if err != nil { return fmt.Errorf("failed to get gitlab credentials. err: %+v", err) } - client := gitlab.NewClient(nil, c.token) - if err = client.SetBaseURL(gl.GitlabBaseURL); err != nil { + rc.client = gitlab.NewClient(nil, c.token) + if err = rc.client.SetBaseURL(rc.ges.GitlabBaseURL); err != nil { return fmt.Errorf("failed to set gitlab base url, err: %+v", err) } - rc.Configs[labelGitlabClient] = client - - formattedUrl := gwcommon.GenerateFormattedURL(gl.Hook) + formattedUrl := gwcommon.GenerateFormattedURL(rc.ges.Hook) opt := &gitlab.AddProjectHookOptions{ URL: &formattedUrl, Token: &c.token, - EnableSSLVerification: &gl.EnableSSLVerification, + EnableSSLVerification: &rc.ges.EnableSSLVerification, } - elem := reflect.ValueOf(opt).Elem().FieldByName(string(gl.Event)) + elem := reflect.ValueOf(opt).Elem().FieldByName(string(rc.ges.Event)) if ok := elem.IsValid(); !ok { - return fmt.Errorf("unknown event %s", gl.Event) + return fmt.Errorf("unknown event %s", rc.ges.Event) } iev := reflect.New(elem.Type().Elem()) reflect.Indirect(iev).SetBool(true) elem.Set(iev) - hook, _, err := client.Projects.AddProjectHook(gl.ProjectId, opt) + existingHooks, _, err := rc.client.Projects.ListProjectHooks(rc.ges.ProjectId, &gitlab.ListProjectHooksOptions{}) + if err != nil { + return fmt.Errorf("failed to list existing webhooks. err: %+v", err) + } + + for _, h := range existingHooks { + elem = reflect.ValueOf(h).Elem().FieldByName(string(rc.ges.Event)) + if ok := elem.IsValid(); !ok { + return fmt.Errorf("failed to check if hook is already registered with the event %s. unknown event", rc.ges.Event) + } + if reflect.New(elem.Type().Elem()).Bool() && h.URL == formattedUrl { + rc.route.Logger.Info().Str("event-source", rc.route.EventSource.Name).Msg("hook is already configured") + return nil + } + } + + hook, _, err := rc.client.Projects.AddProjectHook(rc.ges.ProjectId, opt) if err != nil { return fmt.Errorf("failed to add project hook. err: %+v", err) } - rc.Configs[labelWebhook] = hook + rc.hook = hook - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Interface("hook-id", hook.ID).Msg("gitlab hook created") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("gitlab hook created") return nil } -func PostStop(rc *gwcommon.RouteConfig) error { - gl := rc.Configs[labelGitlabConfig].(*glab) - client := rc.Configs[labelGitlabClient].(*gitlab.Client) - hook := rc.Configs[labelWebhook].(*gitlab.ProjectHook) - - if _, err := client.Projects.DeleteProjectHook(gl.ProjectId, hook.ID); err != nil { - rc.Log.Error().Err(err).Str("event-source-name", rc.EventSource.Name).Interface("hook-id", hook.ID).Msg("failed to delete gitlab hook") +func (rc *RouteConfig) PostStop() error { + if _, err := rc.client.Projects.DeleteProjectHook(rc.ges.ProjectId, rc.hook.ID); err != nil { + rc.route.Logger.Error().Err(err).Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("failed to delete gitlab hook") return err } - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Interface("hook-id", hook.ID).Msg("gitlab hook deleted") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("gitlab hook deleted") return nil } // routeActiveHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { var response string - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). + logger := rc.route.Logger.With().Str("event-source", rc.route.EventSource.Name).Str("endpoint", rc.route.Webhook.Endpoint). + Str("port", rc.route.Webhook.Port). Str("http-method", request.Method).Logger() + logger.Info().Msg("request received") - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) + if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { + response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.route.Webhook.Endpoint, rc.route.Webhook.Method) logger.Info().Msg("endpoint is not active") common.SendErrorResponse(writer, response) return @@ -132,7 +139,7 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g return } - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- body + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- body response = "request successfully processed" logger.Info().Msg(response) common.SendSuccessResponse(writer, response) @@ -148,18 +155,17 @@ func (ese *GitlabEventSourceExecutor) StartEventSource(eventSource *gateways.Eve ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") return err } - gl := config.(*glab) - - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: gl.Hook, - Configs: map[string]interface{}{ - labelGitlabConfig: gl, + gl := config.(*gitlabEventSource) + + return gwcommon.ProcessRoute(&RouteConfig{ + route: &gwcommon.Route{ + EventSource: eventSource, + Logger: &ese.Log, + Webhook: gl.Hook, + StartCh: make(chan struct{}), }, - Log: ese.Log, - EventSource: eventSource, - PostActivate: ese.PostActivate, - PostStop: PostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + namespace: ese.Namespace, + clientset: ese.Clientset, + ges: gl, }, helper, eventStream) } diff --git a/gateways/community/gitlab/start_test.go b/gateways/community/gitlab/start_test.go index 88aa3e6cc8..4c27de9979 100644 --- a/gateways/community/gitlab/start_test.go +++ b/gateways/community/gitlab/start_test.go @@ -18,14 +18,13 @@ package gitlab import ( "bytes" + "github.com/xanzy/go-gitlab" "io/ioutil" "net/http" "testing" - "github.com/argoproj/argo-events/common" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" - "github.com/google/go-github/github" "github.com/smartystreets/goconvey/convey" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -33,10 +32,10 @@ import ( ) var ( - ese = &GitlabEventSourceExecutor{ - Clientset: fake.NewSimpleClientset(), - Namespace: "fake", - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), + rc = &RouteConfig{ + route: gwcommon.GetFakeRoute(), + clientset: fake.NewSimpleClientset(), + namespace: "fake", } secretName = "gitlab-access" @@ -46,10 +45,10 @@ var ( func TestGetCredentials(t *testing.T) { convey.Convey("Given a kubernetes secret, get credentials", t, func() { - secret, err := ese.Clientset.CoreV1().Secrets(ese.Namespace).Create(&corev1.Secret{ + secret, err := rc.clientset.CoreV1().Secrets(rc.namespace).Create(&corev1.Secret{ ObjectMeta: metav1.ObjectMeta{ Name: secretName, - Namespace: ese.Namespace, + Namespace: rc.namespace, }, Data: map[string][]byte{ LabelAccessKey: []byte(accessKey), @@ -60,7 +59,7 @@ func TestGetCredentials(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) - creds, err := ese.getCredentials(ps.(*glab).AccessToken) + creds, err := rc.getCredentials(ps.(*gitlabEventSource).AccessToken) convey.So(err, convey.ShouldBeNil) convey.So(creds, convey.ShouldNotBeNil) convey.So(creds.token, convey.ShouldEqual, "YWNjZXNz") @@ -69,8 +68,7 @@ func TestGetCredentials(t *testing.T) { func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRoute() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } @@ -78,33 +76,34 @@ func TestRouteActiveHandler(t *testing.T) { writer := &gwcommon.FakeHttpWriter{} ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) - pbytes, err := yaml.Marshal(ps.(*glab)) + pbytes, err := yaml.Marshal(ps.(*gitlabEventSource)) convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) convey.Convey("Active route should return success", func() { - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true - rc.Configs[labelWebhook] = &github.Hook{ - Config: make(map[string]interface{}), + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active = true + rc.hook = &gitlab.ProjectHook{ + URL: "fake", + PushEvents: true, } dataCh := make(chan []byte) go func() { - resp := <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh + resp := <-helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh dataCh <- resp }() - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) + }) data := <-dataCh convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) convey.So(string(data), convey.ShouldEqual, string(pbytes)) - rc.Configs[labelGitlabConfig] = ps.(*glab) - err = ese.PostActivate(rc) + rc.ges = ps.(*gitlabEventSource) + err = rc.PostStart() convey.So(err, convey.ShouldNotBeNil) }) }) diff --git a/gateways/community/gitlab/validate.go b/gateways/community/gitlab/validate.go index 48193aa4e3..9cc9607cd8 100644 --- a/gateways/community/gitlab/validate.go +++ b/gateways/community/gitlab/validate.go @@ -27,7 +27,7 @@ func (ese *GitlabEventSourceExecutor) ValidateEventSource(ctx context.Context, e } func validateGitlab(config interface{}) error { - g := config.(*glab) + g := config.(*gitlabEventSource) if g == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/slack/config.go b/gateways/community/slack/config.go index 7467f21a40..dba70a7e38 100644 --- a/gateways/community/slack/config.go +++ b/gateways/community/slack/config.go @@ -18,6 +18,7 @@ package slack import ( "github.com/argoproj/argo-events/gateways/common" + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/rs/zerolog" corev1 "k8s.io/api/core/v1" @@ -33,8 +34,17 @@ type SlackEventSourceExecutor struct { Log zerolog.Logger } -// slackConfig -type slackConfig struct { +// +type RouteConfig struct { + route *gwcommon.Route + ses *slackEventSource + token string + clientset kubernetes.Interface + namespace string +} + +// slackEventSource +type slackEventSource struct { // Token for URL verification handshake Token *corev1.SecretKeySelector `json:"token"` // Webhook @@ -42,7 +52,7 @@ type slackConfig struct { } func parseEventSource(es string) (interface{}, error) { - var n *slackConfig + var n *slackEventSource err := yaml.Unmarshal([]byte(es), &n) if err != nil { return nil, err diff --git a/gateways/community/slack/config_test.go b/gateways/community/slack/config_test.go index d61fe38be9..b07e62fdd7 100644 --- a/gateways/community/slack/config_test.go +++ b/gateways/community/slack/config_test.go @@ -36,7 +36,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*slackConfig) + _, ok := ps.(*slackEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/slack/start.go b/gateways/community/slack/start.go index c104f5ddd5..573f5ee160 100644 --- a/gateways/community/slack/start.go +++ b/gateways/community/slack/start.go @@ -19,7 +19,6 @@ package slack import ( "bytes" "encoding/json" - "fmt" "net/http" "github.com/argoproj/argo-events/common" @@ -29,10 +28,6 @@ import ( "github.com/nlopes/slack/slackevents" ) -const ( - labelSlackToken = "slackToken" -) - var ( helper = gwcommon.NewWebhookHelper() ) @@ -41,36 +36,43 @@ func init() { go gwcommon.InitRouteChannels(helper) } +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.route +} + // RouteHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { var response string - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). + r := rc.route + + logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port). Str("http-method", request.Method).Logger() + logger.Info().Msg("request received") - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) - logger.Info().Msg("endpoint is not active") - common.SendErrorResponse(writer, response) + if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { + response := "endpoint is not active" + logger.Warn().Msg(response) + common.SendErrorResponse(writer, "") return } var buf bytes.Buffer if _, err := buf.ReadFrom(request.Body); err != nil { - logger.Error().Err(err).Msg("failed to parse request body") - common.SendInternalErrorResponse(writer, fmt.Sprintf("failed to parse request. err: %+v", err)) + response := "failed to parse request body" + logger.Error().Err(err).Msg(response) + common.SendInternalErrorResponse(writer, response) return } body := buf.String() - token := rc.Configs[labelSlackToken] - eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: token.(string)})) + eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: rc.token})) if e != nil { response = "failed to extract event" logger.Error().Msg(response) - common.SendInternalErrorResponse(writer, "failed to extract event") + common.SendInternalErrorResponse(writer, response) return } @@ -84,7 +86,10 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g return } writer.Header().Set("Content-Type", "text") - writer.Write([]byte(r.Challenge)) + if _, err := writer.Write([]byte(r.Challenge)); err != nil { + logger.Error().Err(err).Msg("failed to write the response for url verification") + // don't return, we want to keep this running to give user chance to retry + } } if eventsAPIEvent.Type == slackevents.CallbackEvent { @@ -95,7 +100,7 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g common.SendInternalErrorResponse(writer, response) return } - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- data + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- data } response = "request successfully processed" @@ -103,6 +108,14 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g common.SendSuccessResponse(writer, response) } +func (rc *RouteConfig) PostStart() error { + return nil +} + +func (rc *RouteConfig) PostStop() error { + return nil +} + // StartEventSource starts a event source func (ese *SlackEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) @@ -115,24 +128,24 @@ func (ese *SlackEventSourceExecutor) StartEventSource(eventSource *gateways.Even logger.Error().Err(err).Msg("failed to parse event source") return err } - sc := config.(*slackConfig) + ses := config.(*slackEventSource) - token, err := store.GetSecrets(ese.Clientset, ese.Namespace, sc.Token.Name, sc.Token.Key) + token, err := store.GetSecrets(ese.Clientset, ese.Namespace, ses.Token.Name, ses.Token.Key) if err != nil { logger.Error().Err(err).Msg("failed to retrieve token") return err } - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: sc.Hook, - Configs: map[string]interface{}{ - labelSlackToken: token, + return gwcommon.ProcessRoute(&RouteConfig{ + route: &gwcommon.Route{ + Logger: &ese.Log, + StartCh: make(chan struct{}), + Webhook: ses.Hook, + EventSource: eventSource, }, - Log: ese.Log, - EventSource: eventSource, - PostActivate: gwcommon.DefaultPostActivate, - PostStop: gwcommon.DefaultPostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + token: token, + clientset: ese.Clientset, + namespace: ese.Namespace, + ses: ses, }, helper, eventStream) } diff --git a/gateways/community/slack/start_test.go b/gateways/community/slack/start_test.go index da6cf61eb6..158cbcf11c 100644 --- a/gateways/community/slack/start_test.go +++ b/gateways/community/slack/start_test.go @@ -19,32 +19,37 @@ package slack import ( "bytes" "encoding/json" - "github.com/ghodss/yaml" - "github.com/nlopes/slack/slackevents" "io/ioutil" "net/http" "testing" gwcommon "github.com/argoproj/argo-events/gateways/common" + "github.com/ghodss/yaml" + "github.com/nlopes/slack/slackevents" "github.com/smartystreets/goconvey/convey" + "k8s.io/client-go/kubernetes/fake" ) func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRoute() + rc := &RouteConfig{ + route: gwcommon.GetFakeRoute(), + clientset: fake.NewSimpleClientset(), + namespace: "fake", + } - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } convey.Convey("Inactive route should return 404", func() { writer := &gwcommon.FakeHttpWriter{} - RouteActiveHandler(writer, &http.Request{}, rc) + rc.RouteHandler(writer, &http.Request{}) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) }) - rc.Configs[labelSlackToken] = "Jhj5dZrVaK7ZwHHjRyZWjbDl" - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true + rc.token = "Jhj5dZrVaK7ZwHHjRyZWjbDl" + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active = true convey.Convey("Test url verification request", func() { writer := &gwcommon.FakeHttpWriter{} @@ -56,9 +61,9 @@ func TestRouteActiveHandler(t *testing.T) { payload, err := yaml.Marshal(urlVer) convey.So(err, convey.ShouldBeNil) convey.So(payload, convey.ShouldNotBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(payload)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusInternalServerError) }) @@ -90,12 +95,12 @@ func TestRouteActiveHandler(t *testing.T) { convey.So(err, convey.ShouldBeNil) go func() { - <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh + <-helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh }() - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewBuffer(payload)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusInternalServerError) }) diff --git a/gateways/community/slack/validate.go b/gateways/community/slack/validate.go index eceac34931..5c54cee246 100644 --- a/gateways/community/slack/validate.go +++ b/gateways/community/slack/validate.go @@ -30,7 +30,7 @@ func (ese *SlackEventSourceExecutor) ValidateEventSource(ctx context.Context, es } func validateSlack(config interface{}) error { - sc := config.(*slackConfig) + sc := config.(*slackEventSource) if sc == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/storagegrid/config.go b/gateways/community/storagegrid/config.go index 1fa565cce8..52ad9f5942 100644 --- a/gateways/community/storagegrid/config.go +++ b/gateways/community/storagegrid/config.go @@ -21,7 +21,7 @@ import ( "time" "github.com/argoproj/argo-events/gateways/common" - + gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/ghodss/yaml" "github.com/rs/zerolog" ) @@ -31,8 +31,13 @@ type StorageGridEventSourceExecutor struct { Log zerolog.Logger } -// storageGrid contains configuration for storage grid sns -type storageGrid struct { +type RouteConfig struct { + route *gwcommon.Route + sges *storageGridEventSource +} + +// storageGridEventSource contains configuration for storage grid sns +type storageGridEventSource struct { // Webhook Hook *common.Webhook `json:"hook"` @@ -98,7 +103,7 @@ type storageGridNotification struct { } func parseEventSource(eventSource string) (interface{}, error) { - var s *storageGrid + var s *storageGridEventSource err := yaml.Unmarshal([]byte(eventSource), &s) if err != nil { return nil, err diff --git a/gateways/community/storagegrid/config_test.go b/gateways/community/storagegrid/config_test.go index e8c88b27e2..dac18610eb 100644 --- a/gateways/community/storagegrid/config_test.go +++ b/gateways/community/storagegrid/config_test.go @@ -38,7 +38,7 @@ func TestParseConfig(t *testing.T) { ps, err := parseEventSource(es) convey.So(err, convey.ShouldBeNil) convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*storageGrid) + _, ok := ps.(*storageGridEventSource) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/storagegrid/start.go b/gateways/community/storagegrid/start.go index a84b49aa2b..150085b99a 100644 --- a/gateways/community/storagegrid/start.go +++ b/gateways/community/storagegrid/start.go @@ -24,17 +24,12 @@ import ( "strings" "github.com/argoproj/argo-events/common" - "github.com/argoproj/argo-events/gateways" gwcommon "github.com/argoproj/argo-events/gateways/common" "github.com/joncalhoun/qson" "github.com/satori/go.uuid" ) -const ( - LabelStorageGridConfig = "storageGridConfig" -) - var ( helper = gwcommon.NewWebhookHelper() @@ -59,7 +54,7 @@ func generateUUID() uuid.UUID { } // filterEvent filters notification based on event filter in a gateway configuration -func filterEvent(notification *storageGridNotification, sg *storageGrid) bool { +func filterEvent(notification *storageGridNotification, sg *storageGridEventSource) bool { if sg.Events == nil { return true } @@ -72,7 +67,7 @@ func filterEvent(notification *storageGridNotification, sg *storageGrid) bool { } // filterName filters object key based on configured prefix and/or suffix -func filterName(notification *storageGridNotification, sg *storageGrid) bool { +func filterName(notification *storageGridNotification, sg *storageGridEventSource) bool { if sg.Filter == nil { return true } @@ -88,6 +83,10 @@ func filterName(notification *storageGridNotification, sg *storageGrid) bool { return true } +func (rc *RouteConfig) GetRoute() *gwcommon.Route { + return rc.route +} + // StartConfig runs a configuration func (ese *StorageGridEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { defer gateways.Recover(eventSource.Name) @@ -98,33 +97,41 @@ func (ese *StorageGridEventSourceExecutor) StartEventSource(eventSource *gateway ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") return err } - sg := config.(*storageGrid) - - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Configs: map[string]interface{}{ - LabelStorageGridConfig: sg, + sges := config.(*storageGridEventSource) + + return gwcommon.ProcessRoute(&RouteConfig{ + route: &gwcommon.Route{ + Webhook: sges.Hook, + EventSource: eventSource, + Logger: &ese.Log, + StartCh: make(chan struct{}), }, - Webhook: sg.Hook, - Log: ese.Log, - EventSource: eventSource, - PostActivate: gwcommon.DefaultPostActivate, - PostStop: gwcommon.DefaultPostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), + sges: sges, }, helper, eventStream) } -// routeActiveHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { - logger := rc.Log.With().Str("event-source-name", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint).Str("port", rc.Webhook.Port).Str("method", http.MethodHead).Logger() +func (rc *RouteConfig) PostStart() error { + return nil +} + +func (rc *RouteConfig) PostStop() error { + return nil +} - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { +// RouteHandler handles new route +func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { + logger := rc.route.Logger.With(). + Str("event-source-name", rc.route.EventSource.Name). + Str("endpoint", rc.route.Webhook.Endpoint).Str("port", rc.route.Webhook.Port). + Str("method", http.MethodHead).Logger() + + if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { logger.Warn().Msg("inactive route") common.SendErrorResponse(writer, "route is not valid") return } - rc.Log.Info().Str("event-source-name", rc.EventSource.Name).Str("method", http.MethodHead).Msg("received a request") + logger.Info().Str("event-source-name", rc.route.EventSource.Name).Str("method", http.MethodHead).Msg("received a request") body, err := ioutil.ReadAll(request.Body) if err != nil { logger.Error().Err(err).Msg("failed to parse request body") @@ -159,11 +166,9 @@ func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *g return } - storageGridConfig := rc.Configs[LabelStorageGridConfig].(*storageGrid) - - if filterEvent(notification, storageGridConfig) && filterName(notification, storageGridConfig) { + if filterEvent(notification, rc.sges) && filterName(notification, rc.sges) { logger.Info().Msg("new event received, dispatching to gateway client") - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- b + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- b return } diff --git a/gateways/community/storagegrid/start_test.go b/gateways/community/storagegrid/start_test.go index 24e97492f3..e0d7e040e5 100644 --- a/gateways/community/storagegrid/start_test.go +++ b/gateways/community/storagegrid/start_test.go @@ -27,7 +27,8 @@ import ( "testing" ) -var notification = ` +var ( + notification = ` { "Action": "Publish", "Message": { @@ -70,11 +71,14 @@ var notification = ` "Version": "2010-03-31" } ` + rc = &RouteConfig{ + route: gwcommon.GetFakeRoute(), + } +) func TestRouteActiveHandler(t *testing.T) { convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRoute() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ + helper.ActiveEndpoints[rc.route.Webhook.Endpoint] = &gwcommon.Endpoint{ DataCh: make(chan []byte), } @@ -83,29 +87,28 @@ func TestRouteActiveHandler(t *testing.T) { writer := &gwcommon.FakeHttpWriter{} convey.Convey("Inactive route should return error", func() { - pbytes, err := yaml.Marshal(ps.(*storageGrid)) + pbytes, err := yaml.Marshal(ps.(*storageGridEventSource)) convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) }) convey.Convey("Active route should return success", func() { - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true - rc.Configs[LabelStorageGridConfig] = ps.(*storageGrid) + helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active = true + rc.sges = ps.(*storageGridEventSource) dataCh := make(chan []byte) go func() { - resp := <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh + resp := <-helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh dataCh <- resp }() - RouteActiveHandler(writer, &http.Request{ + rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewReader([]byte(notification))), - }, rc) + }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) }) - }) } @@ -126,7 +129,7 @@ func TestFilterEvent(t *testing.T) { convey.So(err, convey.ShouldBeNil) convey.So(sg, convey.ShouldNotBeNil) - ok := filterEvent(sg, ps.(*storageGrid)) + ok := filterEvent(sg, ps.(*storageGridEventSource)) convey.So(ok, convey.ShouldEqual, true) }) } @@ -140,7 +143,7 @@ func TestFilterName(t *testing.T) { convey.So(err, convey.ShouldBeNil) convey.So(sg, convey.ShouldNotBeNil) - ok := filterName(sg, ps.(*storageGrid)) + ok := filterName(sg, ps.(*storageGridEventSource)) convey.So(ok, convey.ShouldEqual, true) }) } diff --git a/gateways/community/storagegrid/validate.go b/gateways/community/storagegrid/validate.go index 2be908877c..e23bd84908 100644 --- a/gateways/community/storagegrid/validate.go +++ b/gateways/community/storagegrid/validate.go @@ -28,7 +28,7 @@ func (ese *StorageGridEventSourceExecutor) ValidateEventSource(ctx context.Conte } func validateStorageGrid(config interface{}) error { - sg := config.(*storageGrid) + sg := config.(*storageGridEventSource) if sg == nil { return gwcommon.ErrNilEventSource } diff --git a/gateways/community/trello/Dockerfile b/gateways/community/trello/Dockerfile deleted file mode 100644 index 2df46e146a..0000000000 --- a/gateways/community/trello/Dockerfile +++ /dev/null @@ -1,3 +0,0 @@ -FROM scratch -COPY dist/trello-gateway /bin/ -ENTRYPOINT [ "/bin/trello-gateway" ] diff --git a/gateways/community/trello/cmd/main.go b/gateways/community/trello/cmd/main.go deleted file mode 100644 index 913dac80b6..0000000000 --- a/gateways/community/trello/cmd/main.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 main - -import ( - "os" - - "github.com/argoproj/argo-events/common" - "github.com/argoproj/argo-events/gateways" - "github.com/argoproj/argo-events/gateways/community/trello" - "k8s.io/client-go/kubernetes" -) - -func main() { - kubeConfig, _ := os.LookupEnv(common.EnvVarKubeConfig) - restConfig, err := common.GetClientConfig(kubeConfig) - if err != nil { - panic(err) - } - clientset := kubernetes.NewForConfigOrDie(restConfig) - namespace, ok := os.LookupEnv(common.EnvVarGatewayNamespace) - if !ok { - panic("namespace is not provided") - } - gateways.StartGateway(&trello.TrelloEventSourceExecutor{ - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), - Clientset: clientset, - Namespace: namespace, - }) -} diff --git a/gateways/community/trello/config.go b/gateways/community/trello/config.go deleted file mode 100644 index 40975a45a3..0000000000 --- a/gateways/community/trello/config.go +++ /dev/null @@ -1,54 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "github.com/argoproj/argo-events/gateways/common" - "github.com/ghodss/yaml" - "github.com/rs/zerolog" - corev1 "k8s.io/api/core/v1" - "k8s.io/client-go/kubernetes" -) - -type TrelloEventSourceExecutor struct { - Log zerolog.Logger - // Clientset is kubernetes client - Clientset kubernetes.Interface - // Namespace where gateway is deployed - Namespace string -} - -type trello struct { - // Webhook - Hook *common.Webhook `json:"hook"` - // ApiKey for client - ApiKey *corev1.SecretKeySelector `json:"apiKey"` - // Token for client - Token *corev1.SecretKeySelector `json:"token"` - // Description for webhook - // +optional - Description string `json:"description,omitempty"` -} - -func parseEventSource(es string) (interface{}, error) { - var n *trello - err := yaml.Unmarshal([]byte(es), &n) - if err != nil { - return nil, err - } - return n, nil -} diff --git a/gateways/community/trello/config_test.go b/gateways/community/trello/config_test.go deleted file mode 100644 index 26d63464df..0000000000 --- a/gateways/community/trello/config_test.go +++ /dev/null @@ -1,47 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "github.com/smartystreets/goconvey/convey" - "testing" -) - -var es = ` -hook: - endpoint: "/" - port: "8080" - url: "testurl" -apiKey: - key: api - name: trello -token: - key: token - name: trello -url: "URL to register on trello" -description: "test hook" -` - -func TestParseConfig(t *testing.T) { - convey.Convey("Given a trello event source, parse it", t, func() { - ps, err := parseEventSource(es) - convey.So(err, convey.ShouldBeNil) - convey.So(ps, convey.ShouldNotBeNil) - _, ok := ps.(*trello) - convey.So(ok, convey.ShouldEqual, true) - }) -} diff --git a/gateways/community/trello/start.go b/gateways/community/trello/start.go deleted file mode 100644 index ca62fecf2b..0000000000 --- a/gateways/community/trello/start.go +++ /dev/null @@ -1,134 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "fmt" - "io/ioutil" - "net/http" - - trellolib "github.com/adlio/trello" - "github.com/argoproj/argo-events/common" - "github.com/argoproj/argo-events/gateways" - gwcommon "github.com/argoproj/argo-events/gateways/common" - "github.com/argoproj/argo-events/store" -) - -const ( - LabelTrelloConfig = "trelloConfig" - LabelTrelloClient = "trelloClient" -) - -var ( - helper = gwcommon.NewWebhookHelper() -) - -func init() { - go gwcommon.InitRouteChannels(helper) -} - -// routeActiveHandler handles new route -func RouteActiveHandler(writer http.ResponseWriter, request *http.Request, rc *gwcommon.RouteConfig) { - var response string - - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port). - Str("http-method", request.Method).Logger() - logger.Info().Msg("request received") - - if !helper.ActiveEndpoints[rc.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.Webhook.Endpoint, rc.Webhook.Method) - logger.Info().Msg("endpoint is not active") - common.SendErrorResponse(writer, response) - return - } - - body, err := ioutil.ReadAll(request.Body) - if err != nil { - logger.Error().Err(err).Msg("failed to parse request body") - return - } - - helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh <- body - - response = "request successfully processed" - logger.Info().Msg(response) - common.SendSuccessResponse(writer, response) -} - -func (ese *TrelloEventSourceExecutor) PostActivate(rc *gwcommon.RouteConfig) error { - logger := rc.Log.With().Str("event-source", rc.EventSource.Name).Str("endpoint", rc.Webhook.Endpoint). - Str("port", rc.Webhook.Port).Logger() - - tl := rc.Configs[LabelTrelloConfig].(*trello) - - logger.Info().Msg("retrieving apikey and token") - apiKey, err := store.GetSecrets(ese.Clientset, ese.Namespace, tl.ApiKey.Name, tl.ApiKey.Key) - if err != nil { - logger.Error().Err(err).Msg("failed to retrieve api key") - return err - } - token, err := store.GetSecrets(ese.Clientset, ese.Namespace, tl.Token.Name, tl.Token.Key) - if err != nil { - logger.Error().Err(err).Msg("failed to retrieve token") - return err - } - - client := trellolib.NewClient(apiKey, token) - - formattedUrl := gwcommon.GenerateFormattedURL(tl.Hook) - - if err = client.CreateWebhook(&trellolib.Webhook{ - Active: true, - Description: tl.Description, - CallbackURL: formattedUrl, - }); err != nil { - logger.Error().Err(err).Msg("failed to create webhook") - return err - } - - rc.Configs[LabelTrelloClient] = client - - logger.Info().Msg("webhook created") - return nil -} - -// StartConfig runs a configuration -func (ese *TrelloEventSourceExecutor) StartEventSource(eventSource *gateways.EventSource, eventStream gateways.Eventing_StartEventSourceServer) error { - defer gateways.Recover(eventSource.Name) - - ese.Log.Info().Str("event-source-name", eventSource.Name).Msg("operating on event source") - config, err := parseEventSource(eventSource.Data) - if err != nil { - ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") - return err - } - tl := config.(*trello) - - return gwcommon.ProcessRoute(&gwcommon.RouteConfig{ - Webhook: tl.Hook, - Configs: map[string]interface{}{ - LabelTrelloConfig: tl, - }, - Log: ese.Log, - EventSource: eventSource, - PostActivate: ese.PostActivate, - PostStop: gwcommon.DefaultPostStop, - RouteActiveHandler: RouteActiveHandler, - StartCh: make(chan struct{}), - }, helper, eventStream) -} diff --git a/gateways/community/trello/start_test.go b/gateways/community/trello/start_test.go deleted file mode 100644 index 60ffb00bdd..0000000000 --- a/gateways/community/trello/start_test.go +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "bytes" - "github.com/argoproj/argo-events/common" - "io/ioutil" - "k8s.io/client-go/kubernetes/fake" - "net/http" - "testing" - - gwcommon "github.com/argoproj/argo-events/gateways/common" - "github.com/ghodss/yaml" - "github.com/smartystreets/goconvey/convey" - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -func TestRouteActiveHandler(t *testing.T) { - convey.Convey("Given a route configuration", t, func() { - rc := gwcommon.GetFakeRoute() - helper.ActiveEndpoints[rc.Webhook.Endpoint] = &gwcommon.Endpoint{ - DataCh: make(chan []byte), - } - - ps, err := parseEventSource(es) - convey.So(err, convey.ShouldBeNil) - rc.Configs[LabelTrelloConfig] = ps.(*trello) - writer := &gwcommon.FakeHttpWriter{} - - convey.Convey("Inactive route should return error", func() { - pbytes, err := yaml.Marshal(ps.(*trello)) - convey.So(err, convey.ShouldBeNil) - RouteActiveHandler(writer, &http.Request{ - Body: ioutil.NopCloser(bytes.NewReader(pbytes)), - }, rc) - convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) - }) - - convey.Convey("Active route should return success", func() { - helper.ActiveEndpoints[rc.Webhook.Endpoint].Active = true - dataCh := make(chan []byte) - go func() { - resp := <-helper.ActiveEndpoints[rc.Webhook.Endpoint].DataCh - dataCh <- resp - }() - - RouteActiveHandler(writer, &http.Request{ - Body: ioutil.NopCloser(bytes.NewReader([]byte("fake notification"))), - }, rc) - convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) - data := <-dataCh - convey.So(string(data), convey.ShouldEqual, "fake notification") - }) - - convey.Convey("Run post activate", func() { - ese := &TrelloEventSourceExecutor{ - Clientset: fake.NewSimpleClientset(), - Log: common.GetLoggerContext(common.LoggerConf()).Logger(), - Namespace: "fake", - } - secret, err := ese.Clientset.CoreV1().Secrets(ese.Namespace).Create(&corev1.Secret{ - ObjectMeta: metav1.ObjectMeta{ - Name: "trello", - Namespace: ese.Namespace, - }, - Data: map[string][]byte{ - "api": []byte("api"), - "token": []byte("token"), - }, - }) - convey.So(err, convey.ShouldBeNil) - convey.So(secret, convey.ShouldNotBeNil) - - err = ese.PostActivate(rc) - convey.So(err, convey.ShouldNotBeNil) - }) - - }) -} diff --git a/gateways/community/trello/validate.go b/gateways/community/trello/validate.go deleted file mode 100644 index dbd8a35a20..0000000000 --- a/gateways/community/trello/validate.go +++ /dev/null @@ -1,44 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "context" - "fmt" - "github.com/argoproj/argo-events/gateways" - gwcommon "github.com/argoproj/argo-events/gateways/common" -) - -// ValidateEventSource validates a s3 event source -func (ese *TrelloEventSourceExecutor) ValidateEventSource(ctx context.Context, eventSource *gateways.EventSource) (*gateways.ValidEventSource, error) { - return gwcommon.ValidateGatewayEventSource(eventSource.Data, parseEventSource, validateTrello) -} - -// validates trello config -func validateTrello(config interface{}) error { - tl := config.(*trello) - if tl == nil { - return gwcommon.ErrNilEventSource - } - if tl.Token == nil { - return fmt.Errorf("token can't be empty") - } - if tl.ApiKey == nil { - return fmt.Errorf("api key can't be empty") - } - return gwcommon.ValidateWebhook(tl.Hook) -} diff --git a/gateways/community/trello/validate_test.go b/gateways/community/trello/validate_test.go deleted file mode 100644 index 35b1b5a30d..0000000000 --- a/gateways/community/trello/validate_test.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -Copyright 2018 BlackRock, Inc. - -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 trello - -import ( - "context" - "testing" - - "github.com/argoproj/argo-events/gateways" - "github.com/smartystreets/goconvey/convey" -) - -var ( - configKey = "testConfig" - configId = "1234" - validConfig = ` -hook: - endpoint: "/" - port: "8080" - url: "testurl" -apiKey: - key: api - name: trello -token: - key: token - name: trello -url: "URL to register on trello" -description: "test hook" -` - - invalidConfig = ` -endpoint: "/" -port: "8080" -` -) - -func TestTrelloEventSourceExecutor_ValidateEventSource(t *testing.T) { - convey.Convey("Given a valid trello event source spec, parse it and make sure no error occurs", t, func() { - ese := &TrelloEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Name: configKey, - Id: configId, - Data: validConfig, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeTrue) - }) - - convey.Convey("Given an invalid trello event source spec, parse it and make sure error occurs", t, func() { - ese := &TrelloEventSourceExecutor{} - valid, _ := ese.ValidateEventSource(context.Background(), &gateways.EventSource{ - Data: invalidConfig, - Id: configId, - Name: configKey, - }) - convey.So(valid, convey.ShouldNotBeNil) - convey.So(valid.IsValid, convey.ShouldBeFalse) - convey.So(valid.Reason, convey.ShouldNotBeEmpty) - }) -} From 8a3d018019606056ef48f966a4997d3da7a6c973 Mon Sep 17 00:00:00 2001 From: vpage Date: Tue, 19 Mar 2019 17:35:37 -0400 Subject: [PATCH 03/11] refactor(): route config --- gateways/community/aws-sns/start.go | 49 ++++++++++++------------- gateways/community/aws-sqs/start.go | 1 - gateways/community/github/config.go | 1 + gateways/community/github/start.go | 33 +++++++---------- gateways/community/gitlab/start.go | 23 +++++------- gateways/community/slack/start.go | 38 +++++++++---------- gateways/community/storagegrid/start.go | 9 +++-- gateways/event-sources.go | 1 + 8 files changed, 72 insertions(+), 83 deletions(-) diff --git a/gateways/community/aws-sns/start.go b/gateways/community/aws-sns/start.go index 781996fb0e..6e8bcd93c5 100644 --- a/gateways/community/aws-sns/start.go +++ b/gateways/community/aws-sns/start.go @@ -36,31 +36,33 @@ func init() { go gwcommon.InitRouteChannels(helper) } +// GetRoute returns the route func (rc *RouteConfig) GetRoute() *gwcommon.Route { return rc.Route } // RouteHandler handles new routes func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - var response string - r := rc.Route - logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + + logger := r.Logger.With(). + Str("event-source", r.EventSource.Name). + Str("endpoint", r.Webhook.Endpoint). Str("port", r.Webhook.Port). Str("http-method", request.Method).Logger() + logger.Info().Msg("request received") if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", r.Webhook.Endpoint, r.Webhook.Method) logger.Info().Msg("endpoint is not active") - common.SendErrorResponse(writer, response) + common.SendErrorResponse(writer, "") return } body, err := ioutil.ReadAll(request.Body) if err != nil { logger.Error().Err(err).Msg("failed to parse request body") - common.SendErrorResponse(writer, "failed to parse request") + common.SendErrorResponse(writer, "") return } @@ -68,22 +70,20 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re err = yaml.Unmarshal(body, &snspayload) if err != nil { logger.Error().Err(err).Msg("failed to convert request payload into snses payload") - common.SendErrorResponse(writer, "failed to marshal request") + common.SendErrorResponse(writer, "") return } - sc := rc.snses - switch snspayload.Type { case messageTypeSubscriptionConfirmation: awsSession := rc.session out, err := awsSession.ConfirmSubscription(&snslib.ConfirmSubscriptionInput{ - TopicArn: &sc.TopicArn, + TopicArn: &rc.snses.TopicArn, Token: &snspayload.Token, }) if err != nil { logger.Error().Err(err).Msg("failed to send confirmation response to amazon") - common.SendErrorResponse(writer, "failed to confirm subscription") + common.SendErrorResponse(writer, "") return } rc.subscriptionArn = out.SubscriptionArn @@ -92,40 +92,40 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body } - response = "request successfully processed" - logger.Info().Msg(response) - common.SendSuccessResponse(writer, response) + logger.Info().Msg("request successfully processed") } // PostStart subscribes to the sns topic func (rc *RouteConfig) PostStart() error { r := rc.Route - logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). - Str("port", r.Webhook.Port).Logger() + + logger := r.Logger.With(). + Str("event-source", r.EventSource.Name). + Str("endpoint", r.Webhook.Endpoint). + Str("port", r.Webhook.Port). + Str("topic-arn", rc.snses.TopicArn). + Logger() + logger.Info().Msg("subscribing to sns topic") sc := rc.snses creds, err := gwcommon.GetAWSCreds(rc.clientset, rc.namespace, sc.AccessKey, sc.SecretKey) if err != nil { - logger.Error().Err(err).Msg("failed to get aws credentials") + return fmt.Errorf("failed to get aws credentials. err: %+v", err) } awsSession, err := gwcommon.GetAWSSession(creds, sc.Region) if err != nil { - logger.Error().Err(err).Msg("failed to create new session") - return err + return fmt.Errorf("failed to create aws session. err: %+v", err) } - logger.Info().Msg("subscribing to sns topic") rc.session = snslib.New(awsSession) formattedUrl := gwcommon.GenerateFormattedURL(sc.Hook) - if _, err := rc.session.Subscribe(&snslib.SubscribeInput{ Endpoint: &formattedUrl, Protocol: &snsProtocol, TopicArn: &sc.TopicArn, }); err != nil { - logger.Error().Err(err).Msg("failed to send subscribe request") - return err + return fmt.Errorf("failed to send subscribe request. err: %+v", err) } return nil @@ -136,8 +136,7 @@ func (rc *RouteConfig) PostStop() error { if _, err := rc.session.Unsubscribe(&snslib.UnsubscribeInput{ SubscriptionArn: rc.subscriptionArn, }); err != nil { - rc.Route.Logger.Error().Err(err).Str("event-source-name", rc.Route.EventSource.Name).Msg("failed to unsubscribe") - return err + return fmt.Errorf("failed to unsubscribe. err: %+v", err) } return nil } diff --git a/gateways/community/aws-sqs/start.go b/gateways/community/aws-sqs/start.go index dfeff38374..b564aa8ac9 100644 --- a/gateways/community/aws-sqs/start.go +++ b/gateways/community/aws-sqs/start.go @@ -29,7 +29,6 @@ func (ese *SQSEventSourceExecutor) StartEventSource(eventSource *gateways.EventS config, err := parseEventSource(eventSource.Data) if err != nil { ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") - return err } diff --git a/gateways/community/github/config.go b/gateways/community/github/config.go index 32a216be05..ec82a9d1c6 100644 --- a/gateways/community/github/config.go +++ b/gateways/community/github/config.go @@ -35,6 +35,7 @@ type GithubEventSourceExecutor struct { Namespace string } +// RouteConfig contains information about the route type RouteConfig struct { route *gwcommon.Route ges *githubEventSource diff --git a/gateways/community/github/start.go b/gateways/community/github/start.go index 1609f861c2..15aea2e06a 100644 --- a/gateways/community/github/start.go +++ b/gateways/community/github/start.go @@ -132,19 +132,14 @@ func (rc *RouteConfig) PostStart() error { return nil } +// PostStop runs after event source is stopped func (rc *RouteConfig) PostStop() error { - r := rc.route - gc := rc.ges - client := rc.client - hook := rc.hook - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() - if _, err := client.Repositories.DeleteHook(ctx, gc.Owner, gc.Repository, *hook.ID); err != nil { - r.Logger.Error().Err(err).Str("event-source-name", r.EventSource.Name).Msg("failed to delete github hook") - return err + if _, err := rc.client.Repositories.DeleteHook(ctx, rc.ges.Owner, rc.ges.Repository, *rc.hook.ID); err != nil { + return fmt.Errorf("failed to delete hook. err: %+v", err) } - r.Logger.Info().Str("event-source-name", r.EventSource.Name).Int64("hook-id", *hook.ID).Msg("github hook deleted") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int64("hook-id", *rc.hook.ID).Msg("github hook deleted") return nil } @@ -156,6 +151,7 @@ func (ese *GithubEventSourceExecutor) StartEventSource(eventSource *gateways.Eve config, err := parseEventSource(eventSource.Data) if err != nil { ese.Log.Error().Err(err).Str("event-source-name", eventSource.Name).Msg("failed to parse event source") + return err } gc := config.(*githubEventSource) @@ -187,19 +183,19 @@ func parseValidateRequest(r *http.Request, secret []byte) ([]byte, error) { // routeActiveHandler handles new route func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - var response string - r := rc.route - logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + logger := r.Logger.With(). + Str("event-source", r.EventSource.Name). + Str("endpoint", r.Webhook.Endpoint). Str("port", r.Webhook.Port). - Str("http-method", request.Method).Logger() + Logger() + logger.Info().Msg("request received") if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", r.Webhook.Endpoint, r.Webhook.Method) logger.Info().Msg("endpoint is not active") - common.SendErrorResponse(writer, response) + common.SendErrorResponse(writer, "") return } @@ -211,12 +207,11 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re body, err := parseValidateRequest(request, []byte(secret)) if err != nil { logger.Error().Err(err).Msg("request is not valid event notification") - common.SendErrorResponse(writer, fmt.Sprintf("invalid event notification")) + common.SendErrorResponse(writer, "") return } helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh <- body - response = "request successfully processed" - logger.Info().Msg(response) - common.SendSuccessResponse(writer, response) + logger.Info().Msg("request successfully processed") + common.SendSuccessResponse(writer, "") } diff --git a/gateways/community/gitlab/start.go b/gateways/community/gitlab/start.go index 8536f3e5ed..734db1d1ca 100644 --- a/gateways/community/gitlab/start.go +++ b/gateways/community/gitlab/start.go @@ -91,7 +91,7 @@ func (rc *RouteConfig) PostStart() error { return fmt.Errorf("failed to check if hook is already registered with the event %s. unknown event", rc.ges.Event) } if reflect.New(elem.Type().Elem()).Bool() && h.URL == formattedUrl { - rc.route.Logger.Info().Str("event-source", rc.route.EventSource.Name).Msg("hook is already configured") + rc.route.Logger.Warn().Str("event-source", rc.route.EventSource.Name).Msg("hook is already configured") return nil } } @@ -108,8 +108,7 @@ func (rc *RouteConfig) PostStart() error { func (rc *RouteConfig) PostStop() error { if _, err := rc.client.Projects.DeleteProjectHook(rc.ges.ProjectId, rc.hook.ID); err != nil { - rc.route.Logger.Error().Err(err).Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("failed to delete gitlab hook") - return err + return fmt.Errorf("failed to delete hook. err: %+v", err) } rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("gitlab hook deleted") return nil @@ -117,32 +116,30 @@ func (rc *RouteConfig) PostStop() error { // routeActiveHandler handles new route func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - var response string - - logger := rc.route.Logger.With().Str("event-source", rc.route.EventSource.Name).Str("endpoint", rc.route.Webhook.Endpoint). + logger := rc.route.Logger.With(). + Str("event-source", rc.route.EventSource.Name). + Str("endpoint", rc.route.Webhook.Endpoint). Str("port", rc.route.Webhook.Port). - Str("http-method", request.Method).Logger() + Logger() logger.Info().Msg("request received") if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { - response = fmt.Sprintf("the route: endpoint %s and method %s is deactived", rc.route.Webhook.Endpoint, rc.route.Webhook.Method) logger.Info().Msg("endpoint is not active") - common.SendErrorResponse(writer, response) + common.SendErrorResponse(writer, "") return } body, err := ioutil.ReadAll(request.Body) if err != nil { logger.Error().Err(err).Msg("failed to parse request body") - common.SendErrorResponse(writer, fmt.Sprintf("failed to parse request. err: %+v", err)) + common.SendErrorResponse(writer, "") return } helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- body - response = "request successfully processed" - logger.Info().Msg(response) - common.SendSuccessResponse(writer, response) + logger.Info().Msg("request successfully processed") + common.SendSuccessResponse(writer, "") } // StartEventSource starts an event source diff --git a/gateways/community/slack/start.go b/gateways/community/slack/start.go index 573f5ee160..2fe9479f9d 100644 --- a/gateways/community/slack/start.go +++ b/gateways/community/slack/start.go @@ -42,37 +42,35 @@ func (rc *RouteConfig) GetRoute() *gwcommon.Route { // RouteHandler handles new route func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { - var response string - r := rc.route - logger := r.Logger.With().Str("event-source", r.EventSource.Name).Str("endpoint", r.Webhook.Endpoint). + logger := r.Logger.With(). + Str("event-source", r.EventSource.Name). + Str("endpoint", r.Webhook.Endpoint). Str("port", r.Webhook.Port). - Str("http-method", request.Method).Logger() + Str("http-method", request.Method). + Logger() logger.Info().Msg("request received") if !helper.ActiveEndpoints[r.Webhook.Endpoint].Active { - response := "endpoint is not active" - logger.Warn().Msg(response) + logger.Warn().Msg("endpoint is not active") common.SendErrorResponse(writer, "") return } var buf bytes.Buffer if _, err := buf.ReadFrom(request.Body); err != nil { - response := "failed to parse request body" - logger.Error().Err(err).Msg(response) - common.SendInternalErrorResponse(writer, response) + logger.Error().Err(err).Msg("failed to parse request body") + common.SendInternalErrorResponse(writer, "") return } body := buf.String() eventsAPIEvent, e := slackevents.ParseEvent(json.RawMessage(body), slackevents.OptionVerifyToken(&slackevents.TokenComparator{VerificationToken: rc.token})) if e != nil { - response = "failed to extract event" - logger.Error().Msg(response) - common.SendInternalErrorResponse(writer, response) + logger.Error().Msg("failed to extract event") + common.SendInternalErrorResponse(writer, "") return } @@ -80,9 +78,8 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re var r *slackevents.ChallengeResponse err := json.Unmarshal([]byte(body), &r) if err != nil { - response = "failed to verify the challenge" - logger.Error().Msg(response) - common.SendInternalErrorResponse(writer, response) + logger.Error().Msg("failed to verify the challenge") + common.SendInternalErrorResponse(writer, "") return } writer.Header().Set("Content-Type", "text") @@ -95,17 +92,15 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re if eventsAPIEvent.Type == slackevents.CallbackEvent { data, err := json.Marshal(eventsAPIEvent.InnerEvent.Data) if err != nil { - response = "failed to marshal event data" - logger.Error().Err(err).Msg(response) - common.SendInternalErrorResponse(writer, response) + logger.Error().Err(err).Msg("failed to marshal event data") + common.SendInternalErrorResponse(writer, "") return } helper.ActiveEndpoints[rc.route.Webhook.Endpoint].DataCh <- data } - response = "request successfully processed" - logger.Info().Msg(response) - common.SendSuccessResponse(writer, response) + logger.Info().Msg("request successfully processed") + common.SendSuccessResponse(writer, "") } func (rc *RouteConfig) PostStart() error { @@ -128,6 +123,7 @@ func (ese *SlackEventSourceExecutor) StartEventSource(eventSource *gateways.Even logger.Error().Err(err).Msg("failed to parse event source") return err } + ses := config.(*slackEventSource) token, err := store.GetSecrets(ese.Clientset, ese.Namespace, ses.Token.Name, ses.Token.Key) diff --git a/gateways/community/storagegrid/start.go b/gateways/community/storagegrid/start.go index 150085b99a..cd169f644b 100644 --- a/gateways/community/storagegrid/start.go +++ b/gateways/community/storagegrid/start.go @@ -122,12 +122,13 @@ func (rc *RouteConfig) PostStop() error { func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Request) { logger := rc.route.Logger.With(). Str("event-source-name", rc.route.EventSource.Name). - Str("endpoint", rc.route.Webhook.Endpoint).Str("port", rc.route.Webhook.Port). - Str("method", http.MethodHead).Logger() + Str("endpoint", rc.route.Webhook.Endpoint). + Str("port", rc.route.Webhook.Port). + Logger() if !helper.ActiveEndpoints[rc.route.Webhook.Endpoint].Active { logger.Warn().Msg("inactive route") - common.SendErrorResponse(writer, "route is not valid") + common.SendErrorResponse(writer, "") return } @@ -135,7 +136,7 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re body, err := ioutil.ReadAll(request.Body) if err != nil { logger.Error().Err(err).Msg("failed to parse request body") - common.SendErrorResponse(writer, "failed to parse request body") + common.SendErrorResponse(writer, "") return } diff --git a/gateways/event-sources.go b/gateways/event-sources.go index 5868c119c4..b558f84d07 100644 --- a/gateways/event-sources.go +++ b/gateways/event-sources.go @@ -172,6 +172,7 @@ func (gc *GatewayConfig) startEventSources(eventSources map[string]*EventSourceC Data: eventSource.Data.Config, }) if err != nil { + gc.Log.Error().Err(err).Str("event-source-name", eventSource.Data.Src).Msg("error occurred while starting event source") gc.StatusCh <- EventSourceStatus{ Phase: v1alpha1.NodePhaseError, Message: "failed_to_receive_event_stream", From 0d62b353ad3d3f12517dd55772b15c5c973f5ab5 Mon Sep 17 00:00:00 2001 From: VaibhavPage Date: Tue, 19 Mar 2019 22:45:54 -0400 Subject: [PATCH 04/11] fix(): bug introduced from #221 --- examples/gateways/github-configmap.yaml | 1 + examples/gateways/gitlab-configmap.yaml | 1 + gateways/common/webhook.go | 5 ++++ gateways/community/github/config.go | 2 ++ gateways/community/github/config_test.go | 1 + gateways/community/github/start.go | 21 ++++++++++++++-- gateways/community/github/validate.go | 3 +++ gateways/community/github/validate_test.go | 1 + gateways/community/gitlab/config.go | 2 ++ gateways/community/gitlab/config_test.go | 1 + gateways/community/gitlab/start.go | 29 ++++++---------------- gateways/community/gitlab/validate.go | 3 +++ gateways/community/gitlab/validate_test.go | 1 + gateways/gateway.go | 7 +++--- 14 files changed, 52 insertions(+), 26 deletions(-) diff --git a/examples/gateways/github-configmap.yaml b/examples/gateways/github-configmap.yaml index d8102dc53f..7930457657 100644 --- a/examples/gateways/github-configmap.yaml +++ b/examples/gateways/github-configmap.yaml @@ -4,6 +4,7 @@ metadata: name: github-gateway-configmap data: project_1: |- + id: 1234 owner: "owner-example" repository: "repo-example" hook: diff --git a/examples/gateways/gitlab-configmap.yaml b/examples/gateways/gitlab-configmap.yaml index 205ab86136..9eee3acfad 100644 --- a/examples/gateways/gitlab-configmap.yaml +++ b/examples/gateways/gitlab-configmap.yaml @@ -4,6 +4,7 @@ metadata: name: gitlab-gateway-configmap data: project_1: |- + id: 1234 projectId: "1" hook: endpoint: "/push" diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index 36205d8117..c1560cae4e 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -227,23 +227,28 @@ func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways func ProcessRoute(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { r := rc.GetRoute() + r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("validating the route") if err := validateRoute(rc.GetRoute()); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred validating route") return err } + r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("activating the route") activateRoute(rc, helper) + r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("running post start") if err := rc.PostStart(); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post start") return err } + r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("processing channels") if err := processChannels(rc, helper, eventStream); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in process channel") return err } + r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("running post stop") if err := rc.PostStop(); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post stop") } diff --git a/gateways/community/github/config.go b/gateways/community/github/config.go index ec82a9d1c6..08ee5c9801 100644 --- a/gateways/community/github/config.go +++ b/gateways/community/github/config.go @@ -47,6 +47,8 @@ type RouteConfig struct { // githubEventSource contains information to setup a github project integration type githubEventSource struct { + // Webhook ID + Id int64 `json:"id"` // Webhook Hook *common.Webhook `json:"hook"` // GitHub owner name i.e. argoproj diff --git a/gateways/community/github/config_test.go b/gateways/community/github/config_test.go index 688ee574f0..08bb2e6c1f 100644 --- a/gateways/community/github/config_test.go +++ b/gateways/community/github/config_test.go @@ -22,6 +22,7 @@ import ( ) var es = ` +id: 1234 hook: endpoint: "/push" port: "12000" diff --git a/gateways/community/github/start.go b/gateways/community/github/start.go index 15aea2e06a..3e0df19b0b 100644 --- a/gateways/community/github/start.go +++ b/gateways/community/github/start.go @@ -99,6 +99,7 @@ func (rc *RouteConfig) PostStart() error { Events: gc.Events, Active: gh.Bool(gc.Active), Config: hookConfig, + ID: &rc.ges.Id, } rc.client = gh.NewClient(PATTransport.Client()) @@ -128,7 +129,17 @@ func (rc *RouteConfig) PostStart() error { } } - rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int64("hook-id", *hook.ID).Msg("github hook created") + if hook == nil { + ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) + defer cancel() + hook, _, err = rc.client.Repositories.GetHook(ctx, gc.Owner, gc.Repository, rc.ges.Id) + if err != nil { + return fmt.Errorf("failed to get existing webhook with id %d. err: %+v", rc.ges.Id, err) + } + } + + rc.hook = hook + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Msg("github hook created") return nil } @@ -139,7 +150,7 @@ func (rc *RouteConfig) PostStop() error { if _, err := rc.client.Repositories.DeleteHook(ctx, rc.ges.Owner, rc.ges.Repository, *rc.hook.ID); err != nil { return fmt.Errorf("failed to delete hook. err: %+v", err) } - rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int64("hook-id", *rc.hook.ID).Msg("github hook deleted") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Msg("github hook deleted") return nil } @@ -156,6 +167,12 @@ func (ese *GithubEventSourceExecutor) StartEventSource(eventSource *gateways.Eve gc := config.(*githubEventSource) return gwcommon.ProcessRoute(&RouteConfig{ + route: &gwcommon.Route{ + Logger: &ese.Log, + EventSource: eventSource, + Webhook: gc.Hook, + StartCh: make(chan struct{}), + }, clientset: ese.Clientset, namespace: ese.Namespace, ges: gc, diff --git a/gateways/community/github/validate.go b/gateways/community/github/validate.go index 24342d8a27..4812e86498 100644 --- a/gateways/community/github/validate.go +++ b/gateways/community/github/validate.go @@ -30,6 +30,9 @@ func validateGithub(config interface{}) error { if g == nil { return gwcommon.ErrNilEventSource } + if g.Id == 0 { + return fmt.Errorf("hook id must be not be zero") + } if g.Repository == "" { return fmt.Errorf("repository cannot be empty") } diff --git a/gateways/community/github/validate_test.go b/gateways/community/github/validate_test.go index ac7ed8dc9d..15ba48bf25 100644 --- a/gateways/community/github/validate_test.go +++ b/gateways/community/github/validate_test.go @@ -11,6 +11,7 @@ var ( configKey = "testConfig" configId = "1234" goodConfig = ` +id: 1234 hook: endpoint: "/push" port: "12000" diff --git a/gateways/community/gitlab/config.go b/gateways/community/gitlab/config.go index a514e1c430..0b8b066272 100644 --- a/gateways/community/gitlab/config.go +++ b/gateways/community/gitlab/config.go @@ -46,6 +46,8 @@ type RouteConfig struct { // gitlabEventSource contains information to setup a gitlab project integration type gitlabEventSource struct { + // Webhook Id + Id int `json:"id"` // Webhook Hook *common.Webhook `json:"hook"` // ProjectId is the id of project for which integration needs to setup diff --git a/gateways/community/gitlab/config_test.go b/gateways/community/gitlab/config_test.go index 25a761a0dc..8496bda0bd 100644 --- a/gateways/community/gitlab/config_test.go +++ b/gateways/community/gitlab/config_test.go @@ -23,6 +23,7 @@ import ( ) var es = ` +id: 12 hook: endpoint: "/push" port: "12000" diff --git a/gateways/community/gitlab/start.go b/gateways/community/gitlab/start.go index 734db1d1ca..66423a9718 100644 --- a/gateways/community/gitlab/start.go +++ b/gateways/community/gitlab/start.go @@ -66,8 +66,8 @@ func (rc *RouteConfig) PostStart() error { formattedUrl := gwcommon.GenerateFormattedURL(rc.ges.Hook) opt := &gitlab.AddProjectHookOptions{ - URL: &formattedUrl, - Token: &c.token, + URL: &formattedUrl, + Token: &c.token, EnableSSLVerification: &rc.ges.EnableSSLVerification, } @@ -80,29 +80,16 @@ func (rc *RouteConfig) PostStart() error { reflect.Indirect(iev).SetBool(true) elem.Set(iev) - existingHooks, _, err := rc.client.Projects.ListProjectHooks(rc.ges.ProjectId, &gitlab.ListProjectHooksOptions{}) + hook, _, err := rc.client.Projects.GetProjectHook(rc.ges.ProjectId, rc.ges.Id) if err != nil { - return fmt.Errorf("failed to list existing webhooks. err: %+v", err) - } - - for _, h := range existingHooks { - elem = reflect.ValueOf(h).Elem().FieldByName(string(rc.ges.Event)) - if ok := elem.IsValid(); !ok { - return fmt.Errorf("failed to check if hook is already registered with the event %s. unknown event", rc.ges.Event) - } - if reflect.New(elem.Type().Elem()).Bool() && h.URL == formattedUrl { - rc.route.Logger.Warn().Str("event-source", rc.route.EventSource.Name).Msg("hook is already configured") - return nil + hook, _, err = rc.client.Projects.AddProjectHook(rc.ges.ProjectId, opt) + if err != nil { + return fmt.Errorf("failed to add project hook. err: %+v", err) } } - hook, _, err := rc.client.Projects.AddProjectHook(rc.ges.ProjectId, opt) - if err != nil { - return fmt.Errorf("failed to add project hook. err: %+v", err) - } rc.hook = hook - - rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("gitlab hook created") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Msg("gitlab hook created") return nil } @@ -110,7 +97,7 @@ func (rc *RouteConfig) PostStop() error { if _, err := rc.client.Projects.DeleteProjectHook(rc.ges.ProjectId, rc.hook.ID); err != nil { return fmt.Errorf("failed to delete hook. err: %+v", err) } - rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Int("hook-id", rc.hook.ID).Msg("gitlab hook deleted") + rc.route.Logger.Info().Str("event-source-name", rc.route.EventSource.Name).Msg("gitlab hook deleted") return nil } diff --git a/gateways/community/gitlab/validate.go b/gateways/community/gitlab/validate.go index 9cc9607cd8..8e5dd0e556 100644 --- a/gateways/community/gitlab/validate.go +++ b/gateways/community/gitlab/validate.go @@ -31,6 +31,9 @@ func validateGitlab(config interface{}) error { if g == nil { return gwcommon.ErrNilEventSource } + if g.Id == 0 { + return fmt.Errorf("hook id must be not be zero") + } if g.ProjectId == "" { return fmt.Errorf("project id can't be empty") } diff --git a/gateways/community/gitlab/validate_test.go b/gateways/community/gitlab/validate_test.go index e8cd87ef29..fa3e331ec1 100644 --- a/gateways/community/gitlab/validate_test.go +++ b/gateways/community/gitlab/validate_test.go @@ -27,6 +27,7 @@ var ( configKey = "testConfig" configId = "1234" validConfig = ` +id: 1234 hook: endpoint: "/push" port: "12000" diff --git a/gateways/gateway.go b/gateways/gateway.go index 33278c58dd..56655e4285 100644 --- a/gateways/gateway.go +++ b/gateways/gateway.go @@ -18,12 +18,12 @@ package gateways import ( "fmt" - "net" - "os" - "github.com/argoproj/argo-events/common" zlog "github.com/rs/zerolog" "google.golang.org/grpc" + "net" + "os" + "runtime/debug" ) // StartGateway start a gateway @@ -50,6 +50,7 @@ func StartGateway(es EventingServer) { func Recover(eventSource string) { if r := recover(); r != nil { fmt.Printf("recovered event source %s from error. recover: %v", eventSource, r) + debug.PrintStack() } } From cbcece14a27f20c2267ddfffec230054a327e129 Mon Sep 17 00:00:00 2001 From: VaibhavPage Date: Tue, 19 Mar 2019 22:53:13 -0400 Subject: [PATCH 05/11] chore(): fix calendar gateway example --- examples/gateways/calendar.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/gateways/calendar.yaml b/examples/gateways/calendar.yaml index a6604323be..9a9d04f93b 100644 --- a/examples/gateways/calendar.yaml +++ b/examples/gateways/calendar.yaml @@ -19,11 +19,11 @@ spec: spec: containers: - name: "gateway-client" - image: "argoproj/gateway-client:v0.8.3" + image: "argoproj/gateway-client" imagePullPolicy: "Always" command: ["/bin/gateway-client"] - name: "calendar-events" - image: "argoproj/calendar-gateway:v0.8.3" + image: "argoproj/calendar-gateway" imagePullPolicy: "Always" command: ["/bin/calendar-gateway"] serviceAccountName: "argo-events-sa" From c3099843828a68a1cc80a759566a3c142eb4d7f1 Mon Sep 17 00:00:00 2001 From: VaibhavPage Date: Tue, 19 Mar 2019 23:18:43 -0400 Subject: [PATCH 06/11] fix(): sns gateway test --- gateways/community/aws-sns/start_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/gateways/community/aws-sns/start_test.go b/gateways/community/aws-sns/start_test.go index 93fa4bccb3..92df16d68f 100644 --- a/gateways/community/aws-sns/start_test.go +++ b/gateways/community/aws-sns/start_test.go @@ -79,10 +79,12 @@ func TestAWSSNS(t *testing.T) { Body: ioutil.NopCloser(bytes.NewBuffer(payloadBytes)), }) convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusBadRequest) - convey.So(string(writer.Payload), convey.ShouldEqual, "failed to confirm subscription") + + dataCh := make(chan []byte) go func() { - <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh + data := <-helper.ActiveEndpoints[r.Webhook.Endpoint].DataCh + dataCh <- data }() payload.Type = messageTypeNotification @@ -91,7 +93,8 @@ func TestAWSSNS(t *testing.T) { rc.RouteHandler(writer, &http.Request{ Body: ioutil.NopCloser(bytes.NewBuffer(payloadBytes)), }) - convey.So(writer.HeaderStatus, convey.ShouldEqual, http.StatusOK) + data := <-dataCh + convey.So(data, convey.ShouldNotBeNil) }) convey.Convey("Run post activate", func() { From 8f84ae373c296982aece758161f26e9e99f37fe2 Mon Sep 17 00:00:00 2001 From: VaibhavPage Date: Wed, 20 Mar 2019 07:49:49 -0400 Subject: [PATCH 07/11] test(): recover test --- gateways/gateway_test.go | 7 ------- 1 file changed, 7 deletions(-) diff --git a/gateways/gateway_test.go b/gateways/gateway_test.go index 9cbb0f565e..4362c06b53 100644 --- a/gateways/gateway_test.go +++ b/gateways/gateway_test.go @@ -61,13 +61,6 @@ func (f *FakeGRPCStream) RecvMsg(m interface{}) error { return nil } -func TestRecover(t *testing.T) { - convey.Convey("Recover from panic", t, func() { - defer Recover("fake") - panic("fake panic") - }) -} - func TestHandleEventsFromEventSource(t *testing.T) { convey.Convey("Given a gateway server, handle events from an event source", t, func() { dataCh := make(chan []byte) From ced2392a2eb0accda69ac51d4d1337b01081b42a Mon Sep 17 00:00:00 2001 From: vpage Date: Wed, 20 Mar 2019 11:03:42 -0400 Subject: [PATCH 08/11] fix(): makefile --- Makefile | 16 +++------------- VERSION | 2 +- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Makefile b/Makefile index b77accbdb7..ac07c31897 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ override LDFLAGS += \ # docker image publishing options DOCKER_PUSH?=true IMAGE_NAMESPACE?=argoproj -IMAGE_TAG?=v0.8 +IMAGE_TAG?=v0.8.3 ifeq (${DOCKER_PUSH},true) ifndef IMAGE_NAMESPACE @@ -35,9 +35,9 @@ endif # Build the project images .DELETE_ON_ERROR: -all: sensor-linux sensor-controller-linux gateway-controller-linux gateway-client-linux webhook-linux calendar-linux resource-linux artifact-linux file-linux nats-linux kafka-linux amqp-linux mqtt-linux storage-grid-linux github-linux hdfs-linux gitlab-linux sns-linux sqs-linux pubsub-linux trello-linux +all: sensor-linux sensor-controller-linux gateway-controller-linux gateway-client-linux webhook-linux calendar-linux resource-linux artifact-linux file-linux nats-linux kafka-linux amqp-linux mqtt-linux storage-grid-linux github-linux hdfs-linux gitlab-linux sns-linux sqs-linux pubsub-linux -all-images: sensor-image sensor-controller-image gateway-controller-image gateway-client-image webhook-image calendar-image resource-image artifact-image file-image nats-image kafka-image amqp-image mqtt-image storage-grid-image github-image gitlab-image sns-image pubsub-image hdfs-image sqs-image trello-image +all-images: sensor-image sensor-controller-image gateway-controller-image gateway-client-image webhook-image calendar-image resource-image artifact-image file-image nats-image kafka-image amqp-image mqtt-image storage-grid-image github-image gitlab-image sns-image pubsub-image hdfs-image sqs-image all-controller-images: sensor-controller-image gateway-controller-image @@ -263,16 +263,6 @@ sqs-image: sqs-linux docker build -t $(IMAGE_PREFIX)aws-sqs-gateway:$(IMAGE_TAG) -f ./gateways/community/aws-sqs/Dockerfile . @if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)aws-sqs-gateway:$(IMAGE_TAG) ; fi -trello: - go build -v -ldflags '${LDFLAGS}' -o ${DIST_DIR}/trello-gateway ./gateways/community/trello/cmd - -trello-linux: - CGO_ENABLED=0 GOOS=linux GOARCH=amd64 make trello - -trello-image: trello-linux - docker build -t $(IMAGE_PREFIX)trello-gateway:$(IMAGE_TAG) -f ./gateways/community/trello/Dockerfile . - @if [ "$(DOCKER_PUSH)" = "true" ] ; then docker push $(IMAGE_PREFIX)trello-gateway:$(IMAGE_TAG) ; fi - test: go test $(shell go list ./... | grep -v /vendor/) -race -short -v diff --git a/VERSION b/VERSION index 8adc70fdd9..fab77af2a1 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -0.8.0 \ No newline at end of file +0.8.3 \ No newline at end of file From b6a3c16ebbf8291793f97803479ff2ac575bed63 Mon Sep 17 00:00:00 2001 From: vpage Date: Wed, 20 Mar 2019 11:14:51 -0400 Subject: [PATCH 09/11] chore(): updating comments --- gateways/common/webhook.go | 3 ++- gateways/community/aws-sns/config.go | 2 +- gateways/community/aws-sns/start.go | 2 +- gateways/community/slack/config.go | 2 -- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index c1560cae4e..0607a6f076 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -97,7 +97,7 @@ type Endpoint struct { DataCh chan []byte } -// NewWebhookHelper returns new r.Webhook helper +// NewWebhookHelper returns new Webhook helper func NewWebhookHelper() *WebhookHelper { return &WebhookHelper{ ActiveEndpoints: make(map[string]*Endpoint), @@ -184,6 +184,7 @@ func activateRoute(rc RouteConfig, helper *WebhookHelper) { } r.Logger.Info().Str("event-source-name", r.EventSource.Name).Str("port", r.Webhook.Port).Str("endpoint", r.Webhook.Endpoint).Msg("adding route handler") + if _, ok := helper.ActiveEndpoints[r.Webhook.Endpoint]; !ok { helper.ActiveEndpoints[r.Webhook.Endpoint] = &Endpoint{ Active: true, diff --git a/gateways/community/aws-sns/config.go b/gateways/community/aws-sns/config.go index be6241abb7..54f678a034 100644 --- a/gateways/community/aws-sns/config.go +++ b/gateways/community/aws-sns/config.go @@ -76,7 +76,7 @@ type httpNotification struct { UnsubscribeURL string `json:"UnsubscribeURL,omitempty"` // Only for notifications } -// snses contains configuration to subscribe to SNS topic +// snsEventSource contains configuration to subscribe to SNS topic type snsEventSource struct { // Hook defines a webhook. Hook *common.Webhook `json:"hook"` diff --git a/gateways/community/aws-sns/start.go b/gateways/community/aws-sns/start.go index 6e8bcd93c5..368f24eca0 100644 --- a/gateways/community/aws-sns/start.go +++ b/gateways/community/aws-sns/start.go @@ -69,7 +69,7 @@ func (rc *RouteConfig) RouteHandler(writer http.ResponseWriter, request *http.Re var snspayload *httpNotification err = yaml.Unmarshal(body, &snspayload) if err != nil { - logger.Error().Err(err).Msg("failed to convert request payload into snses payload") + logger.Error().Err(err).Msg("failed to convert request payload into sns event source payload") common.SendErrorResponse(writer, "") return } diff --git a/gateways/community/slack/config.go b/gateways/community/slack/config.go index dba70a7e38..6087f0b86e 100644 --- a/gateways/community/slack/config.go +++ b/gateways/community/slack/config.go @@ -34,7 +34,6 @@ type SlackEventSourceExecutor struct { Log zerolog.Logger } -// type RouteConfig struct { route *gwcommon.Route ses *slackEventSource @@ -43,7 +42,6 @@ type RouteConfig struct { namespace string } -// slackEventSource type slackEventSource struct { // Token for URL verification handshake Token *corev1.SecretKeySelector `json:"token"` From f86e00badbd60c34bf4df692ee2cdfec2792b73e Mon Sep 17 00:00:00 2001 From: vpage Date: Wed, 20 Mar 2019 11:19:57 -0400 Subject: [PATCH 10/11] chore(): updating makefile image version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ac07c31897..140658dc1b 100644 --- a/Makefile +++ b/Makefile @@ -17,7 +17,7 @@ override LDFLAGS += \ # docker image publishing options DOCKER_PUSH?=true IMAGE_NAMESPACE?=argoproj -IMAGE_TAG?=v0.8.3 +IMAGE_TAG?=latest ifeq (${DOCKER_PUSH},true) ifndef IMAGE_NAMESPACE From 30eaa296651e80b11ffef3b20464a08a2041eb09 Mon Sep 17 00:00:00 2001 From: vpage Date: Wed, 20 Mar 2019 14:07:21 -0400 Subject: [PATCH 11/11] refactor(): rename RouteConfig interface to RouteManager --- gateways/common/webhook.go | 44 +++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/gateways/common/webhook.go b/gateways/common/webhook.go index 0607a6f076..902492dcb5 100644 --- a/gateways/common/webhook.go +++ b/gateways/common/webhook.go @@ -57,9 +57,9 @@ type WebhookHelper struct { // ActiveEndpoints keep track of endpoints that are already registered with server and their status active or inactive ActiveEndpoints map[string]*Endpoint // RouteActivateChan handles assigning new route to server. - RouteActivateChan chan RouteConfig + RouteActivateChan chan RouteManager // RouteDeactivateChan handles deactivating existing route - RouteDeactivateChan chan RouteConfig + RouteDeactivateChan chan RouteManager } // HTTP Muxer @@ -81,8 +81,8 @@ type Route struct { EventSource *gateways.EventSource } -// RouteConfig is an interface to manage the configuration for a route -type RouteConfig interface { +// RouteManager is an interface to manage the configuration for a route +type RouteManager interface { GetRoute() *Route RouteHandler(writer http.ResponseWriter, request *http.Request) PostStart() error @@ -103,8 +103,8 @@ func NewWebhookHelper() *WebhookHelper { ActiveEndpoints: make(map[string]*Endpoint), ActiveServers: make(map[string]*activeServer), Mutex: sync.Mutex{}, - RouteActivateChan: make(chan RouteConfig), - RouteDeactivateChan: make(chan RouteConfig), + RouteActivateChan: make(chan RouteManager), + RouteDeactivateChan: make(chan RouteManager), } } @@ -134,10 +134,10 @@ func (s *server) ServeHTTP(w http.ResponseWriter, r *http.Request) { } // starts a http server -func startHttpServer(rc RouteConfig, helper *WebhookHelper) { +func startHttpServer(routeManager RouteManager, helper *WebhookHelper) { // start a http server only if no other configuration previously started the server on given port helper.Mutex.Lock() - r := rc.GetRoute() + r := routeManager.GetRoute() if _, ok := helper.ActiveServers[r.Webhook.Port]; !ok { s := &server{ mux: http.NewServeMux(), @@ -171,9 +171,9 @@ func startHttpServer(rc RouteConfig, helper *WebhookHelper) { } // activateRoute activates route -func activateRoute(rc RouteConfig, helper *WebhookHelper) { - r := rc.GetRoute() - helper.RouteActivateChan <- rc +func activateRoute(routeManager RouteManager, helper *WebhookHelper) { + r := routeManager.GetRoute() + helper.RouteActivateChan <- routeManager <-r.StartCh @@ -190,15 +190,15 @@ func activateRoute(rc RouteConfig, helper *WebhookHelper) { Active: true, DataCh: make(chan []byte), } - r.Webhook.mux.HandleFunc(r.Webhook.Endpoint, rc.RouteHandler) + r.Webhook.mux.HandleFunc(r.Webhook.Endpoint, routeManager.RouteHandler) } helper.ActiveEndpoints[r.Webhook.Endpoint].Active = true r.Logger.Info().Str("event-source-name", r.EventSource.Name).Str("port", r.Webhook.Port).Str("endpoint", r.Webhook.Endpoint).Msg("route handler added") } -func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { - r := rc.GetRoute() +func processChannels(routeManager RouteManager, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { + r := routeManager.GetRoute() for { select { @@ -215,7 +215,7 @@ func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways case <-eventStream.Context().Done(): r.Logger.Info().Str("event-source-name", r.EventSource.Name).Msg("connection is closed by client") - helper.RouteDeactivateChan <- rc + helper.RouteDeactivateChan <- routeManager return nil // this error indicates that the server has stopped running @@ -225,32 +225,32 @@ func processChannels(rc RouteConfig, helper *WebhookHelper, eventStream gateways } } -func ProcessRoute(rc RouteConfig, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { - r := rc.GetRoute() +func ProcessRoute(routeManager RouteManager, helper *WebhookHelper, eventStream gateways.Eventing_StartEventSourceServer) error { + r := routeManager.GetRoute() r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("validating the route") - if err := validateRoute(rc.GetRoute()); err != nil { + if err := validateRoute(routeManager.GetRoute()); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred validating route") return err } r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("activating the route") - activateRoute(rc, helper) + activateRoute(routeManager, helper) r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("running post start") - if err := rc.PostStart(); err != nil { + if err := routeManager.PostStart(); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post start") return err } r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("processing channels") - if err := processChannels(rc, helper, eventStream); err != nil { + if err := processChannels(routeManager, helper, eventStream); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in process channel") return err } r.Logger.Info().Str("event-source", r.EventSource.Name).Msg("running post stop") - if err := rc.PostStop(); err != nil { + if err := routeManager.PostStop(); err != nil { r.Logger.Error().Err(err).Str("event-source", r.EventSource.Name).Msg("error occurred in post stop") } return nil