diff --git a/services/actions-handler/go.sum b/services/actions-handler/go.sum index d463fd2dc5..ca98698ba3 100644 --- a/services/actions-handler/go.sum +++ b/services/actions-handler/go.sum @@ -842,8 +842,6 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= -github.com/uselagoon/machinery v0.0.24 h1:Kea7eQiwqrlF1NnG4YmV5dMNM1NxuhiY1vhoahEFkQA= -github.com/uselagoon/machinery v0.0.24/go.mod h1:NbgtEofjK2XY0iUpk9aMYazIo+W/NI56+UF72jv8zVY= github.com/uselagoon/machinery v0.0.29 h1:invFIPv1Z1xCt8/1ilbiNDuAEPrb+AUO21BnNG+CX8c= github.com/uselagoon/machinery v0.0.29/go.mod h1:X0qguIO9skumMhhT0ap5CKHulKgYzy3TiIn+xlwiFQc= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= diff --git a/services/logs2notifications/go.mod b/services/logs2notifications/go.mod index fd9b429bdc..b205e9aa44 100644 --- a/services/logs2notifications/go.mod +++ b/services/logs2notifications/go.mod @@ -6,19 +6,22 @@ require ( github.com/aws/aws-sdk-go v1.55.5 github.com/cheshir/go-mq/v2 v2.0.1 github.com/dgrijalva/jwt-go v3.2.0+incompatible - github.com/machinebox/graphql v0.2.3-0.20181106130121-3a9253180225 github.com/matryer/try v0.0.0-20161228173917-9ac251b645a2 github.com/slack-go/slack v0.13.1 + github.com/uselagoon/machinery v0.0.29 gopkg.in/mail.v2 v2.3.1 ) require ( github.com/NeowayLabs/wabbit v0.0.0-20210927194032-73ad61d1620e // indirect github.com/cheekybits/is v0.0.0-20150225183255-68e9c0620927 // indirect + github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/google/uuid v1.6.0 // indirect github.com/gorilla/websocket v1.5.3 // indirect + github.com/guregu/null v4.0.0+incompatible // indirect + github.com/hashicorp/go-version v1.6.0 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect - github.com/matryer/is v1.4.0 // indirect + github.com/machinebox/graphql v0.2.3-0.20181106130121-3a9253180225 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/rabbitmq/amqp091-go v1.10.0 // indirect diff --git a/services/logs2notifications/go.sum b/services/logs2notifications/go.sum index 1696d19a27..3814b9458d 100644 --- a/services/logs2notifications/go.sum +++ b/services/logs2notifications/go.sum @@ -110,8 +110,6 @@ github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmV github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.15.11/go.mod h1:mFuSZ37Z9YOHbQEwBWztmVzqXrEkub65tZoCYDt7FT0= -github.com/aws/aws-sdk-go v1.55.3 h1:0B5hOX+mIx7I5XPOrjrHlKSDQV/+ypFZpIHOx5LOk3E= -github.com/aws/aws-sdk-go v1.55.3/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= github.com/benbjohnson/clock v1.0.3/go.mod h1:bGMdMPoPVvcYyt1gHDf4J2KE153Yf9BuiUKYMaxlTDM= @@ -414,6 +412,8 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= +github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= +github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -515,6 +515,8 @@ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgf github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= +github.com/guregu/null v4.0.0+incompatible h1:4zw0ckM7ECd6FNNddc3Fu4aty9nTlpkkzH7dPn4/4Gw= +github.com/guregu/null v4.0.0+incompatible/go.mod h1:ePGpQaN9cw0tj45IR5E5ehMvsFlLlQZAkkOXZurJ3NM= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= @@ -531,6 +533,8 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.6.0 h1:feTTfFNnjP967rlCxM/I9g701jU+RN74YKx2mOkIeek= +github.com/hashicorp/go-version v1.6.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= @@ -854,6 +858,8 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/uselagoon/machinery v0.0.29 h1:invFIPv1Z1xCt8/1ilbiNDuAEPrb+AUO21BnNG+CX8c= +github.com/uselagoon/machinery v0.0.29/go.mod h1:X0qguIO9skumMhhT0ap5CKHulKgYzy3TiIn+xlwiFQc= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netlink v1.1.1-0.20201029203352-d40f9887b852/go.mod h1:twkDnbuQxJYemMlGd4JFIcuhgX83tXhKS2B/PRMpOho= @@ -1167,8 +1173,9 @@ golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220405210540-1e041c57c461/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f h1:v4INt8xihDGvnrfjMDVXGxw9wrfxYyCjk0KbXjhR55s= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= diff --git a/services/logs2notifications/internal/handler/email_events.go b/services/logs2notifications/internal/handler/email_events.go index f26c19e463..251abb5be3 100644 --- a/services/logs2notifications/internal/handler/email_events.go +++ b/services/logs2notifications/internal/handler/email_events.go @@ -210,7 +210,7 @@ func (h *Messaging) sendEmailMessage(emoji, color, subject, event, project, emai } } - log.Println(fmt.Sprintf("Sent %s message to email for project %s", event, project)) + log.Printf("Sent %s message to email for project %s", event, project) } func getEmailEvent(msgEvent string) (string, string, string, error) { diff --git a/services/logs2notifications/internal/handler/main.go b/services/logs2notifications/internal/handler/main.go index 89a1823728..8c81d5f6ce 100644 --- a/services/logs2notifications/internal/handler/main.go +++ b/services/logs2notifications/internal/handler/main.go @@ -10,10 +10,11 @@ import ( mq "github.com/cheshir/go-mq/v2" "github.com/matryer/try" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/lagoon" - lclient "github.com/uselagoon/lagoon/services/logs2notifications/internal/lagoon/client" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/lagoon/jwt" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/schema" + + "github.com/uselagoon/machinery/api/lagoon" + lclient "github.com/uselagoon/machinery/api/lagoon/client" + "github.com/uselagoon/machinery/api/schema" + "github.com/uselagoon/machinery/utils/jwt" ) // RabbitBroker . @@ -31,6 +32,7 @@ type LagoonAPI struct { TokenSigningKey string `json:"tokenSigningKey"` JWTSubject string `json:"subject"` JWTIssuer string `json:"issuer"` + Version string `json:"version"` } // Action is the structure of an action that is received via the message queue. @@ -40,11 +42,6 @@ type Action struct { Data map[string]interface{} `json:"data"` // contains the payload for the action, this could be any json so using a map } -type messaging interface { - Consumer() - Publish(string, []byte) -} - // Messaging is used for the config and client information for the messaging queue. type Messaging struct { Config mq.Config @@ -204,7 +201,7 @@ func (h *Messaging) Consumer() { go func() { for err := range messageQueue.Error() { - log.Println(fmt.Sprintf("Caught error from message queue: %v", err)) + log.Printf("Caught error from message queue: %v", err) } }() @@ -217,7 +214,7 @@ func (h *Messaging) Consumer() { message.Ack(false) // ack to remove from queue }) if err != nil { - log.Println(fmt.Sprintf("Failed to set handler to consumer `%s`: %v", "items-queue", err)) + log.Printf("Failed to set handler to consumer `%s`: %v", "items-queue", err) } <-forever } @@ -282,7 +279,7 @@ func (h *Messaging) processMessage(message []byte) { } func (h *Messaging) getProjectNotifictions(ctx context.Context, projectName string) (*schema.Project, error) { - token, err := jwt.OneMinuteAdminToken(h.LagoonAPI.TokenSigningKey, h.LagoonAPI.JWTAudience, h.LagoonAPI.JWTSubject, h.LagoonAPI.JWTIssuer) + token, err := jwt.GenerateAdminToken(h.LagoonAPI.TokenSigningKey, h.LagoonAPI.JWTAudience, h.LagoonAPI.JWTSubject, h.LagoonAPI.JWTIssuer, time.Now().Unix(), 60) if err != nil { // the token wasn't generated if h.EnableDebug { @@ -291,7 +288,7 @@ func (h *Messaging) getProjectNotifictions(ctx context.Context, projectName stri return nil, err } // get all notifications for said project - l := lclient.New(h.LagoonAPI.Endpoint, token, "logs2notifications", false) + l := lclient.New(h.LagoonAPI.Endpoint, "actions-handler", h.LagoonAPI.Version, &token, false) projectNotifications, err := lagoon.NotificationsForProject(ctx, projectName, l) if err != nil { log.Println(err) diff --git a/services/logs2notifications/internal/handler/main_test.go b/services/logs2notifications/internal/handler/main_test.go index 698f6757bd..f10ad3b316 100644 --- a/services/logs2notifications/internal/handler/main_test.go +++ b/services/logs2notifications/internal/handler/main_test.go @@ -1,26 +1,13 @@ package handler import ( - "bytes" "encoding/json" "io/ioutil" - "reflect" "testing" mq "github.com/cheshir/go-mq/v2" ) -func checkEqual(t *testing.T, got, want interface{}, msgs ...interface{}) { - if !reflect.DeepEqual(got, want) { - buf := bytes.Buffer{} - buf.WriteString("got:\n[%v]\nwant:\n[%v]\n") - for _, v := range msgs { - buf.WriteString(v.(string)) - } - t.Errorf(buf.String(), got, want) - } -} - func TestProcessing(t *testing.T) { config := mq.Config{} graphQLConfig := LagoonAPI{ diff --git a/services/logs2notifications/internal/handler/microsoftteams_events.go b/services/logs2notifications/internal/handler/microsoftteams_events.go index e335cd9601..bd97a9e82e 100644 --- a/services/logs2notifications/internal/handler/microsoftteams_events.go +++ b/services/logs2notifications/internal/handler/microsoftteams_events.go @@ -115,6 +115,10 @@ func (h *Messaging) sendMicrosoftTeamsMessage(emoji, color, webhook, event, proj teamsPayloadBytes, _ := json.Marshal(teamsPayload) req, err := http.NewRequest("POST", webhook, bytes.NewBuffer(teamsPayloadBytes)) + if err != nil { + log.Printf("Error sending message to microsoft teams for project %s: %v", project, err) + return + } req.Header.Set("Content-Type", "application/json") client := &http.Client{} @@ -124,7 +128,7 @@ func (h *Messaging) sendMicrosoftTeamsMessage(emoji, color, webhook, event, proj return } defer resp.Body.Close() - log.Println(fmt.Sprintf("Sent %s message to microsoft teams for project %s", event, project)) + log.Printf("Sent %s message to microsoft teams for project %s", event, project) } func getMicrosoftTeamsEvent(msgEvent string) (string, string, string, error) { diff --git a/services/logs2notifications/internal/handler/rocketchat_events.go b/services/logs2notifications/internal/handler/rocketchat_events.go index aabcce38c8..4e5c6c237a 100644 --- a/services/logs2notifications/internal/handler/rocketchat_events.go +++ b/services/logs2notifications/internal/handler/rocketchat_events.go @@ -120,6 +120,10 @@ func (h *Messaging) sendRocketChatMessage(emoji, color, appID, channel, webhook, } jsonBytes, _ := json.Marshal(data) req, err := http.NewRequest("POST", webhook, bytes.NewBuffer(jsonBytes)) + if err != nil { + log.Printf("Error sending message to rocketchat channel %s for project %s: %v", channel, project, err) + return + } req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Length", fmt.Sprintf("%d", len(jsonBytes))) @@ -130,7 +134,7 @@ func (h *Messaging) sendRocketChatMessage(emoji, color, appID, channel, webhook, return } defer resp.Body.Close() - log.Println(fmt.Sprintf("Sent %s message to rocketchat channel %s for project %s", event, channel, project)) + log.Printf("Sent %s message to rocketchat channel %s for project %s", event, channel, project) } func getRocketChatEvent(msgEvent string) (string, string, string, error) { diff --git a/services/logs2notifications/internal/handler/s3_events.go b/services/logs2notifications/internal/handler/s3_events.go index 5a534943e8..1959d918ed 100644 --- a/services/logs2notifications/internal/handler/s3_events.go +++ b/services/logs2notifications/internal/handler/s3_events.go @@ -9,7 +9,7 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/s3" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/helpers" + "github.com/uselagoon/machinery/utils/namespace" ) // MessageType . @@ -41,7 +41,7 @@ func (h *Messaging) SendToS3(notification *Notification, msgType MessageType) { if notification.Meta.Environment != "" { filePath = fmt.Sprintf("tasklogs/%s/%s/%s-%s.txt", notification.Project, - helpers.ShortenEnvironment(notification.Project, helpers.MakeSafe(notification.Meta.Environment)), + namespace.ShortenEnvironment(notification.Project, namespace.MakeSafe(notification.Meta.Environment)), notification.Meta.Task.ID, notification.Meta.RemoteID, ) @@ -56,8 +56,7 @@ func (h *Messaging) SendToS3(notification *Notification, msgType MessageType) { // UploadFileS3 func (h *Messaging) uploadFileS3(message, fileName string) { - var forcePath bool - forcePath = true + forcePath := true session, err := session.NewSession(&aws.Config{ Region: aws.String(h.S3FilesRegion), Endpoint: aws.String(h.S3FilesOrigin), @@ -81,6 +80,5 @@ func (h *Messaging) uploadFileS3(message, fileName string) { if err != nil { log.Println(err) } - log.Println(fmt.Sprintf("Uploaded file %s", fileName)) - return + log.Printf("Uploaded file %s\n", fileName) } diff --git a/services/logs2notifications/internal/handler/slack_events.go b/services/logs2notifications/internal/handler/slack_events.go index c7484cee27..9b2a60657e 100644 --- a/services/logs2notifications/internal/handler/slack_events.go +++ b/services/logs2notifications/internal/handler/slack_events.go @@ -101,7 +101,7 @@ func (h *Messaging) sendSlackMessage(emoji, color, appID, channel, webhook, even log.Printf("Error sending message to slack channel %s for project %s: %v", channel, project, err) return } - log.Println(fmt.Sprintf("Sent %s message to slack channel %s for project %s", event, channel, project)) + log.Printf("Sent %s message to slack channel %s for project %s", event, channel, project) } func getSlackEvent(msgEvent string) (string, string, string, error) { diff --git a/services/logs2notifications/internal/handler/webhook_events.go b/services/logs2notifications/internal/handler/webhook_events.go index 57bee762b2..a272c416e8 100644 --- a/services/logs2notifications/internal/handler/webhook_events.go +++ b/services/logs2notifications/internal/handler/webhook_events.go @@ -8,7 +8,7 @@ import ( "net/http" "strings" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/schema" + "github.com/uselagoon/machinery/api/schema" ) // WebhookData . @@ -24,7 +24,7 @@ type WebhookData struct { } // SendToWebhook . -func (h *Messaging) SendToWebhook(notification *Notification, webhook schema.NotificationWebhook) { +func (h *Messaging) SendToWebhook(notification *Notification, webhook schema.AddNotificationWebhookInput) { message, err := h.processWebhookTemplate(notification) if err != nil { return @@ -32,9 +32,13 @@ func (h *Messaging) SendToWebhook(notification *Notification, webhook schema.Not h.sendWebhookMessage(notification.Meta.ProjectName, *message, webhook) } -func (h *Messaging) sendWebhookMessage(project string, data WebhookData, webhook schema.NotificationWebhook) { +func (h *Messaging) sendWebhookMessage(project string, data WebhookData, webhook schema.AddNotificationWebhookInput) { message, _ := json.Marshal(data) req, err := http.NewRequest("POST", webhook.Webhook, bytes.NewBuffer(message)) + if err != nil { + log.Printf("Error sending message to webhook: %v", err) + return + } req.Header.Set("Content-Type", "application/json") req.Header.Set("Content-Length", fmt.Sprintf("%d", len(message))) @@ -45,13 +49,7 @@ func (h *Messaging) sendWebhookMessage(project string, data WebhookData, webhook return } defer resp.Body.Close() - log.Println(fmt.Sprintf("Sent %s message to webhook", data.Event)) - if err != nil { - log.Printf("Error sending message to webhook for project %s: %v", project, err) - return - } - defer resp.Body.Close() - log.Println(fmt.Sprintf("Sent %s message to webhook for project %s", data.Event, project)) + log.Printf("Sent %s message to webhook for project %s", data.Event, project) } // processWebhookTemplate . diff --git a/services/logs2notifications/internal/helpers/helpers.go b/services/logs2notifications/internal/helpers/helpers.go deleted file mode 100644 index 46d554bf6f..0000000000 --- a/services/logs2notifications/internal/helpers/helpers.go +++ /dev/null @@ -1,77 +0,0 @@ -package helpers - -import ( - "crypto/sha1" - "fmt" - "regexp" - "strings" -) - -const ( - // DefaultNamespacePattern is what is used when one is not provided. - DefaultNamespacePattern = "${project}-${environment}" -) - -// GenerateNamespaceName handles the generation of the namespace name from environment and project name with prefixes and patterns -func GenerateNamespaceName(pattern, environmentName, projectname, prefix, controllerNamespace string, randomPrefix bool) string { - nsPattern := pattern - if pattern == "" { - nsPattern = DefaultNamespacePattern - } - environmentName = ShortenEnvironment(projectname, MakeSafe(environmentName)) - // lowercase and dnsify the namespace against the namespace pattern - ns := MakeSafe( - strings.Replace( - strings.Replace( - nsPattern, - "${environment}", - environmentName, - -1, - ), - "${project}", - projectname, - -1, - ), - ) - // If there is a namespaceprefix defined, and random prefix is disabled - // then add the prefix to the namespace - if prefix != "" && randomPrefix == false { - ns = fmt.Sprintf("%s-%s", prefix, ns) - } - // If the randomprefix is enabled, then add a prefix based on the hash of the controller namespace - if randomPrefix { - ns = fmt.Sprintf("%s-%s", HashString(controllerNamespace)[0:8], ns) - } - // Once the namespace is fully calculated, then truncate the generated namespace - // to 63 characters to not exceed the kubernetes namespace limit - if len(ns) > 63 { - ns = fmt.Sprintf("%s-%s", ns[0:58], HashString(ns)[0:4]) - } - return ns -} - -// ShortenEnvironment shortens the environment name down the same way that Lagoon does -func ShortenEnvironment(project, environment string) string { - overlength := 58 - len(project) - if len(environment) > overlength { - environment = fmt.Sprintf("%s-%s", environment[0:overlength-5], HashString(environment)[0:4]) - } - return environment -} - -// MakeSafe ensures that any string is dns safe -func MakeSafe(in string) string { - out := regexp.MustCompile(`[^0-9a-z-]`).ReplaceAllString( - strings.ToLower(in), - "$1-$2", - ) - return out -} - -// HashString get the hash of a given string. -func HashString(s string) string { - h := sha1.New() - h.Write([]byte(s)) - bs := h.Sum(nil) - return fmt.Sprintf("%x", bs) -} diff --git a/services/logs2notifications/internal/helpers/helpers_test.go b/services/logs2notifications/internal/helpers/helpers_test.go deleted file mode 100644 index 6967bf4d8d..0000000000 --- a/services/logs2notifications/internal/helpers/helpers_test.go +++ /dev/null @@ -1,160 +0,0 @@ -package helpers - -import ( - "testing" -) - -func TestGenerateNamespaceName(t *testing.T) { - type args struct { - pattern string - environmentName string - projectname string - prefix string - controllerNamespace string - randomPrefix bool - } - tests := []struct { - name string - args args - want string - }{ - { - name: "really long environment name with slash and capitals", - args: args{ - pattern: "", - environmentName: "Feature/Really-Exceedingly-Long-Environment-Name-For-A-Branch", - projectname: "this-is-my-project", - prefix: "", - controllerNamespace: "lagoon", - randomPrefix: false, - }, - want: "this-is-my-project-feature-really-exceedingly-long-env-dc8c", - }, - { - name: "really long environment name with slash and no capitals", - args: args{ - pattern: "", - environmentName: "feature/really-exceedingly-long-environment-name-for-a-branch", - projectname: "this-is-my-project", - prefix: "", - controllerNamespace: "lagoon", - randomPrefix: false, - }, - want: "this-is-my-project-feature-really-exceedingly-long-env-dc8c", - }, - { - name: "short environment name with slash and capitals", - args: args{ - pattern: "", - environmentName: "Feature/Branch", - projectname: "this-is-my-project", - prefix: "", - controllerNamespace: "lagoon", - randomPrefix: false, - }, - want: "this-is-my-project-feature-branch", - }, - { - name: "short environment name with slash and no capitals", - args: args{ - pattern: "", - environmentName: "feature/branch", - projectname: "this-is-my-project", - prefix: "", - controllerNamespace: "lagoon", - randomPrefix: false, - }, - want: "this-is-my-project-feature-branch", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := GenerateNamespaceName(tt.args.pattern, tt.args.environmentName, tt.args.projectname, tt.args.prefix, tt.args.controllerNamespace, tt.args.randomPrefix); got != tt.want { - t.Errorf("GenerateNamespaceName() got %v, want %v", got, tt.want) - } - }) - } -} - -func TestMakeSafe(t *testing.T) { - tests := []struct { - name string - in string - want string - }{ - { - name: "slash in name", - in: "Feature/Branch", - want: "feature-branch", - }, - { - name: "noslash in name", - in: "Feature-Branch", - want: "feature-branch", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := MakeSafe(tt.in); got != tt.want { - t.Errorf("MakeSafe() go %v, want %v", got, tt.want) - } - }) - } -} - -func TestHashString(t *testing.T) { - tests := []struct { - name string - in string - want string - }{ - { - name: "generate hash", - in: "feature-branch", - want: "011122006d017c21d1376add9f7f65b43555a455", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := HashString(tt.in); got != tt.want { - t.Errorf("HashString() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestShortenEnvironment(t *testing.T) { - type args struct { - project string - environment string - } - tests := []struct { - name string - args args - want string - }{ - { - name: "really long environment name with slash and capitals", - args: args{ - environment: MakeSafe("Feature/Really-Exceedingly-Long-Environment-Name-For-A-Branch"), - project: "this-is-my-project", - }, - want: "feature-really-exceedingly-long-env-dc8c", - }, - { - name: "short environment name", - args: args{ - environment: MakeSafe("Feature/Branch"), - project: "this-is-my-project", - }, - want: "feature-branch", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := ShortenEnvironment(tt.args.project, tt.args.environment); got != tt.want { - t.Errorf("ShortenEnvironment() got %v, want %v", got, tt.want) - } - }) - } -} diff --git a/services/logs2notifications/internal/lagoon/client/_lgraphql/projectNotifications.graphql b/services/logs2notifications/internal/lagoon/client/_lgraphql/projectNotifications.graphql deleted file mode 100644 index a1f4eca381..0000000000 --- a/services/logs2notifications/internal/lagoon/client/_lgraphql/projectNotifications.graphql +++ /dev/null @@ -1,41 +0,0 @@ -query ( - $name: String! -) { - projectByName( - name: $name - ) { - id - name - notifications { - ... on NotificationSlack { - __typename - webhook - name - channel - } - ... on NotificationRocketChat { - __typename - webhook - name - channel - } - ... on NotificationEmail { - __typename - emailAddress - name - } - ... on NotificationMicrosoftTeams { - __typename - webhook - name - } - ... on NotificationWebhook { - __typename - webhook - name - contentType - notificationSeverityThreshold - } - } - } -} \ No newline at end of file diff --git a/services/logs2notifications/internal/lagoon/client/client.go b/services/logs2notifications/internal/lagoon/client/client.go deleted file mode 100644 index 9ca3bb2624..0000000000 --- a/services/logs2notifications/internal/lagoon/client/client.go +++ /dev/null @@ -1,93 +0,0 @@ -//go:generate go-bindata -pkg lgraphql -o lgraphql/lgraphql.go -nometadata _lgraphql/ - -// Package client implements the interfaces required by the parent lagoon -// package. -package client - -import ( - "encoding/json" - "fmt" - "log" - "os" - - "github.com/machinebox/graphql" - "github.com/uselagoon/lagoon/services/logs2notifications/internal/lagoon/client/lgraphql" -) - -// Client implements the lagoon package interfaces for the Lagoon GraphQL API. -type Client struct { - userAgent string - token string - client *graphql.Client -} - -// New creates a new Client for the given endpoint. -func New(endpoint, token, userAgent string, debug bool) *Client { - if debug { - return &Client{ - userAgent: userAgent, - token: token, - client: graphql.NewClient(endpoint, - // enable debug logging to stderr - func(c *graphql.Client) { - l := log.New(os.Stderr, "graphql", 0) - c.Log = func(s string) { - l.Println(s) - } - }), - } - } - return &Client{ - userAgent: userAgent, - token: token, - client: graphql.NewClient(endpoint), - } -} - -// newRequest constructs a graphql request. -// assetName is the name of the graphql query template in _graphql/. -// varStruct is converted to a map of variables for the template. -func (c *Client) newRequest( - assetName string, varStruct interface{}) (*graphql.Request, error) { - - q, err := lgraphql.Asset(assetName) - if err != nil { - return nil, fmt.Errorf("couldn't get asset: %w", err) - } - - return c.doRequest(string(q), varStruct) -} - -func (c *Client) doRequest(query string, varStruct interface{}) (*graphql.Request, error) { - vars, err := structToVarMap(varStruct) - if err != nil { - return nil, fmt.Errorf("couldn't convert struct to map: %w", err) - } - - req := graphql.NewRequest(query) - for key, value := range vars { - req.Var(key, value) - } - - headers := map[string]string{ - "User-Agent": c.userAgent, - "Authorization": fmt.Sprintf("Bearer %s", c.token), - } - for key, value := range headers { - req.Header.Set(key, value) - } - - return req, nil -} - -// structToVarMap encodes the given struct to a map. The idea is that by -// round-tripping through Marshal/Unmarshal, omitempty is applied to the -// zero-valued fields. -func structToVarMap( - varStruct interface{}) (vars map[string]interface{}, err error) { - data, err := json.Marshal(varStruct) - if err != nil { - return vars, err - } - return vars, json.Unmarshal(data, &vars) -} diff --git a/services/logs2notifications/internal/lagoon/client/query.go b/services/logs2notifications/internal/lagoon/client/query.go deleted file mode 100644 index a1e9a2cdca..0000000000 --- a/services/logs2notifications/internal/lagoon/client/query.go +++ /dev/null @@ -1,25 +0,0 @@ -package client - -import ( - "context" - - "github.com/uselagoon/lagoon/services/logs2notifications/internal/schema" -) - -// NotificationsForProjectByName gets all notifications for a project -func (c *Client) NotificationsForProjectByName( - ctx context.Context, name string, project *schema.Project) error { - req, err := c.newRequest("_lgraphql/projectNotifications.graphql", - map[string]interface{}{ - "name": name, - }) - if err != nil { - return err - } - - return c.client.Run(ctx, req, &struct { - Response *schema.Project `json:"projectByName"` - }{ - Response: project, - }) -} diff --git a/services/logs2notifications/internal/lagoon/project.go b/services/logs2notifications/internal/lagoon/project.go deleted file mode 100644 index 7208fc3501..0000000000 --- a/services/logs2notifications/internal/lagoon/project.go +++ /dev/null @@ -1,20 +0,0 @@ -// Package lagoon implements high-level functions for interacting with the -// Lagoon API. -package lagoon - -import ( - "context" - - "github.com/uselagoon/lagoon/services/logs2notifications/internal/schema" -) - -// Project interface contains methods for projects in lagoon. -type Project interface { - NotificationsForProjectByName(ctx context.Context, name string, result *schema.Project) error -} - -// NotificationsForProject gets notifications for a project. -func NotificationsForProject(ctx context.Context, name string, m Project) (*schema.Project, error) { - result := schema.Project{} - return &result, m.NotificationsForProjectByName(ctx, name, &result) -} diff --git a/services/logs2notifications/internal/schema/notifications.go b/services/logs2notifications/internal/schema/notifications.go deleted file mode 100644 index 33aeff6f61..0000000000 --- a/services/logs2notifications/internal/schema/notifications.go +++ /dev/null @@ -1,107 +0,0 @@ -package schema - -import ( - "encoding/json" - "fmt" -) - -// Notifications represents possible Lagoon notification types. -// These are unmarshalled from a projectByName query response. -type Notifications struct { - Slack []NotificationSlack - RocketChat []NotificationRocketChat - Email []NotificationEmail - MicrosoftTeams []NotificationMicrosoftTeams - Webhook []NotificationWebhook -} - -// NotificationSlack is based on the Lagoon API type. -type NotificationSlack struct { - Name string `json:"name"` - Webhook string `json:"webhook"` - Channel string `json:"channel"` -} - -// NotificationRocketChat is based on the Lagoon API type. -type NotificationRocketChat struct { - Name string `json:"name"` - Webhook string `json:"webhook"` - Channel string `json:"channel"` -} - -// NotificationEmail is based on the Lagoon API type. -type NotificationEmail struct { - Name string `json:"name"` - EmailAddress string `json:"emailAddress"` -} - -// NotificationMicrosoftTeams is based on the Lagoon API type. -type NotificationMicrosoftTeams struct { - Name string `json:"name"` - Webhook string `json:"webhook"` -} - -// NotificationWebhook is based on the Lagoon API type. -type NotificationWebhook struct { - Name string `json:"name"` - Webhook string `json:"webhook"` - ContentType string `json:"contentType"` - NotificationSeverityThreshold string `json:"notificationSeverityThreshold"` -} - -// UnmarshalJSON unmashals a quoted json string to the Notification values -// returned from the Lagoon API. -func (n *Notifications) UnmarshalJSON(b []byte) error { - var nArray []map[string]string - err := json.Unmarshal(b, &nArray) - if err != nil { - return err - } - for _, nMap := range nArray { - if len(nMap) == 0 { - // Unsupported notification type returns an empty map. - // This happens when the lagoon API being targeted is actually a higher - // version than configured. - continue - } - switch nMap["__typename"] { - case "NotificationSlack": - n.Slack = append(n.Slack, - NotificationSlack{ - Name: nMap["name"], - Webhook: nMap["webhook"], - Channel: nMap["channel"], - }) - case "NotificationRocketChat": - n.RocketChat = append(n.RocketChat, - NotificationRocketChat{ - Name: nMap["name"], - Webhook: nMap["webhook"], - Channel: nMap["channel"], - }) - case "NotificationEmail": - n.Email = append(n.Email, - NotificationEmail{ - Name: nMap["name"], - EmailAddress: nMap["emailAddress"], - }) - case "NotificationMicrosoftTeams": - n.MicrosoftTeams = append(n.MicrosoftTeams, - NotificationMicrosoftTeams{ - Name: nMap["name"], - Webhook: nMap["webhook"], - }) - case "NotificationWebhook": - n.Webhook = append(n.Webhook, - NotificationWebhook{ - Name: nMap["name"], - Webhook: nMap["webhook"], - ContentType: nMap["contentType"], - NotificationSeverityThreshold: nMap["notificationSeverityThreshold"], - }) - default: - return fmt.Errorf("unknown notification type: %v", nMap["__typename"]) - } - } - return nil -} diff --git a/services/logs2notifications/internal/schema/project.go b/services/logs2notifications/internal/schema/project.go deleted file mode 100644 index d806ac94a8..0000000000 --- a/services/logs2notifications/internal/schema/project.go +++ /dev/null @@ -1,8 +0,0 @@ -package schema - -// Project is based on the Lagoon API type. -type Project struct { - ID uint `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Notifications *Notifications `json:"notifications,omitempty"` -} diff --git a/services/logs2notifications/main.go b/services/logs2notifications/main.go index 12225d1f10..0ab9fe92a4 100644 --- a/services/logs2notifications/main.go +++ b/services/logs2notifications/main.go @@ -23,6 +23,7 @@ var ( startupConnectionAttempts int startupConnectionInterval int lagoonAPIHost string + lagoonAPIVersion string lagoonAppID string jwtTokenSigningKey string jwtAudience string @@ -72,6 +73,8 @@ func main() { "The duration between startup attempts.") flag.StringVar(&lagoonAPIHost, "lagoon-api-host", "http://localhost:3000", "The host for the lagoon api.") + flag.StringVar(&lagoonAPIVersion, "lagoon-api-version", "2.18.0", + "The version for the lagoon api.") flag.StringVar(&jwtTokenSigningKey, "jwt-token-signing-key", "super-secret-string", "The jwt signing token key or secret.") flag.StringVar(&jwtAudience, "jwt-audience", "api.dev", @@ -160,6 +163,7 @@ func main() { JWTAudience: jwtAudience, JWTSubject: jwtSubject, JWTIssuer: jwtIssuer, + Version: lagoonAPIVersion, } log.Println("logs2notifications running")