Skip to content
This repository has been archived by the owner on Apr 8, 2022. It is now read-only.

add google chat handler #120

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmd/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,5 @@ func init() {
configCmd.AddCommand(resourceConfigCmd)
configCmd.AddCommand(flockConfigCmd)
configCmd.AddCommand(webhookConfigCmd)
configCmd.AddCommand(googleChatConfigCmd)
}
53 changes: 53 additions & 0 deletions cmd/googlechat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
Copyright 2018 Bitnami

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 cmd

import (
"github.com/spf13/cobra"
"github.com/bitnami-labs/kubewatch/config"
"github.com/Sirupsen/logrus"
)

// googleChatConfigCmd represents the googleChat subcommand
var googleChatConfigCmd = &cobra.Command{
Use: "googlechat FLAG",
Short: "specific googlechat configuration",
Long: `specific googlechat configuration`,
Run: func(cmd *cobra.Command, args []string){
conf, err := config.New()
if err != nil {
logrus.Fatal(err)
}

url, err := cmd.Flags().GetString("url")
if err == nil {
if len(url) > 0 {
conf.Handler.GoogleChat.Url = url
}
} else {
logrus.Fatal(err)
}

if err = conf.Write(); err != nil {
logrus.Fatal(err)
}
},
}

func init() {
googleChatConfigCmd.Flags().StringP("url", "u", "", "Specify googleChat url")
}
6 changes: 6 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ type Handler struct {
Mattermost Mattermost `json:"mattermost"`
Flock Flock `json:"flock"`
Webhook Webhook `json:"webhook"`
GoogleChat GoogleChat `json:"googlechat"`
}

// Resource contains resource configuration
Expand Down Expand Up @@ -91,6 +92,11 @@ type Webhook struct {
Url string `json:"url"`
}

// GoogleChat contains googlechat configuration
type GoogleChat struct {
Url string `json:"url"`
}

