Repository: fluxcd/notification-controller
Pull request #84 (2020-11-18 13:39:07)

Send notification header identify requests as coming from the notification component.
Add support for sending a Notification-Controller header from the forwarder notifier.

This means that it can be identified in upstream requests.


Patch:
diff --git a/internal/notifier/bitbucket.go b/internal/notifier/bitbucket.go
index e0123c8..129c850 100644
--- a/internal/notifier/bitbucket.go
+++ b/internal/notifier/bitbucket.go
@@ -25,12 +25,14 @@ import (
 	"github.com/ktrysmt/go-bitbucket"
 )
 
+// Bitbucket is a Bitbucket Server notifier.
 type Bitbucket struct {
 	Owner  string
 	Repo   string
 	Client *bitbucket.Client
 }
 
+// NewBitbucket creates and returns a new Bitbucket notifier.
 func NewBitbucket(addr string, token string) (*Bitbucket, error) {
 	if len(token) == 0 {
 		return nil, errors.New("bitbucket token cannot be empty")
diff --git a/internal/notifier/client.go b/internal/notifier/client.go
index 8738375..40aaff8 100644
--- a/internal/notifier/client.go
+++ b/internal/notifier/client.go
@@ -28,7 +28,9 @@ import (
 	"github.com/hashicorp/go-retryablehttp"
 )
 
-func postMessage(address string, proxy string, payload interface{}) error {
+type requestOptFunc func(*retryablehttp.Request)
+
+func postMessage(address, proxy string, payload interface{}, reqOpts ...requestOptFunc) error {
 	httpClient := retryablehttp.NewClient()
 
 	if proxy != "" {
@@ -61,8 +63,16 @@ func postMessage(address string, proxy string, payload interface{}) error {
 		return fmt.Errorf("marshalling notification payload failed: %w", err)
 	}
 
-	if _, err := httpClient.Post(address, "application/json", data); err != nil {
-		return err
+	req, err := retryablehttp.NewRequest(http.MethodPost, address, data)
+	if err != nil {
+		return fmt.Errorf("failed to create a new request: %w", err)
+	}
+	req.Header.Set("Content-Type", "application/json")
+	for _, o := range reqOpts {
+		o(req)
+	}
+	if _, err := httpClient.Do(req); err != nil {
+		return fmt.Errorf("failed to execute request: %w", err)
 	}
 
 	return nil
diff --git a/internal/notifier/forwarder.go b/internal/notifier/forwarder.go
index d976c5f..092f661 100644
--- a/internal/notifier/forwarder.go
+++ b/internal/notifier/forwarder.go
@@ -21,8 +21,15 @@ import (
 	"net/url"
 
 	"github.com/fluxcd/pkg/recorder"
+	"github.com/hashicorp/go-retryablehttp"
 )
 
+// NotificationHeader is a header sent to identify requests from the
+// notification controller.
+const NotificationHeader = "gotk-component"
+
+// Forwarder is an implementation of the notification Interface that posts the
+// body as an HTTP request using an optional proxy.
 type Forwarder struct {
 	URL      string
 	ProxyURL string
@@ -30,7 +37,7 @@ type Forwarder struct {
 
 func NewForwarder(hookURL string, proxyURL string) (*Forwarder, error) {
 	if _, err := url.ParseRequestURI(hookURL); err != nil {
-		return nil, fmt.Errorf("invalid Discord hook URL %s", hookURL)
+		return nil, fmt.Errorf("invalid hook URL %s: %w", hookURL, err)
 	}
 
 	return &Forwarder{
@@ -40,7 +47,10 @@ func NewForwarder(hookURL string, proxyURL string) (*Forwarder, error) {
 }
 
 func (f *Forwarder) Post(event recorder.Event) error {
-	err := postMessage(f.URL, f.ProxyURL, event)
+	err := postMessage(f.URL, f.ProxyURL, event, func(req *retryablehttp.Request) {
+		req.Header.Set(NotificationHeader, event.ReportingController)
+	})
+
 	if err != nil {
 		return fmt.Errorf("postMessage failed: %w", err)
 	}


Test patch:
diff --git a/internal/notifier/client_test.go b/internal/notifier/client_test.go
index 4f25aeb..b1d4eb9 100644
--- a/internal/notifier/client_test.go
+++ b/internal/notifier/client_test.go
@@ -42,7 +42,6 @@ func Test_postMessage(t *testing.T) {
 		require.Equal(t, "success", payload["status"])
 	}))
 	defer ts.Close()
-
 	err := postMessage(ts.URL, "", map[string]string{"status": "success"})
 	require.NoError(t, err)
 }
diff --git a/internal/notifier/forwarder_test.go b/internal/notifier/forwarder_test.go
index d07354d..9b16a65 100644
--- a/internal/notifier/forwarder_test.go
+++ b/internal/notifier/forwarder_test.go
@@ -33,6 +33,7 @@ func TestForwarder_Post(t *testing.T) {
 		b, err := ioutil.ReadAll(r.Body)
 		require.NoError(t, err)
 
+		require.Equal(t, "source-controller", r.Header.Get("gotk-component"))
 		var payload = recorder.Event{}
 		err = json.Unmarshal(b, &payload)
 		require.NoError(t, err)
diff --git a/internal/notifier/slack_test.go b/internal/notifier/slack_test.go
index 5357e6a..97738a8 100644
--- a/internal/notifier/slack_test.go
+++ b/internal/notifier/slack_test.go
@@ -44,7 +44,6 @@ func TestSlack_Post(t *testing.T) {
 
 	err = slack.Post(testEvent())
 	require.NoError(t, err)
-
 }
 
 func TestSlack_PostUpdate(t *testing.T) {