diff --git a/cmd/daemon/command/start.go b/cmd/daemon/command/start.go index 3ca1c2e4..a3753a6b 100644 --- a/cmd/daemon/command/start.go +++ b/cmd/daemon/command/start.go @@ -6,6 +6,7 @@ import ( "syscall" "time" + flux_notification_controller "github.com/lunarway/release-manager/cmd/daemon/flux2notifications" "github.com/lunarway/release-manager/cmd/daemon/kubernetes" httpinternal "github.com/lunarway/release-manager/internal/http" "github.com/lunarway/release-manager/internal/log" @@ -56,6 +57,7 @@ func StartDaemon() *cobra.Command { kubernetes.RegisterJobInformer(kubectl.InformerFactory, exporter, handlerFactory, kubectl.Clientset) kubernetes.RegisterPodInformer(kubectl.InformerFactory, exporter, handlerFactory, kubectl.Clientset, moduloCrashReportNotif) kubernetes.RegisterStatefulSetInformer(kubectl.InformerFactory, exporter, handlerFactory, kubectl.Clientset) + flux_notification_controller.StartHttpServer() log.Info("Deamon started") diff --git a/cmd/daemon/flux2notifications/api.go b/cmd/daemon/flux2notifications/api.go new file mode 100644 index 00000000..d8271f52 --- /dev/null +++ b/cmd/daemon/flux2notifications/api.go @@ -0,0 +1,46 @@ +package flux2notifications + +import ( + "encoding/json" + "io/ioutil" + "net/http" + "time" + + "github.com/lunarway/release-manager/internal/log" +) + +type Event struct { + InvolvedObject struct { + Kind string `json:"kind"` + Namespace string `json:"namespace"` + Name string `json:"name"` + UID string `json:"uid"` + APIVersion string `json:"apiVersion"` + ResourceVersion string `json:"resourceVersion"` + } `json:"involvedObject"` + Severity string `json:"severity"` + Timestamp time.Time `json:"timestamp"` + Message string `json:"message"` + Reason string `json:"reason"` + ReportingController string `json:"reportingController"` + ReportingInstance string `json:"reportingInstance"` +} + +func HandleEventFromFlux2(w http.ResponseWriter, r *http.Request) { + defer r.Body.Close() + body, err := ioutil.ReadAll(r.Body) //TODO: log something + if err != nil { + log.Errorf("Failed to unmarshal alert from flux2-notification-controller: %v", err) + http.Error(w, "unknown error", http.StatusInternalServerError) + return + } + + var event Event + err = json.Unmarshal(body, &event) + if err != nil { + log.Errorf("Failed to unmarshal alert from flux2-notification-controller: %v", err) + http.Error(w, "unknown error", http.StatusInternalServerError) + return + } + log.Infof("Received alert from flux2-notification-controller: %s with msg: %s", event.InvolvedObject.Name, event.Message) +} diff --git a/cmd/daemon/flux2notifications/api_test.go b/cmd/daemon/flux2notifications/api_test.go new file mode 100644 index 00000000..22239095 --- /dev/null +++ b/cmd/daemon/flux2notifications/api_test.go @@ -0,0 +1,43 @@ +package flux2notifications + +import ( + "io/ioutil" + "net/http" + "net/http/httptest" + "strings" + "testing" + + "github.com/lunarway/release-manager/internal/log" + "github.com/stretchr/testify/assert" + "go.uber.org/zap/zapcore" +) + +// TestWebhookForAlerts tests if /flux2-alerts can handle requests from flux2-notification-controller +func TestWebhookForAlerts(t *testing.T) { + //arrange + setupTest() + var ( + eventAsJson = "{\"involvedObject\": {\"kind\":\"GitRepository\",\"namespace\":\"flux-system\",\"name\":\"flux-system\",\"uid\":\"cc4d0095-83f4-4f08-98f2-d2e9f3731fb9\",\"apiVersion\":\"source.toolkit.fluxcd.io/v1beta2\", \"resourceVersion\":\"56921\"},\"severity\":\"info\",\"timestamp\":\"2006-01-02T15:04:05Z\",\"message\":\"Fetched revision: main/731f7eaddfb6af01cb2173e18f0f75b0ba780ef1\",\"reason\":\"info\",\"reportingController\":\"source-controller\",\"reportingInstance\":\"source-controller-7c7b47f5f-8bhrp\"}" + request = httptest.NewRequest(http.MethodPost, "/webhook/flux2-alerts", strings.NewReader(eventAsJson)) + w = httptest.NewRecorder() + ) + + //act + HandleEventFromFlux2(w, request) + response := w.Result() + defer response.Body.Close() + _, err := ioutil.ReadAll(response.Body) + + //assert + assert.NoError(t, err, "HandleEventFromFlux2 could not handle request") + assert.Equal(t, http.StatusOK, response.StatusCode) +} + +func setupTest() { + log.Init(&log.Configuration{ + Level: log.Level{ + Level: zapcore.DebugLevel, + }, + Development: true, + }) +} diff --git a/cmd/daemon/flux2notifications/server.go b/cmd/daemon/flux2notifications/server.go new file mode 100644 index 00000000..505f7de1 --- /dev/null +++ b/cmd/daemon/flux2notifications/server.go @@ -0,0 +1,17 @@ +package flux2notifications + +import ( + "net/http" + + "github.com/gorilla/mux" + "github.com/lunarway/release-manager/internal/log" +) + +func StartHttpServer() { + router := mux.NewRouter() + router.HandleFunc("/webhook/flux2-alerts", HandleEventFromFlux2).Methods(http.MethodPost) + err := http.ListenAndServe(":3001", router) + if err != nil { + log.Errorf("Failed to start daemon's HTTP server: %v", err) + } +} diff --git a/go.mod b/go.mod index 34b329d1..eafcb6b8 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,8 @@ require ( k8s.io/client-go v0.24.1 ) +require github.com/gorilla/mux v1.8.0 + require ( github.com/Microsoft/go-winio v0.4.16 // indirect github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7 // indirect @@ -46,14 +48,14 @@ require ( github.com/emirpasic/gods v1.12.0 // indirect github.com/go-git/gcfg v1.5.0 // indirect github.com/go-git/go-billy/v5 v5.3.1 // indirect - github.com/go-logr/logr v1.2.0 // indirect + github.com/go-logr/logr v1.2.3 // indirect github.com/go-openapi/jsonpointer v0.19.5 // indirect github.com/go-openapi/jsonreference v0.19.5 // indirect github.com/go-openapi/swag v0.19.14 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect - github.com/google/go-cmp v0.5.6 // indirect + github.com/google/go-cmp v0.5.7 // indirect github.com/google/gofuzz v1.1.0 // indirect github.com/gorilla/websocket v1.4.2 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -78,7 +80,7 @@ require ( github.com/shabbyrobe/gocovmerge v0.0.0-20180507124511-f6ea450bfb63 // indirect github.com/stretchr/objx v0.2.0 // indirect github.com/xanzy/ssh-agent v0.3.0 // indirect - go.uber.org/atomic v1.7.0 // indirect + go.uber.org/atomic v1.9.0 // indirect golang.org/x/crypto v0.0.0-20220214200702-86341886e292 // indirect golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd // indirect golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect diff --git a/go.sum b/go.sum index ffa4de41..b793bc83 100644 --- a/go.sum +++ b/go.sum @@ -147,8 +147,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= -github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= +github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= @@ -211,8 +212,8 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= +github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -236,6 +237,7 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= github.com/gorilla/websocket v1.2.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= @@ -347,6 +349,8 @@ github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5Fsn github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= +github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -416,8 +420,9 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= +go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= +go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.0.0/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=