Skip to content

Commit

Permalink
Merge branch 'messagebird:master' into add-sfr-dmc-provider
Browse files Browse the repository at this point in the history
  • Loading branch information
thiperson committed Apr 20, 2022
2 parents 20b0280 + 2881390 commit fce4b63
Show file tree
Hide file tree
Showing 39 changed files with 691 additions and 331 deletions.
24 changes: 24 additions & 0 deletions .github/workflows/go.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Go

on:
push:
branches: [ master main ]
pull_request:

jobs:

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2

- name: Set up Go
uses: actions/setup-go@v2
with:
go-version: 1.18

- name: Build
run: go build -v ./...

- name: Test
run: go test -v ./...
44 changes: 44 additions & 0 deletions .github/workflows/golangci-lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
name: golangci-lint
on:
push:
tags:
- v*
branches:
- master
- main
pull_request:
permissions:
contents: read
# Optional: allow read access to pull request. Use with `only-new-issues` option.
# pull-requests: read
jobs:
golangci:
name: lint
runs-on: ubuntu-latest
steps:
- uses: actions/setup-go@v3
- uses: actions/checkout@v3
- name: golangci-lint
uses: golangci/golangci-lint-action@v2
with:
# Optional: version of golangci-lint to use in form of v1.2 or v1.2.3 or `latest` to use the latest version
version: latest

# Optional: working directory, useful for monorepos
# working-directory: somedir

# Optional: golangci-lint command line arguments.
# args: --issues-exit-code=0

# Optional: show only new issues if it's a pull request. The default value is `false`.
# only-new-issues: true

# Optional: if set to true then the all caching functionality will be complete disabled,
# takes precedence over all other caching options.
# skip-cache: true

# Optional: if set to true then the action don't cache or restore ~/go/pkg.
# skip-pkg-cache: true

# Optional: if set to true then the action don't cache or restore ~/.cache/go-build.
# skip-build-cache: true
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ gin-bin
bin
config.yaml
.idea
.vscode
89 changes: 89 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
run:
modules-download-mode: readonly
issues-exit-code: 0

linters-settings:
exhaustive:
default-signifies-exhaustive: false
gci:
sections:
- standard
- default
- prefix(github.com/messagebird/sachet)
goconst:
min-occurrences: 5
ignore-tests: true
godot:
scope: toplevel
exclude:
- go-sumtype:decl
- check interfaces
capital: true
godox:
keywords:
- BUG
- FIXME
- HACK
goimports:
local-prefixes: github.com/messagebird/sachet
gosimple:
go: "1.18"
checks: ["all"]
lll:
line-length: 130
tab-width: 4
nolintlint:
allow-unused: false
allow-leading-space: false
allow-no-explanation: []
require-explanation: true
require-specific: true
staticcheck:
go: "1.18"
checks: ["all"]
stylecheck:
go: "1.18"
checks: ["all"]
dot-import-whitelist: []
initialisms: []
http-status-code-whitelist: []
unparam:
check-exported: true
unused:
go: "1.18"
whitespace:
multi-if: false
multi-func: false
tagliatelle:

linters:
enable-all: true
disable:
# TODO: enable one by one
- ireturn
- forbidigo
- containedctx
- tagliatelle
- cyclop
- errcheck
- exhaustivestruct
- forcetypeassert
- funlen
- gochecknoglobals
- gochecknoinits
- goerr113
- gomnd
- gosec
- revive
- varnamelen
- wrapcheck
- noctx
- staticcheck
- stylecheck
- golint
- interfacer
- maligned
- nlreturn
- scopelint
- testpackage
- wsl
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
FROM golang:1.17 AS builder
FROM golang:1.18 AS builder

WORKDIR /build

COPY . .

RUN GO111MODULE=on CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -mod vendor -o sachet github.com/messagebird/sachet/cmd/sachet

FROM alpine
FROM alpine:3.15

COPY --from=builder /build/sachet /usr/local/bin
COPY --chown=nobody examples/config.yaml /etc/sachet/config.yaml
Expand Down
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# Sachet