// New creates new config object
func New() (*Config, error) {
c := &Config{}
Expand Down
24 changes: 13 additions & 11 deletions examples/conf/kubewatch.conf.webhook.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,18 @@ handler:
flock:

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this file should be duplicated for google chat, not overwriting the webhook example.

url: ""
webhook:
url: "http://localhost:8080"
url: ""
googlechat:
url: "https://chat.googleapis.com/v1/spaces/AAAAosXkqiA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=soK8YP_o6jn_ShJi_QErkn95XVIWOc7wletgqtHUNnY%3Dhttps://chat.googleapis.com/v1/spaces/AAAAosXkqiA/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=soK8YP_o6jn_ShJi_QErkn95XVIWOc7wletgqtHUNnY%3D"
resource:
deployment: false
replicationcontroller: false
replicaset: false
daemonset: false
services: false
pod: false
job: false
persistentvolume: false
deployment: true
replicationcontroller: true
replicaset: true
daemonset: true
services: true
pod: true
job: true
persistentvolume: true
namespace: true
secret: false
ingress: false
secret: true
ingress: true
4 changes: 3 additions & 1 deletion pkg/client/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ package client

import (
"log"

"github.com/bitnami-labs/kubewatch/config"
"github.com/bitnami-labs/kubewatch/pkg/handlers"
"github.com/bitnami-labs/kubewatch/pkg/handlers/slack"
Expand All @@ -27,6 +26,7 @@ import (
"github.com/bitnami-labs/kubewatch/pkg/handlers/mattermost"
"github.com/bitnami-labs/kubewatch/pkg/handlers/flock"
"github.com/bitnami-labs/kubewatch/pkg/handlers/webhook"
"github.com/bitnami-labs/kubewatch/pkg/handlers/googlechat"
)

// Run runs the event loop processing with given handler
Expand All @@ -43,6 +43,8 @@ func Run(conf *config.Config) {
eventHandler = new(flock.Flock)
case len(conf.Handler.Webhook.Url) > 0:
eventHandler = new(webhook.Webhook)
case len(conf.Handler.GoogleChat.Url) > 0:
eventHandler = new(googlechat.GoogleChat)
default:
eventHandler = new(handlers.Default)
}
Expand Down
173 changes: 173 additions & 0 deletions pkg/handlers/googlechat/googlechat.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,173 @@
/*
Copyright 2016 Skippbox, Ltd.

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 googlechat

import (
"fmt"
"log"
"os"

"bytes"
"encoding/json"
"net/http"
"time"

"github.com/bitnami-labs/kubewatch/config"
kbEvent "github.com/bitnami-labs/kubewatch/pkg/event"
)

var GoogleChatErrorMsg = `
%s

You need to set GoogleChat url
using "--url/-u" or using environment variables:

export KW_GOOGLECHAT_URL=googleChat url

Command line flags will override environment variables

`

// GoogleChat handler implements handler.Handler interface,
// Notify event to GoogleChat channel
type GoogleChat struct {
Url string
}

type GoogleChatMessage struct {
Text string `json:"text"`
Cards []GoogleCard `json:"cards"`
}

type GoogleCard struct{
Header GoogleCardHeader `json:"header"`
Sections []GoogleCardSection `json:"sections"`
}

type GoogleCardHeader struct{
Title string `json:"title"`
}

type GoogleCardSection struct{
Header string `json:"header"`
Widgets []GoogleCardWidgetParagraph `json:"widgets"`
}

type GoogleCardWidgetParagraph struct{
TextParagraph GoogleCardWidgetText `json:"textParagraph"`
}

type GoogleCardWidgetText struct{
Text string `json:"text"`
}

// Init prepares GoogleChat configuration
func (m *GoogleChat) Init(c *config.Config) error {
url := c.Handler.GoogleChat.Url

if url == "" {
url = os.Getenv("KW_GOOGLECHAT_URL")
}

m.Url = url


log.Printf("Google chat initialized")
return checkMissingGChatVars(m)
}

func (m *GoogleChat) ObjectCreated(obj interface{}) {
notifyGoogleChat(m, obj, "created")
}

func (m *GoogleChat) ObjectDeleted(obj interface{}) {
notifyGoogleChat(m, obj, "deleted")
}

func (m *GoogleChat) ObjectUpdated(oldObj, newObj interface{}) {
notifyGoogleChat(m, newObj, "updated")
}


func notifyGoogleChat(m *GoogleChat, obj interface{}, action string) {
e := kbEvent.New(obj, action)

chatMessage := prepareChatMessage(e)

err := postMessage(m.Url, chatMessage)
if err != nil {
log.Printf("%s\n", err)
return
}
res2B, _ := json.Marshal(chatMessage)
fmt.Println(string(res2B))

log.Printf("Message successfully sent to %s at %s ", m.Url, time.Now())
}

func checkMissingGChatVars(s *GoogleChat) error {
if s.Url == "" {
return fmt.Errorf(GoogleChatErrorMsg, "Missing GoogleChat url")
}

return nil
}

func prepareChatMessage(e kbEvent.Event) *GoogleChatMessage {
return &GoogleChatMessage{
Text: "",
Cards: []GoogleCard{
{
Header: GoogleCardHeader{
Title: "Kubewatch Notifications",
},
Sections: []GoogleCardSection{
{
Header: "Message",
Widgets: []GoogleCardWidgetParagraph{
{
TextParagraph: GoogleCardWidgetText{
Text: e.Message(),
},
},
},
},
},
},
},
}
}

func postMessage(url string, chatMessage *GoogleChatMessage) error {
message, err := json.Marshal(chatMessage)
if err != nil {
return err
}
req, err := http.NewRequest("POST", url, bytes.NewBuffer(message))
if err != nil {
return err
}
req.Header.Add("Content-Type", "application/json")

client := &http.Client{}
_, err = client.Do(req)
if err != nil {
return err
}

return nil
}
46 changes: 46 additions & 0 deletions pkg/handlers/googlechat/googlechat_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
Copyright 2016 Skippbox, Ltd.

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 googlechat

import (
"fmt"
"reflect"
"testing"

"github.com/bitnami-labs/kubewatch/config"
)

func TestGoogleChatInit(t *testing.T) {
s := &GoogleChat{}
expectedError := fmt.Errorf(GoogleChatErrorMsg, "Missing GoogleChat url")

var Tests = []struct {
googleChat config.GoogleChat
err error
}{
{config.GoogleChat{Url: "foo"}, nil},
{config.GoogleChat{}, expectedError},
}

for _, tt := range Tests {
c := &config.Config{}
c.Handler.GoogleChat = tt.googleChat
if err := s.Init(c); !reflect.DeepEqual(err, tt.err) {
t.Fatalf("Init(): %v", err)
}
}
}
2 changes: 2 additions & 0 deletions pkg/handlers/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/bitnami-labs/kubewatch/pkg/handlers/mattermost"
"github.com/bitnami-labs/kubewatch/pkg/handlers/flock"
"github.com/bitnami-labs/kubewatch/pkg/handlers/webhook"
"github.com/bitnami-labs/kubewatch/pkg/handlers/googlechat"
)

// Handler is implemented by any handler.
Expand All @@ -42,6 +43,7 @@ var Map = map[string]interface{}{
"mattermost": &mattermost.Mattermost{},
"flock": &flock.Flock{},
"webhook": &webhook.Webhook{},
"googlechat": &googlechat.GoogleChat{},
}

// Default handler implements Handler interface,
Expand Down
21 changes: 21 additions & 0 deletions sample.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"cards": [
{
"header": {
"title": "Kubewatch Notifications"
},
"sections": [
{
"header": "Message",
"widgets": [
{
"textParagraph": {
"text": "some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message some message "
}
}
]
}
]
}
]
}
Loading