Skip to content

Commit

Permalink
Initial commit of major rewrite from github.com/ollytom/pover
Browse files Browse the repository at this point in the history
  • Loading branch information
ollytom committed Jun 15, 2021
0 parents commit e20d6ba
Show file tree
Hide file tree
Showing 12 changed files with 441 additions and 0 deletions.
13 changes: 13 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Copyright (c) 2021 Oliver Lowe <o@olowe.co>

Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This repository contains the Go pushover package,
the pover command-line utility,
and example Icinga2 configuration and scripts to send notifications from Icinga2 using pover.
10 changes: 10 additions & 0 deletions cmd/pover/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## Tests
Tests are run by building and running pover

First, build pover:

go build

Create a valid credentials file, then run test.sh

./test.sh
51 changes: 51 additions & 0 deletions cmd/pover/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package main

import (
"os"
"bufio"
"strings"
"fmt"
)

type config struct {
user string
token string
}

func configFromFile(name string) (config, error) {
f, err := os.Open(name)
if err != nil {
f.Close()
return config{}, err
}
defer f.Close()
sc := bufio.NewScanner(f)
i := 0
c := config{}
for sc.Scan() {
i++
s := sc.Text()
// skip comments
if strings.HasPrefix(s, "#") {
continue
}
slice := strings.Split(s, " ")
if len(slice) > 2 {
return config{}, fmt.Errorf("%s:%d: too many values", f.Name(), i)
}
switch slice[0] {
case "user":
c.user = slice[1]
case "token":
c.token = slice[1]
default:
return config{}, fmt.Errorf("%s:%d: unknown key %s", f.Name(), i, slice[0])
}
}
if c.user == "" {
return config{}, fmt.Errorf("no user")
} else if c.token == "" {
return config{}, fmt.Errorf("no token")
}
return c, nil
}
33 changes: 33 additions & 0 deletions cmd/pover/icinga2.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
object NotificationCommand "pushover" {
command = [ ConfigDir + "/scripts/pushover-icinga2.sh" ]
arguments = {
"-f" = "$pushover_config$"
}

env = {
HOSTADDRESS = "$address$"
HOSTDISPLAYNAME = "$host.display_name$"
LONGDATETIME = "$icinga.long_date_time$"
NOTIFICATIONAUTHORNAME = "$notification.author$"
NOTIFICATIONCOMMENT = "$notification.comment$"
NOTIFICATIONTYPE = "$notification.type$"
SERVICEDESC = "$service.name$"
SERVICEDISPLAYNAME = "$service.display_name$"
SERVICEOUTPUT = "$service.output$"
SERVICESTATE = "$service.state$"
}
}

object User "otl" {
display_name = "Oliver Lowe"
groups = [ "icingaadmins" ]
email = "otl@example.com"
vars.pushover_config = "/path/to/credentials/file"
}

apply Notification "olly-notification" to Service {
users = [ "otl" ]
command = "pushover"
/* Notify for every Service except for rdiff-backup services. */
assign where !match("rdiff-backup*", service.name)
}
52 changes: 52 additions & 0 deletions cmd/pover/pover.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
.TH POVER 1
.SH NAME
pover \- push a notification to Pushover
.SH SYNOPSIS
.B pover
[
.B -d
]
[
.B -f
.I file
]
.SH DESCRIPTION
.I Pover
pushes a notification to Pushover using text read from standard input as the message body.
The
.B -d
flag enables debugging output.
The
.B -f
flag sets credentials to be read from
.IR file .
.PP
Credentials must be present in a credentials file.
A credentials file is a newline-delimited text file.
Lines beginning with "#" are treated as comments and ignored.
The recognised keys in the credentials file are:
.TP
.B user
Pushover account User key.
.TP
.B token
API token.
.SH EXAMPLES
An example credentials file
.EX
# for pushover application "shell"
user abcd12345
token zxcvbnm98765
.EE
.PP
Send a message "Hello world",
reading credentials from a non-default path
.EX
echo "Hello world" | pover -f /tmp/creds
.EE
.SH FILES
.B $HOME/.config/pover
.TP
default credentials file
.SH SOURCE
.B github.com/ollytom/pover
64 changes: 64 additions & 0 deletions cmd/pover/pover.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package main

import (
"flag"
"fmt"
"os"
"io"
"io/ioutil"
"path/filepath"

"git.sr.ht/~otl/pushover"
)

const usage string = "usage: pover [-d] [-f file]"

var debug *bool
var configflag *string

func init() {
debug = flag.Bool("d", false, "debug")
configflag = flag.String("f", "", "path to configuration file")
flag.Parse()
}