[![Build Status](https://travis-ci.org/messagebird/sachet.svg?branch=master)](https://travis-ci.org/messagebird/sachet)

Sachet (or सचेत) is Hindi for conscious. Sachet is an SMS alerting tool for the [Prometheus Alertmanager](https://github.com/prometheus/alertmanager).

## The problem
Expand Down
7 changes: 3 additions & 4 deletions cmd/sachet/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ package main
import (
"io/ioutil"

"github.com/messagebird/sachet/provider/esendex"
"github.com/prometheus/alertmanager/template"
"gopkg.in/yaml.v2"

"github.com/messagebird/sachet/provider/aliyun"
"github.com/messagebird/sachet/provider/aspsms"
"github.com/messagebird/sachet/provider/cm"
"github.com/messagebird/sachet/provider/esendex"
"github.com/messagebird/sachet/provider/exotel"
"github.com/messagebird/sachet/provider/freemobile"
"github.com/messagebird/sachet/provider/ghasedak"
Expand All @@ -32,9 +34,6 @@ import (
"github.com/messagebird/sachet/provider/textmagic"
"github.com/messagebird/sachet/provider/turbosms"
"github.com/messagebird/sachet/provider/twilio"

"github.com/prometheus/alertmanager/template"
"gopkg.in/yaml.v2"
)

type ReceiverConf struct {
Expand Down
110 changes: 110 additions & 0 deletions cmd/sachet/handlers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package main

import (
"encoding/json"
"fmt"
"log"
"net/http"
"sort"
"strings"

"github.com/prometheus/alertmanager/template"

"github.com/messagebird/sachet"
)

type handlers struct{}

func newAlertText(data template.Data) string {
if len(data.Alerts) > 1 {
labelAlerts := map[string]template.Alerts{
"Firing": data.Alerts.Firing(),
"Resolved": data.Alerts.Resolved(),
}
text := ""
for label, alerts := range labelAlerts {
if len(alerts) > 0 {
text += label + ": \n"
for _, alert := range alerts {
text += alert.Labels["alertname"] + " @" + alert.Labels["instance"]
if len(alert.Labels["exported_instance"]) > 0 {
text += " (" + alert.Labels["exported_instance"] + ")"
}
text += "\n"
}
}
}
return text
}

if len(data.Alerts) == 1 {
alert := data.Alerts[0]
tuples := []string{}
for k, v := range alert.Labels {
tuples = append(tuples, k+"= "+v)
}
sort.Strings(tuples)
return strings.ToUpper(data.Status) + " \n" + strings.Join(tuples, "\n")
}

return "Alert \n" + strings.Join(data.CommonLabels.Values(), " | ")
}

func (h handlers) Alert(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()

// https://godoc.org/github.com/prometheus/alertmanager/template#Data
data := template.Data{}
if err := json.NewDecoder(r.Body).Decode(&data); err != nil {
errorHandler(w, http.StatusBadRequest, err, "?")
return
}

receiverConf := receiverConfByReceiver(data.Receiver)
if receiverConf == nil {
errorHandler(w, http.StatusBadRequest, fmt.Errorf("Receiver missing: %s", data.Receiver), "?")
return
}
provider, err := providerByName(receiverConf.Provider)
if err != nil {
errorHandler(w, http.StatusInternalServerError, err, receiverConf.Provider)
return
}

var text string
if receiverConf.Text != "" {
text, err = tmpl.ExecuteTextString(receiverConf.Text, data)
if err != nil {
errorHandler(w, http.StatusInternalServerError, err, receiverConf.Provider)
return
}
} else {
text = newAlertText(data)
}

message := sachet.Message{
To: receiverConf.To,
From: receiverConf.From,
Type: receiverConf.Type,
Text: text,
}

if err = provider.Send(message); err != nil {
errorHandler(w, http.StatusBadRequest, err, receiverConf.Provider)
return
}

requestTotal.WithLabelValues("200", receiverConf.Provider).Inc()
}

func (h handlers) Reload(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
if r.Method == http.MethodPost {
log.Println("Loading configuration file", *configFile)
if err := LoadConfig(*configFile); err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
} else {
http.Error(w, "Invalid request method.", http.StatusMethodNotAllowed)
}
}
62 changes: 62 additions & 0 deletions cmd/sachet/handlers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
package main

import (
"testing"

"github.com/prometheus/alertmanager/template"
"github.com/stretchr/testify/assert"
)

func Test_newAlertText(t *testing.T) {
t.Parallel()

cases := []struct {
name string
data template.Data
exp string
}{
{
name: "empty",
data: template.Data{},
exp: "Alert \n",
},
{
name: "empty alerts",
data: template.Data{
Alerts: template.Alerts{
template.Alert{},
},
},
exp: " \n",
},
{
name: "alert labels",
data: template.Data{
Alerts: template.Alerts{
template.Alert{
Labels: map[string]string{
"alertname": "a",
"instance": "a",
"exported_instance": "a",
},
},
},
},
exp: " \nalertname= a\nexported_instance= a\ninstance= a",
},
{
name: "common labels",
data: template.Data{
CommonLabels: template.KV{
"a": "a",
"b": "b",
"c": "c",
},
},
exp: "Alert \na | b | c",
},
}
for _, tc := range cases {
assert.Equal(t, tc.exp, newAlertText(tc.data), tc.name)
}
}
Loading

0 comments on commit fce4b63

Please sign in to comment.