From 6ffa2e91fe5249225f08e6f698b95d403941b93d Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 28 Apr 2021 10:53:36 +0200 Subject: [PATCH 1/9] Add support for Azure EventHub provider Solves #190 Signed-off-by: Edvin Norling --- api/v1beta1/provider_types.go | 3 +- ...ification.toolkit.fluxcd.io_providers.yaml | 1 + docs/spec/v1beta1/provider.md | 3 +- go.mod | 8 +++ internal/notifier/eventhub.go | 61 +++++++++++++++++++ internal/notifier/factory.go | 2 + 6 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 internal/notifier/eventhub.go diff --git a/api/v1beta1/provider_types.go b/api/v1beta1/provider_types.go index 1a0039745..29bfd0f9e 100644 --- a/api/v1beta1/provider_types.go +++ b/api/v1beta1/provider_types.go @@ -28,7 +28,7 @@ const ( // ProviderSpec defines the desired state of Provider type ProviderSpec struct { // Type of provider - // +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry + // +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry;eventhub; // +required Type string `json:"type"` @@ -76,6 +76,7 @@ const ( GoogleChatProvider string = "googlechat" WebexProvider string = "webex" SentryProvider string = "sentry" + EventHubProvider string = "eventhub" ) // ProviderStatus defines the observed state of Provider diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml index fdf5c1570..6e42d8ff8 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml @@ -92,6 +92,7 @@ spec: - googlechat - webex - sentry + - eventhub type: string username: description: Bot username for this provider diff --git a/docs/spec/v1beta1/provider.md b/docs/spec/v1beta1/provider.md index 5c493ca8a..02afaa00d 100644 --- a/docs/spec/v1beta1/provider.md +++ b/docs/spec/v1beta1/provider.md @@ -46,6 +46,7 @@ Notification providers: * Google Chat * Webex * Sentry +* EventHub * Generic webhook Git commit status providers: @@ -106,7 +107,7 @@ kubectl create secret generic webhook-url \ Note that the secret must contain an `address` field. -The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`. +The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `eventhub`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`. When type `generic` is specified, the notification controller will post the incoming [event](event.md) in JSON format to the webhook address. diff --git a/go.mod b/go.mod index d760b5ef9..2d59fa199 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,10 @@ go 1.15 replace github.com/fluxcd/notification-controller/api => ./api require ( + github.com/Azure/azure-amqp-common-go/v3 v3.1.0 // indirect + github.com/Azure/azure-event-hubs-go/v3 v3.3.7 + github.com/Azure/azure-sdk-for-go v53.4.0+incompatible // indirect + github.com/Azure/go-amqp v0.13.6 // indirect github.com/fluxcd/notification-controller/api v0.13.0 github.com/fluxcd/pkg/apis/meta v0.9.0 github.com/fluxcd/pkg/runtime v0.11.0 @@ -12,8 +16,10 @@ require ( github.com/go-logr/logr v0.3.0 github.com/google/go-github/v32 v32.1.0 github.com/hashicorp/go-retryablehttp v0.6.8 + github.com/jpillora/backoff v1.0.0 // indirect github.com/ktrysmt/go-bitbucket v0.6.5 github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 + github.com/mitchellh/mapstructure v1.4.1 // indirect github.com/onsi/ginkgo v1.14.1 github.com/onsi/gomega v1.10.2 github.com/sethvargo/go-limiter v0.6.0 @@ -22,6 +28,8 @@ require ( github.com/stretchr/testify v1.6.1 github.com/whilp/git-urls v1.0.0 github.com/xanzy/go-gitlab v0.38.2 + golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b // indirect + golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d k8s.io/api v0.20.4 k8s.io/apimachinery v0.20.4 diff --git a/internal/notifier/eventhub.go b/internal/notifier/eventhub.go new file mode 100644 index 000000000..a05f2bcd0 --- /dev/null +++ b/internal/notifier/eventhub.go @@ -0,0 +1,61 @@ +/* +Copyright 2020 The Flux authors +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 notifier + +import ( + "context" + "encoding/json" + "fmt" + "time" + + eventhub "github.com/Azure/azure-event-hubs-go/v3" + "github.com/fluxcd/pkg/runtime/events" +) + +type EventHub struct { + Hub *eventhub.Hub +} + +func NewEventHub(endpointURL string) (*EventHub, error) { + hub, err := eventhub.NewHubFromConnectionString(endpointURL) + if err != nil { + return nil, err + } + return &EventHub{ + Hub: hub, + }, nil +} + +// Post EventHub msg +func (e *EventHub) Post(event events.Event) error { + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + eventBytes, err := json.Marshal(event) + if err != nil { + return fmt.Errorf("Unable to marshall event: %w", err) + } + + //err := e.Hub.Send(ctx, eventhub.NewEventFromString("From, String")) + err = e.Hub.Send(ctx, eventhub.NewEvent(eventBytes)) + if err != nil { + return fmt.Errorf("Failed to send msg: %w", err) + } + + err = e.Hub.Close(context.Background()) + if err != nil { + return fmt.Errorf("Unable to close connection: %w", err) + } + return nil +} diff --git a/internal/notifier/factory.go b/internal/notifier/factory.go index a388b9ba3..40b81457f 100644 --- a/internal/notifier/factory.go +++ b/internal/notifier/factory.go @@ -75,6 +75,8 @@ func (f Factory) Notifier(provider string) (Interface, error) { n, err = NewWebex(f.URL, f.ProxyURL, f.CertPool) case v1beta1.SentryProvider: n, err = NewSentry(f.CertPool, f.URL) + case v1beta1.EventHubProvider: + n, err = NewEventHub(f.URL) default: err = fmt.Errorf("provider %s not supported", provider) } From e019aaab34010c1dea8d290db5e42f2a40bd0952 Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Tue, 4 May 2021 08:58:07 +0200 Subject: [PATCH 2/9] Change to azureeventhub * Update go.sum * Use ctx with timeout * minor linting & clean-up Signed-off-by: Edvin Norling --- api/v1beta1/provider_types.go | 28 +++--- ...ification.toolkit.fluxcd.io_providers.yaml | 2 +- docs/spec/v1beta1/provider.md | 2 +- go.sum | 87 +++++++++++++++++-- .../{eventhub.go => azure_eventhub.go} | 19 ++-- internal/notifier/factory.go | 4 +- 6 files changed, 110 insertions(+), 32 deletions(-) rename internal/notifier/{eventhub.go => azure_eventhub.go} (73%) diff --git a/api/v1beta1/provider_types.go b/api/v1beta1/provider_types.go index 29bfd0f9e..ad432dc4f 100644 --- a/api/v1beta1/provider_types.go +++ b/api/v1beta1/provider_types.go @@ -28,7 +28,7 @@ const ( // ProviderSpec defines the desired state of Provider type ProviderSpec struct { // Type of provider - // +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry;eventhub; + // +kubebuilder:validation:Enum=slack;discord;msteams;rocket;generic;github;gitlab;bitbucket;azuredevops;googlechat;webex;sentry;azureeventhub; // +required Type string `json:"type"` @@ -64,19 +64,19 @@ type ProviderSpec struct { } const ( - GenericProvider string = "generic" - SlackProvider string = "slack" - DiscordProvider string = "discord" - MSTeamsProvider string = "msteams" - RocketProvider string = "rocket" - GitHubProvider string = "github" - GitLabProvider string = "gitlab" - BitbucketProvider string = "bitbucket" - AzureDevOpsProvider string = "azuredevops" - GoogleChatProvider string = "googlechat" - WebexProvider string = "webex" - SentryProvider string = "sentry" - EventHubProvider string = "eventhub" + GenericProvider string = "generic" + SlackProvider string = "slack" + DiscordProvider string = "discord" + MSTeamsProvider string = "msteams" + RocketProvider string = "rocket" + GitHubProvider string = "github" + GitLabProvider string = "gitlab" + BitbucketProvider string = "bitbucket" + AzureDevOpsProvider string = "azuredevops" + GoogleChatProvider string = "googlechat" + WebexProvider string = "webex" + SentryProvider string = "sentry" + AzureEventHubProvider string = "azureeventhub" ) // ProviderStatus defines the observed state of Provider diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml index 6e42d8ff8..c7a2214f4 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml @@ -92,7 +92,7 @@ spec: - googlechat - webex - sentry - - eventhub + - azureeventhub type: string username: description: Bot username for this provider diff --git a/docs/spec/v1beta1/provider.md b/docs/spec/v1beta1/provider.md index 02afaa00d..db2e25d02 100644 --- a/docs/spec/v1beta1/provider.md +++ b/docs/spec/v1beta1/provider.md @@ -107,7 +107,7 @@ kubectl create secret generic webhook-url \ Note that the secret must contain an `address` field. -The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `eventhub`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`. +The provider type can be: `slack`, `msteams`, `rocket`, `discord`, `googlechat`, `webex`, `sentry`, `azureeventhub`, `github`, `gitlab`, `bitbucket`, `azuredevops` or `generic`. When type `generic` is specified, the notification controller will post the incoming [event](event.md) in JSON format to the webhook address. diff --git a/go.sum b/go.sum index 4a3b476f2..2b1d3d99f 100644 --- a/go.sum +++ b/go.sum @@ -25,15 +25,64 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl contrib.go.opencensus.io/exporter/prometheus v0.2.0/go.mod h1:TYmVAyE8Tn1lyPcltF5IYYfWp2KHu7lQGIZnj8iZMys= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8= +github.com/Azure/azure-amqp-common-go/v3 v3.0.1/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0= +github.com/Azure/azure-amqp-common-go/v3 v3.1.0 h1:1N4YSkWYWffOpQHromYdOucBSQXhNRKzqtgICy6To8Q= +github.com/Azure/azure-amqp-common-go/v3 v3.1.0/go.mod h1:PBIGdzcO1teYoufTKMcGibdKaYZv4avS+O6LNIp8bq0= +github.com/Azure/azure-event-hubs-go/v3 v3.3.7 h1:xOUxw5zVLnLX8VxS1/exhK1zZsmcoQio7Lzs6xOCIFE= +github.com/Azure/azure-event-hubs-go/v3 v3.3.7/go.mod h1:sszMsQpFy8Au2s2NColbnJY8lRVm1koW0XxBJ3rN5TY= +github.com/Azure/azure-pipeline-go v0.1.8/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= +github.com/Azure/azure-pipeline-go v0.1.9/go.mod h1:XA1kFWRVhSK+KNFiOhfv83Fv8L9achrP7OxIzeTn1Yg= +github.com/Azure/azure-sdk-for-go v37.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v51.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-sdk-for-go v53.4.0+incompatible h1:ky9S0JoJOvO39ncwrYAVMEBiIjFB/WkbZsWkg/nbYx0= +github.com/Azure/azure-sdk-for-go v53.4.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= +github.com/Azure/azure-storage-blob-go v0.6.0/go.mod h1:oGfmITT1V6x//CswqY2gtAHND+xIP64/qL7a5QJix0Y= +github.com/Azure/go-amqp v0.13.0/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs= +github.com/Azure/go-amqp v0.13.1/go.mod h1:qj+o8xPCz9tMSbQ83Vp8boHahuRDl5mkNHyt1xlxUTs= +github.com/Azure/go-amqp v0.13.6 h1:CWjyY59Iyc1sO/fE/AubMLMWf5id+Uiw/ph0bZzG9Ns= +github.com/Azure/go-amqp v0.13.6/go.mod h1:wbpCKA8tR5MLgRyIu+bb+S6ECdIDdYJ0NlpFE9xsBPI= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= +github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK/vTfRHdAubSIPRgs= github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/Azure/go-autorest/autorest v0.9.0/go.mod h1:xyHB1BMZT0cuDHU7I0+g046+BFDTQ8rEZB0s4Yfa6bI= +github.com/Azure/go-autorest/autorest v0.9.3/go.mod h1:GsRuLYvwzLjjjRoWEIyMUaYq8GNUx2nRB378IPt/1p0= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.3/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= +github.com/Azure/go-autorest/autorest v0.11.18 h1:90Y4srNYrwOtAgVo3ndrQkTYn6kf1Eg/AjTFJ8Is2aM= +github.com/Azure/go-autorest/autorest v0.11.18/go.mod h1:dSiJPy22c3u0OtOKDNttNgqpNFY/GeWa7GH/Pz56QRA= +github.com/Azure/go-autorest/autorest/adal v0.5.0/go.mod h1:8Z9fGy2MpX0PvDjB1pEgQTmVqjGhiHBW7RJJEciWzS0= +github.com/Azure/go-autorest/autorest/adal v0.8.0/go.mod h1:Z6vX6WXXuyieHAXwMj0S6HY6e6wcHn37qQMBQlvY3lc= +github.com/Azure/go-autorest/autorest/adal v0.8.1/go.mod h1:ZjhuQClTqx435SRJ2iMlOxPYt3d2C/T/7TiQCVZSn3Q= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= +github.com/Azure/go-autorest/autorest/adal v0.9.13 h1:Mp5hbtOePIzM8pJVRa3YLrWWmZtoxRXqUEzCfJt3+/Q= +github.com/Azure/go-autorest/autorest/adal v0.9.13/go.mod h1:W/MM4U6nLxnIskrw4UwWzlHfGjwUS50aOsc/I3yuU8M= +github.com/Azure/go-autorest/autorest/azure/auth v0.4.2 h1:iM6UAvjR97ZIeR93qTcwpKNMpV+/FTWjwEbuPD495Tk= +github.com/Azure/go-autorest/autorest/azure/auth v0.4.2/go.mod h1:90gmfKdlmKgfjUpnCEpOJzsUEjrWDSLwHIG73tSXddM= +github.com/Azure/go-autorest/autorest/azure/cli v0.3.1 h1:LXl088ZQlP0SBppGFsRZonW6hSvwgL5gRByMbvUbx8U= +github.com/Azure/go-autorest/autorest/azure/cli v0.3.1/go.mod h1:ZG5p860J94/0kI9mNJVoIoLgXcirM2gF5i2kWloofxw= +github.com/Azure/go-autorest/autorest/date v0.1.0/go.mod h1:plvfp3oPSKwf2DNjlBjWF/7vwR+cUD/ELuzDCXwHUVA= +github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g= +github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= +github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0= +github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/mocks v0.4.1 h1:K0laFcLE6VLTOwNgSxaGbUcLPuGXlNkbVvq4cW4nIHk= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= +github.com/Azure/go-autorest/autorest/to v0.3.0/go.mod h1:MgwOyqaIuKdG4TL/2ywSsIWKAfJfgHDo8ObuUk3t5sA= +github.com/Azure/go-autorest/autorest/to v0.4.0 h1:oXVqrxakqqV1UZdSazDOPOLvOIz+XA683u8EctwboHk= +github.com/Azure/go-autorest/autorest/to v0.4.0/go.mod h1:fE8iZBn7LQR7zH/9XU2NcPR4o9jEImooCeWJcYV/zLE= +github.com/Azure/go-autorest/autorest/validation v0.2.0/go.mod h1:3EEqHnBxQGHXRYq3HT1WyXAvT7LLY3tl70hw6tQIbjI= +github.com/Azure/go-autorest/autorest/validation v0.3.1 h1:AgyqjAd94fwNAoTjl/WQXg4VvFeRFpO+UhNyRXqF1ac= +github.com/Azure/go-autorest/autorest/validation v0.3.1/go.mod h1:yhLgjC0Wda5DYXl6JAsWyUe4KVNffhoDhG0zVzUMo3E= +github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= +github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk= +github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -93,10 +142,14 @@ github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7Do github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/devigned/tab v0.1.1 h1:3mD6Kb1mUOYeLpJvTVSDwSg5ZsfSxfvxGRTxRsJsITA= +github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgraph-io/badger v1.6.0/go.mod h1:zwt7syl517jmP8s94KqSxTlM6IMsdhYy6psNgSztDR4= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= +github.com/dimchansky/utfbom v1.1.0 h1:FcM3g+nofKgUteL8dm/UpdRXNC9KmADgTpLKsu0TRo4= +github.com/dimchansky/utfbom v1.1.0/go.mod h1:rO41eb7gLfo8SF1jd9F8HplJm1Fewwi4mQvIirEdv+8= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -119,7 +172,10 @@ github.com/fluxcd/pkg/apis/meta v0.9.0 h1:rxW69p+VmJCKXXkaRYnovRBFlKjd+MJQfm2RrB github.com/fluxcd/pkg/apis/meta v0.9.0/go.mod h1:yHuY8kyGHYz22I0jQzqMMGCcHViuzC/WPdo9Gisk8Po= github.com/fluxcd/pkg/runtime v0.11.0 h1:FPsiu1k5NQGl2tsaXH5WgSmrOMg7o44jdOP0rW/TI1Y= github.com/fluxcd/pkg/runtime v0.11.0/go.mod h1:ZjAwug6DBLXwo9UdP1/tTPyuWpK9kZ0BEJbctbuEB1o= +github.com/form3tech-oss/jwt-go v3.2.2+incompatible h1:TcekIExNqud5crz4xD2pavyTgWiPvpYe4Xau31I0PRk= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= +github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw= +github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= @@ -205,6 +261,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM= github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-github/v32 v32.1.0 h1:GWkQOdXqviCPx7Q7Fj+KyPoGm4SwHRh8rheoPhd27II= @@ -282,7 +339,12 @@ github.com/iris-contrib/go.uuid v2.0.0+incompatible/go.mod h1:iz2lgM/1UnEf1kP0L/ github.com/iris-contrib/jade v1.1.3/go.mod h1:H/geBymxJhShH5kecoiOCSssPX7QWYH7UaeZTSWddIk= github.com/iris-contrib/pongo2 v0.0.1/go.mod h1:Ssh+00+3GAZqSQb30AvBRNxBx7rf0GqwkjqxNd0u65g= github.com/iris-contrib/schema v0.0.1/go.mod h1:urYA3uvUNG1TIIjOSCzHr9/LmbQo8LrOcOqfqxa4hXw= +github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= +github.com/jpillora/backoff v1.0.0 h1:uvFg412JmmHBHw7iwprIxkPMI+sGQ4kzOWsMeHnm2EA= +github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -310,6 +372,7 @@ github.com/klauspost/compress v1.8.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0 github.com/klauspost/compress v1.9.7/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -353,14 +416,16 @@ github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5/go.mod h1:PoGiBqK github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= -github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag= +github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/term v0.0.0-20200312100748-672ec06f55cd/go.mod h1:DdlQx2hp0Ss5/fLikoLlEeIYiATotOjgB//nb973jeo= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= @@ -448,6 +513,7 @@ github.com/sethvargo/go-limiter v0.6.0/go.mod h1:C0kbSFbiriE5k2FFOe18M1YZbAR2Fiw github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/slok/go-http-metrics v0.9.0 h1:o7A7j2DHs7Bnz8aGMotQLele28vf/Cl+O9cwJ6HyGk4= github.com/slok/go-http-metrics v0.9.0/go.mod h1:VCio4Xl8m11JM/0Sl9265RdKyiMypzMo3w1M8xcZGtk= @@ -543,11 +609,14 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0 h1:hb9wdF1z5waM+dSIICn1l0DkLVDT3hqhhQsDNUmHPRE= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b h1:7mWr3k41Qtv8XlltBkDkl8LoP3mpSgBW8BUoxtEdbXg= +golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -611,8 +680,10 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a h1:njMmldwFTyDLqonHMagNXKBWptTBeDZOdblgaDsNEGQ= +golang.org/x/net v0.0.0-20210427231257-85d9c07bbe3a/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/oauth2 v0.0.0-20180227000427-d7d64896b5ff/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -671,15 +742,20 @@ golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201112073958-5cba982894dd h1:5CtCZbICpIOFdgO940moixOPjc0178IU44m4EjOO5IY= golang.org/x/sys v0.0.0-20201112073958-5cba982894dd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.4 h1:0YWbFKbhXG/wIiuHDSKpS0Iy7FSA+u45VtBMfQcFTTc= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= @@ -796,6 +872,7 @@ google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4 google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/internal/notifier/eventhub.go b/internal/notifier/azure_eventhub.go similarity index 73% rename from internal/notifier/eventhub.go rename to internal/notifier/azure_eventhub.go index a05f2bcd0..ae7cee962 100644 --- a/internal/notifier/eventhub.go +++ b/internal/notifier/azure_eventhub.go @@ -1,5 +1,5 @@ /* -Copyright 2020 The Flux authors +Copyright 2021 The Flux authors 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 @@ -23,23 +23,25 @@ import ( "github.com/fluxcd/pkg/runtime/events" ) -type EventHub struct { +// AzureEventHub holds the eventhub client +type AzureEventHub struct { Hub *eventhub.Hub } -func NewEventHub(endpointURL string) (*EventHub, error) { +// NewAzureEventHub creates a eventhub client +func NewAzureEventHub(endpointURL string) (*AzureEventHub, error) { hub, err := eventhub.NewHubFromConnectionString(endpointURL) if err != nil { return nil, err } - return &EventHub{ + return &AzureEventHub{ Hub: hub, }, nil } -// Post EventHub msg -func (e *EventHub) Post(event events.Event) error { - ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) +// Post all notification-controller messages to EventHub +func (e *AzureEventHub) Post(event events.Event) error { + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() eventBytes, err := json.Marshal(event) @@ -47,13 +49,12 @@ func (e *EventHub) Post(event events.Event) error { return fmt.Errorf("Unable to marshall event: %w", err) } - //err := e.Hub.Send(ctx, eventhub.NewEventFromString("From, String")) err = e.Hub.Send(ctx, eventhub.NewEvent(eventBytes)) if err != nil { return fmt.Errorf("Failed to send msg: %w", err) } - err = e.Hub.Close(context.Background()) + err = e.Hub.Close(ctx) if err != nil { return fmt.Errorf("Unable to close connection: %w", err) } diff --git a/internal/notifier/factory.go b/internal/notifier/factory.go index 40b81457f..0dcbb52e6 100644 --- a/internal/notifier/factory.go +++ b/internal/notifier/factory.go @@ -75,8 +75,8 @@ func (f Factory) Notifier(provider string) (Interface, error) { n, err = NewWebex(f.URL, f.ProxyURL, f.CertPool) case v1beta1.SentryProvider: n, err = NewSentry(f.CertPool, f.URL) - case v1beta1.EventHubProvider: - n, err = NewEventHub(f.URL) + case v1beta1.AzureEventHubProvider: + n, err = NewAzureEventHub(f.URL) default: err = fmt.Errorf("provider %s not supported", provider) } From 45a77978b50f633f3e3e04ad97265249f8695ec0 Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Tue, 4 May 2021 15:22:28 +0200 Subject: [PATCH 3/9] Support both JWT and SAS connection string Depending if endpointURL starts with Endpoint or not we assume that it's a JWT token or not. Making sure that the JWT token is up to date is NOT the notifcation-controllers work Signed-off-by: Edvin Norling --- internal/notifier/azure_eventhub.go | 61 +++++++++++++++++++++++++++-- 1 file changed, 58 insertions(+), 3 deletions(-) diff --git a/internal/notifier/azure_eventhub.go b/internal/notifier/azure_eventhub.go index ae7cee962..59cd7d2f8 100644 --- a/internal/notifier/azure_eventhub.go +++ b/internal/notifier/azure_eventhub.go @@ -17,8 +17,10 @@ import ( "context" "encoding/json" "fmt" + "strings" "time" + "github.com/Azure/azure-amqp-common-go/v3/auth" eventhub "github.com/Azure/azure-event-hubs-go/v3" "github.com/fluxcd/pkg/runtime/events" ) @@ -30,10 +32,21 @@ type AzureEventHub struct { // NewAzureEventHub creates a eventhub client func NewAzureEventHub(endpointURL string) (*AzureEventHub, error) { - hub, err := eventhub.NewHubFromConnectionString(endpointURL) - if err != nil { - return nil, err + var hub *eventhub.Hub + var err error + + if strings.ToLower(endpointURL[:8]) != "endpoint" { + hub, err = newJWTHub(endpointURL) + if err != nil { + return nil, fmt.Errorf("failed to create a eventhub using JWT %v", err) + } + } else { + hub, err = newSASHub(endpointURL) + if err != nil { + return nil, fmt.Errorf("failed to create a eventhub using SAS %v", err) + } } + return &AzureEventHub{ Hub: hub, }, nil @@ -60,3 +73,45 @@ func (e *AzureEventHub) Post(event events.Event) error { } return nil } + +// PureJWT just contains the jwt +type PureJWT struct { + jwt string +} + +// NewJWTProvider create a pureJWT method +func NewJWTProvider(jwt string) *PureJWT { + return &PureJWT{ + jwt: jwt, + } +} + +// GetToken uses a JWT token, we assume that we will get new tokens when needed, thus no Expiry defined +func (j *PureJWT) GetToken(uri string) (*auth.Token, error) { + return &auth.Token{ + TokenType: auth.CBSTokenTypeJWT, + Token: j.jwt, + Expiry: "", + }, nil +} + +// newJWTHub used when address is a JWT token +func newJWTHub(address string) (*eventhub.Hub, error) { + provider := NewJWTProvider(address) + + hub, err := eventhub.NewHub("fluxv2", "fluxv2", provider) + if err != nil { + return nil, err + } + return hub, nil +} + +// newSASHub used when address is a SAS ConnectionString +func newSASHub(address string) (*eventhub.Hub, error) { + hub, err := eventhub.NewHubFromConnectionString(address) + if err != nil { + return nil, err + } + + return hub, nil +} From cfa71bf7a8d2b3406637d6ca143ef37225960d8e Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 5 May 2021 10:18:19 +0200 Subject: [PATCH 4/9] Use token & channel in azureevent For JWT * channel = eventhub namespace * address = eventhub name * token = jwt token For SAS * address = connectionString, including endpoint tokens etc Signed-off-by: Edvin Norling --- internal/notifier/azure_eventhub.go | 14 +++++++------- internal/notifier/factory.go | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/internal/notifier/azure_eventhub.go b/internal/notifier/azure_eventhub.go index 59cd7d2f8..ad45ac424 100644 --- a/internal/notifier/azure_eventhub.go +++ b/internal/notifier/azure_eventhub.go @@ -17,7 +17,6 @@ import ( "context" "encoding/json" "fmt" - "strings" "time" "github.com/Azure/azure-amqp-common-go/v3/auth" @@ -31,12 +30,13 @@ type AzureEventHub struct { } // NewAzureEventHub creates a eventhub client -func NewAzureEventHub(endpointURL string) (*AzureEventHub, error) { +func NewAzureEventHub(endpointURL, token, eventhubNamespace string) (*AzureEventHub, error) { var hub *eventhub.Hub var err error - if strings.ToLower(endpointURL[:8]) != "endpoint" { - hub, err = newJWTHub(endpointURL) + // token should only be defined if JWT is used + if token != "" { + hub, err = newJWTHub(endpointURL, token, eventhubNamespace) if err != nil { return nil, fmt.Errorf("failed to create a eventhub using JWT %v", err) } @@ -96,10 +96,10 @@ func (j *PureJWT) GetToken(uri string) (*auth.Token, error) { } // newJWTHub used when address is a JWT token -func newJWTHub(address string) (*eventhub.Hub, error) { - provider := NewJWTProvider(address) +func newJWTHub(eventhubName, token, eventhubNamespace string) (*eventhub.Hub, error) { + provider := NewJWTProvider(token) - hub, err := eventhub.NewHub("fluxv2", "fluxv2", provider) + hub, err := eventhub.NewHub(eventhubNamespace, eventhubName, provider) if err != nil { return nil, err } diff --git a/internal/notifier/factory.go b/internal/notifier/factory.go index 0dcbb52e6..b2cd1f250 100644 --- a/internal/notifier/factory.go +++ b/internal/notifier/factory.go @@ -76,7 +76,7 @@ func (f Factory) Notifier(provider string) (Interface, error) { case v1beta1.SentryProvider: n, err = NewSentry(f.CertPool, f.URL) case v1beta1.AzureEventHubProvider: - n, err = NewAzureEventHub(f.URL) + n, err = NewAzureEventHub(f.URL, f.Token, f.Channel) default: err = fmt.Errorf("provider %s not supported", provider) } From 56d8b0b51619d18174ec0a183c1794b1bfb32571 Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 5 May 2021 11:00:57 +0200 Subject: [PATCH 5/9] Initial docs for azure eventhub Signed-off-by: Edvin Norling --- docs/spec/v1beta1/provider.md | 81 ++++++++++++++++++++++++++++++++++- 1 file changed, 80 insertions(+), 1 deletion(-) diff --git a/docs/spec/v1beta1/provider.md b/docs/spec/v1beta1/provider.md index db2e25d02..8a83896e4 100644 --- a/docs/spec/v1beta1/provider.md +++ b/docs/spec/v1beta1/provider.md @@ -46,7 +46,7 @@ Notification providers: * Google Chat * Webex * Sentry -* EventHub +* AzureEventHub * Generic webhook Git commit status providers: @@ -223,3 +223,82 @@ SECRET_NAME=tls-certs kubectl create secret generic $SECRET_NAME \ --from-file=caFile=ca.crt ``` + +### Azure EventHub + +The Azure EventHub supports two authentication methods, [JWT](https://docs.microsoft.com/en-us/azure/event-hubs/authenticate-application) and [SAS](https://docs.microsoft.com/en-us/azure/event-hubs/authorize-access-shared-access-signature) based. + +#### JWT based auth + +In JWT we use 3 input values. + +Channel, token and address. We perform the follow translation to match we the data we need to communicate with Azure EventHub. + +* channel = Azure EventHub namespace +* address = Azure EventHub name +* token = JWT + +```yaml +apiVersion: notification.toolkit.fluxcd.io/v1beta1 +kind: Provider +metadata: + name: azureeventhub +spec: + type: azureeventhub + channel: fluxv2 + secretRef: + name: webhook-url +``` + +Notification controller don't take any responsibility for the JWT token to be updated. +You need to use a secondary tool to make sure that the token in the secret is renewed. + +If you want to make a easy test assuming that you have setup a Azure Enterprise application and you called it event-hub you can follow most of the bellow commands. +You will need to provide the client_secret that you got when generating the Azure Enterprise Application. + +```shell +export AZURE_CLIENT=$(az ad app list --filter "startswith(displayName,'event-hub')" --query '[].appId' |jq -r '.[0]') +export AZURE_SECRET='secret-client-secret-generated-at-creation' +export AZURE_TENANT=$(az account show -o tsv --query tenantId) + +curl -X GET --data 'grant_type=client_credentials' --data "client_id=$AZURE_CLIENT" --data "client_secret=$AZURE_SECRET" --data 'resource=https://eventhubs.azure.net' -H 'Content-Type: application/x-www-form-urlencoded' https://login.microsoftonline.com/$AZURE_TENANT/oauth2/token |jq .access_token +``` + +Use the output you got from the curl and add it to your secret like bellow. + +```shell +kubectl create secret generic webhook-url \ +--from-literal=address="fluxv2" \ +--from-literal=token='A-valid-JWT-token' +``` + +#### SAS based auth + +In SAS we only use the `address`field in the secret. + +```yaml +apiVersion: notification.toolkit.fluxcd.io/v1beta1 +kind: Provider +metadata: + name: azureeventhub +spec: + type: azureeventhub + secretRef: + name: webhook-url +``` + +Assuming that you have created Azure eventhub and namespace you should be able to use a similar command to get your connection string. +This will give you the default Root SAS, it's NOT supposed to be used in production. + +```shell +az eventhubs namespace authorization-rule keys list --resource-group --namespace-name --name RootManageSharedAccessKey -o tsv --query primaryConnectionString +# The output should look something like this: +Endpoint=sb://fluxv2.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yoursaskeygeneatedbyazure +``` + +To create the needed secret: + +```shell +kubectl create secret generic webhook-url \ +--from-literal=address="Endpoint=sb://fluxv2.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=yoursaskeygeneatedbyazure" +``` From 03b0275dc2acfc1a1f94baf7b55db5e5ad2db9f3 Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 5 May 2021 15:50:00 +0200 Subject: [PATCH 6/9] Update go.mod Signed-off-by: Edvin Norling --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2d59fa199..03284bc66 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.15 replace github.com/fluxcd/notification-controller/api => ./api require ( - github.com/Azure/azure-amqp-common-go/v3 v3.1.0 // indirect + github.com/Azure/azure-amqp-common-go/v3 v3.1.0 github.com/Azure/azure-event-hubs-go/v3 v3.3.7 github.com/Azure/azure-sdk-for-go v53.4.0+incompatible // indirect github.com/Azure/go-amqp v0.13.6 // indirect From ef5a7cdcb6e28eb7caca066f49ee6ddfbb74541d Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 5 May 2021 16:29:58 +0200 Subject: [PATCH 7/9] Change name to Azure Event Hub * Add secret example for SAS and JWT Signed-off-by: Edvin Norling --- docs/spec/v1beta1/provider.md | 39 ++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 8 deletions(-) diff --git a/docs/spec/v1beta1/provider.md b/docs/spec/v1beta1/provider.md index 8a83896e4..54986094e 100644 --- a/docs/spec/v1beta1/provider.md +++ b/docs/spec/v1beta1/provider.md @@ -46,7 +46,7 @@ Notification providers: * Google Chat * Webex * Sentry -* AzureEventHub +* Azure Event Hub * Generic webhook Git commit status providers: @@ -224,18 +224,18 @@ kubectl create secret generic $SECRET_NAME \ --from-file=caFile=ca.crt ``` -### Azure EventHub +### Azure Event Hub -The Azure EventHub supports two authentication methods, [JWT](https://docs.microsoft.com/en-us/azure/event-hubs/authenticate-application) and [SAS](https://docs.microsoft.com/en-us/azure/event-hubs/authorize-access-shared-access-signature) based. +The Azure Event Hub supports two authentication methods, [JWT](https://docs.microsoft.com/en-us/azure/event-hubs/authenticate-application) and [SAS](https://docs.microsoft.com/en-us/azure/event-hubs/authorize-access-shared-access-signature) based. #### JWT based auth In JWT we use 3 input values. -Channel, token and address. We perform the follow translation to match we the data we need to communicate with Azure EventHub. +Channel, token and address. We perform the following translation to match we the data we need to communicate with Azure Event Hub. -* channel = Azure EventHub namespace -* address = Azure EventHub name +* channel = Azure Event Hub namespace +* address = Azure Event Hub name * token = JWT ```yaml @@ -250,7 +250,19 @@ spec: name: webhook-url ``` -Notification controller don't take any responsibility for the JWT token to be updated. +```yaml +apiVersion: v1 +data: + address: Zmx1eHYy + token: QS12YWxpZC1KV1QtdG9rZW4= +kind: Secret +metadata: + name: webhook-url + namespace: default +type: Opaque +``` + +Notification controller doesn't take any responsibility for the JWT token to be updated. You need to use a secondary tool to make sure that the token in the secret is renewed. If you want to make a easy test assuming that you have setup a Azure Enterprise application and you called it event-hub you can follow most of the bellow commands. @@ -287,7 +299,18 @@ spec: name: webhook-url ``` -Assuming that you have created Azure eventhub and namespace you should be able to use a similar command to get your connection string. +```yaml +apiVersion: v1 +data: + address: RW5kcG9pbnQ9c2I6Ly9mbHV4djIuc2VydmljZWJ1cy53aW5kb3dzLm5ldC87U2hhcmVkQWNjZXNzS2V5TmFtZT1Sb290TWFuYWdlU2hhcmVkQWNjZXNzS2V5O1NoYXJlZEFjY2Vzc0tleT15b3Vyc2Fza2V5Z2VuZWF0ZWRieWF6dXJlCg== +kind: Secret +metadata: + name: webhook-url + namespace: default +type: Opaque +``` + +Assuming that you have created Azure event hub and namespace you should be able to use a similar command to get your connection string. This will give you the default Root SAS, it's NOT supposed to be used in production. ```shell From 730565e05eb1af6cf3dc8cdb6d473d4a8f163fba Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Wed, 5 May 2021 16:39:47 +0200 Subject: [PATCH 8/9] Ignore event updates * Change name of var eventhubNamespace to eventhubNamespace Signed-off-by: Edvin Norling --- internal/notifier/azure_eventhub.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/notifier/azure_eventhub.go b/internal/notifier/azure_eventhub.go index ad45ac424..b92b26631 100644 --- a/internal/notifier/azure_eventhub.go +++ b/internal/notifier/azure_eventhub.go @@ -30,13 +30,13 @@ type AzureEventHub struct { } // NewAzureEventHub creates a eventhub client -func NewAzureEventHub(endpointURL, token, eventhubNamespace string) (*AzureEventHub, error) { +func NewAzureEventHub(endpointURL, token, eventHubNamespace string) (*AzureEventHub, error) { var hub *eventhub.Hub var err error // token should only be defined if JWT is used if token != "" { - hub, err = newJWTHub(endpointURL, token, eventhubNamespace) + hub, err = newJWTHub(endpointURL, token, eventHubNamespace) if err != nil { return nil, fmt.Errorf("failed to create a eventhub using JWT %v", err) } @@ -54,6 +54,11 @@ func NewAzureEventHub(endpointURL, token, eventhubNamespace string) (*AzureEvent // Post all notification-controller messages to EventHub func (e *AzureEventHub) Post(event events.Event) error { + // Skip any update events + if isCommitStatus(event.Metadata, "update") { + return nil + } + ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() @@ -96,10 +101,10 @@ func (j *PureJWT) GetToken(uri string) (*auth.Token, error) { } // newJWTHub used when address is a JWT token -func newJWTHub(eventhubName, token, eventhubNamespace string) (*eventhub.Hub, error) { +func newJWTHub(eventhubName, token, eventHubNamespace string) (*eventhub.Hub, error) { provider := NewJWTProvider(token) - hub, err := eventhub.NewHub(eventhubNamespace, eventhubName, provider) + hub, err := eventhub.NewHub(eventHubNamespace, eventhubName, provider) if err != nil { return nil, err } From 39596a27e199ffeb4e844e1c06417705c6c99400 Mon Sep 17 00:00:00 2001 From: Edvin Norling Date: Thu, 6 May 2021 09:01:29 +0200 Subject: [PATCH 9/9] Put secret together with Provider info Signed-off-by: Edvin Norling --- docs/spec/v1beta1/provider.md | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/docs/spec/v1beta1/provider.md b/docs/spec/v1beta1/provider.md index 54986094e..ce68c32c3 100644 --- a/docs/spec/v1beta1/provider.md +++ b/docs/spec/v1beta1/provider.md @@ -248,9 +248,7 @@ spec: channel: fluxv2 secretRef: name: webhook-url -``` - -```yaml +--- apiVersion: v1 data: address: Zmx1eHYy @@ -297,9 +295,7 @@ spec: type: azureeventhub secretRef: name: webhook-url -``` - -```yaml +--- apiVersion: v1 data: address: RW5kcG9pbnQ9c2I6Ly9mbHV4djIuc2VydmljZWJ1cy53aW5kb3dzLm5ldC87U2hhcmVkQWNjZXNzS2V5TmFtZT1Sb290TWFuYWdlU2hhcmVkQWNjZXNzS2V5O1NoYXJlZEFjY2Vzc0tleT15b3Vyc2Fza2V5Z2VuZWF0ZWRieWF6dXJlCg==