func main() {
var configpath string
configpath = *configflag
if *configflag == "" {
s, err := os.UserConfigDir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
configpath = filepath.Join(s, "pover")
}
config, err := configFromFile(configpath)
if err != nil {
fmt.Fprintf(os.Stderr, "load configuration: %v\n", err)
os.Exit(1)
}

lr := io.LimitReader(os.Stdin, pushover.MaxMsgLength)
b, err := ioutil.ReadAll(lr)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
if len(b) == pushover.MaxMsgLength {
fmt.Fprintf(os.Stderr, "max message length (%d) reached\n", pushover.MaxMsgLength)
}
if *debug {
fmt.Fprint(os.Stderr, string(b))
}

msg := pushover.Message{
User: config.user,
Token: config.token,
Message: string(b),
}
if err := pushover.Push(msg); err != nil {
fmt.Fprintf(os.Stderr, "push message: %v\n", err)
os.Exit(1)
}
}
75 changes: 75 additions & 0 deletions cmd/pover/pover.mdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
.Dd $Mdocdate$
.Dt pover 1
.Os
.Sh NAME
.Nm pover
.Nd send a notification to Pushover
.Sh SYNOPSIS
.Nm
.Op Fl d
.Op Fl f Ar file
.Op Fl t Ar title
.Sh DESCRIPTION
.Nm
sends a notification to Pushover using text read from standard input as the message body.
.Pp
The options are:
.Bl -tag -width Ds
.It Fl d
Write debugging output to standard error.
.It Fl f Ar file
Sets configuration to be read from
.Ar file .
.It Fl t Ar title
Sets the message title to
.Ar title .
By default there is no title.
.El
.Pp
Credentials must be present in a configuration file.
A configuration file is a newline-delimited text file.
Lines beginning with
.Dq #
are treated as comments and ignored.
Configuration is a series of key-value pairs separated by whitespace,
one per line.
The recognised keys in the credentials file are:
.Bl -tag -width Ds
.It user
Pushover account user key.
.It token
API token.
.El
.Sh EXIT STATUS
.Ex
.Sh EXAMPLES
An example configuration file:
.Pp
.Bd -literal -offset indent -compact
# for pushover application "shell"
user abcd12345
token zxcvbnm98765
.Ed
.Pp
Send the current date as a notification:
.Pp
.Dl date | pover
.Pp
Send a hello world notification, reading configuration from
.Pa /etc/pover :
.Pp
.Dl echo 'hello world' | pover -f /etc/pover
.Sh FILES
The default configuration file location is as returned from Go's os.UserConfigDir().
.Bl -tag -width Ds
.It Pa $HOME/.config/pover
On Unix.
.It Pa $HOME/Library/Application\ Support/pover
On Darwin.
.It Pa %AppData%\\\pover
On Windows.
.It Pa $home/lib/pover
On Plan 9.
.El
.Sh SEE ALSO
.Lk "Pushover Message API documentation" https://pushover.net/api
18 changes: 18 additions & 0 deletions cmd/pover/pushover-icinga2.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#!/bin/sh

while getopt 'f:' flag
do
case $flag in
f) config=$OPTARG ;;
*) echo "unknown flag" $flag ;;
esac
done

pover -f $config <<EOF
$NOTIFICATIONTYPE
$SERVICEDISPLAYNAME - $SERVICEDESC - on $HOSTDISPLAYNAME ($HOSTADDRESS) is $SERVICESTATE
Time: $LONGDATETIME
Output: $SERVICEOUTPUT
Comments: [$NOTIFICATIONAUTHORNAME] $NOTIFICATIONCOMMENT
EOF
47 changes: 47 additions & 0 deletions cmd/pover/test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#!/bin/sh

if date -n | cmd/pover/pover
then
echo 'date sent ok'
else
echo 'date failed'
fi

if /bin/dd if=/dev/urandom of=/dev/stdout count=1024 | cmd/pover/pover
then
echo 'max length message ok'
else
echo 'max length message failed'
fi

# we expect pover to print a warning to standard error but send a truncated message anyway.
if /bin/dd if=/dev/urandom of=/dev/stdout count=2048 | cmd/pover/pover
then
echo 'too long message ok'
else
echo 'too long message failed'
fi

if ! echo | cmd/pover/pover
then
echo 'blank message ok'
else
echo 'blank message failed'
fi

if ! cmd/pover/pover -f /dev/null
then
echo "empty config ok"
else
echo "empty config failed"
fi

badconfig=`mktemp`
echo 'badconfig' > $badconfig
if ! cmd/pover/pover -f $badconfig
then
echo "bad config ok"
else
echo "bad config failed"
fi
rm $badconfig
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module git.sr.ht/~otl/pushover

go 1.16
Loading

0 comments on commit e20d6ba

Please sign in to comment.