Switched to purer libraries
This commit is contained in:
parent
8fa8bb4c3a
commit
9496947f01
21 changed files with 390 additions and 316 deletions
33
area.go
33
area.go
|
|
@ -2,10 +2,11 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"database/sql"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
@ -19,7 +20,7 @@ type Area struct {
|
||||||
|
|
||||||
func AreaRetrieve() (areas []Area, err error) { // {{{
|
func AreaRetrieve() (areas []Area, err error) { // {{{
|
||||||
areas = []Area{}
|
areas = []Area{}
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(context.Background(), `
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_agg(jsonsections)
|
jsonb_agg(jsonsections)
|
||||||
FROM (
|
FROM (
|
||||||
|
|
@ -59,21 +60,23 @@ func AreaRetrieve() (areas []Area, err error) { // {{{
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func AreaCreate(name string) (err error) { // {{{
|
func AreaCreate(name string) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`INSERT INTO area(name) VALUES($1)`, name)
|
_, err = db.Exec(context.Background(), `INSERT INTO area(name) VALUES($1)`, name)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func AreaRename(id int, name string) (err error) { // {{{
|
func AreaRename(id int, name string) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE area SET name=$2 WHERE id=$1`, id, name)
|
_, err = db.Exec(context.Background(), `UPDATE area SET name=$2 WHERE id=$1`, id, name)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func AreaDelete(id int) (err error) { // {{{
|
func AreaDelete(id int) (err error) { // {{{
|
||||||
var trx *sql.Tx
|
ctx := context.Background()
|
||||||
trx, err = service.Db.Conn.Begin()
|
|
||||||
|
var trx pgx.Tx
|
||||||
|
trx, err = db.Begin(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(id)
|
err = werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = trx.Exec(`
|
_, err = trx.Exec(context.Background(), `
|
||||||
DELETE
|
DELETE
|
||||||
FROM trigger t
|
FROM trigger t
|
||||||
USING section s
|
USING section s
|
||||||
|
|
@ -84,34 +87,34 @@ func AreaDelete(id int) (err error) { // {{{
|
||||||
id,
|
id,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err2 := trx.Rollback()
|
err2 := trx.Rollback(ctx)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return werr.Wrap(err2).WithData(err)
|
return werr.Wrap(err2).WithData(err)
|
||||||
}
|
}
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = trx.Exec(`DELETE FROM public.section WHERE area_id = $1`, id)
|
_, err = trx.Exec(ctx, `DELETE FROM public.section WHERE area_id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err2 := trx.Rollback()
|
err2 := trx.Rollback(ctx)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return werr.Wrap(err2).WithData(err)
|
return werr.Wrap(err2).WithData(err)
|
||||||
}
|
}
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = trx.Exec(`DELETE FROM public.area WHERE id = $1`, id)
|
_, err = trx.Exec(ctx, `DELETE FROM public.area WHERE id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err2 := trx.Rollback()
|
err2 := trx.Rollback(ctx)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return werr.Wrap(err2).WithData(err)
|
return werr.Wrap(err2).WithData(err)
|
||||||
}
|
}
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = trx.Commit()
|
err = trx.Commit(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err2 := trx.Rollback()
|
err2 := trx.Rollback(ctx)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return werr.Wrap(err2).WithData(err)
|
return werr.Wrap(err2).WithData(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
config.go
40
config.go
|
|
@ -1,6 +1,42 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
type FileConfiguration struct {
|
import (
|
||||||
LogFile string
|
// Standard
|
||||||
|
"encoding/json"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type DatabaseDetails struct {
|
||||||
|
Host string
|
||||||
|
Port int
|
||||||
|
Name string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
type Config struct {
|
||||||
|
Network struct {
|
||||||
|
Address string
|
||||||
|
Port int
|
||||||
|
}
|
||||||
|
|
||||||
|
Websocket struct {
|
||||||
|
Domains []string
|
||||||
|
}
|
||||||
|
|
||||||
|
Database DatabaseDetails
|
||||||
|
|
||||||
NodataInterval int `json:"nodata_interval"` // in seconds
|
NodataInterval int `json:"nodata_interval"` // in seconds
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func initConfig(fname string) (cfg Config, err error) {// {{{
|
||||||
|
var data []byte
|
||||||
|
data, err = os.ReadFile(fname)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err = json.Unmarshal(data, &cfg)
|
||||||
|
return
|
||||||
|
}// }}}
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,11 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"database/sql"
|
"context"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -19,8 +20,8 @@ var smonConfig Configuration
|
||||||
func SmonConfigInit() (cfg Configuration, err error) {
|
func SmonConfigInit() (cfg Configuration, err error) {
|
||||||
cfg.Settings = make(map[string]string, 8)
|
cfg.Settings = make(map[string]string, 8)
|
||||||
|
|
||||||
var rows *sql.Rows
|
var rows pgx.Rows
|
||||||
rows, err = service.Db.Conn.Query(`SELECT * FROM public.configuration`)
|
rows, err = db.Query(context.Background(), `SELECT * FROM public.configuration`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err)
|
err = werr.Wrap(err)
|
||||||
return
|
return
|
||||||
|
|
@ -63,7 +64,7 @@ func (cfg *Configuration) Timezone() *time.Location {
|
||||||
|
|
||||||
func (cfg *Configuration) SetTheme(theme string) (err error) {
|
func (cfg *Configuration) SetTheme(theme string) (err error) {
|
||||||
cfg.Settings["THEME"] = theme
|
cfg.Settings["THEME"] = theme
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE public.configuration SET value=$1 WHERE setting='THEME'`, theme)
|
_, err = db.Exec(context.Background(), `UPDATE public.configuration SET value=$1 WHERE setting='THEME'`, theme)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -74,7 +75,7 @@ func (cfg *Configuration) SetTimezone(tz string) (err error) {
|
||||||
return werr.Wrap(err).WithData(tz)
|
return werr.Wrap(err).WithData(tz)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE public.configuration SET value=$1 WHERE setting='TIMEZONE'`, tz)
|
_, err = db.Exec(context.Background(), `UPDATE public.configuration SET value=$1 WHERE setting='TIMEZONE'`, tz)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return werr.Wrap(err).WithData(tz)
|
return werr.Wrap(err).WithData(tz)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
97
datapoint.go
97
datapoint.go
|
|
@ -2,10 +2,11 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
@ -73,7 +74,8 @@ func (dp Datapoint) Update() (err error) { // {{{
|
||||||
}
|
}
|
||||||
|
|
||||||
if dp.ID == 0 {
|
if dp.ID == 0 {
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`INSERT INTO datapoint("group", name, datatype, nodata_problem_seconds, comment) VALUES($1, $2, $3, $4, $5)`,
|
`INSERT INTO datapoint("group", name, datatype, nodata_problem_seconds, comment) VALUES($1, $2, $3, $4, $5)`,
|
||||||
dp.Group,
|
dp.Group,
|
||||||
name,
|
name,
|
||||||
|
|
@ -85,7 +87,8 @@ func (dp Datapoint) Update() (err error) { // {{{
|
||||||
/* Keep nodata_is_problem as is unless the nodata_problem_seconds is changed.
|
/* Keep nodata_is_problem as is unless the nodata_problem_seconds is changed.
|
||||||
* Otherwise unnecessary nodata problems could be notified when updating unrelated
|
* Otherwise unnecessary nodata problems could be notified when updating unrelated
|
||||||
* datapoint properties. */
|
* datapoint properties. */
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
UPDATE datapoint
|
UPDATE datapoint
|
||||||
SET
|
SET
|
||||||
|
|
@ -125,7 +128,7 @@ func DatapointAdd[T any](name string, value T) (err error) { // {{{
|
||||||
value any
|
value any
|
||||||
}
|
}
|
||||||
|
|
||||||
row := service.Db.Conn.QueryRow(`SELECT id, datatype FROM datapoint WHERE name=$1`, name)
|
row := db.QueryRow(context.Background(), `SELECT id, datatype FROM datapoint WHERE name=$1`, name)
|
||||||
var dpID int
|
var dpID int
|
||||||
var dpType DatapointType
|
var dpType DatapointType
|
||||||
|
|
||||||
|
|
@ -140,9 +143,9 @@ func DatapointAdd[T any](name string, value T) (err error) { // {{{
|
||||||
|
|
||||||
switch dpType {
|
switch dpType {
|
||||||
case INT:
|
case INT:
|
||||||
_, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_int) VALUES($1, $2)`, dpID, value)
|
_, err = db.Exec(context.Background(), `INSERT INTO datapoint_value(datapoint_id, value_int) VALUES($1, $2)`, dpID, value)
|
||||||
case STRING:
|
case STRING:
|
||||||
_, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_string) VALUES($1, $2)`, dpID, value)
|
_, err = db.Exec(context.Background(), `INSERT INTO datapoint_value(datapoint_id, value_string) VALUES($1, $2)`, dpID, value)
|
||||||
case DATETIME:
|
case DATETIME:
|
||||||
// Time value is required to be a RFC 3339 formatted time string
|
// Time value is required to be a RFC 3339 formatted time string
|
||||||
var t time.Time
|
var t time.Time
|
||||||
|
|
@ -155,7 +158,7 @@ func DatapointAdd[T any](name string, value T) (err error) { // {{{
|
||||||
return werr.Wrap(err).WithData(dpRequest{dpID, value}).Log()
|
return werr.Wrap(err).WithData(dpRequest{dpID, value}).Log()
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = service.Db.Conn.Exec(`INSERT INTO datapoint_value(datapoint_id, value_datetime) VALUES($1, $2)`, dpID, t)
|
_, err = db.Exec(context.Background(), `INSERT INTO datapoint_value(datapoint_id, value_datetime) VALUES($1, $2)`, dpID, t)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(dpRequest{dpID, value})
|
err = werr.Wrap(err).WithData(dpRequest{dpID, value})
|
||||||
|
|
@ -167,8 +170,10 @@ func DatapointAdd[T any](name string, value T) (err error) { // {{{
|
||||||
|
|
||||||
func DatapointsRetrieve() (dps []Datapoint, err error) { // {{{
|
func DatapointsRetrieve() (dps []Datapoint, err error) { // {{{
|
||||||
dps = []Datapoint{}
|
dps = []Datapoint{}
|
||||||
var rows *sqlx.Rows
|
var rows pgx.Rows
|
||||||
rows, err = service.Db.Conn.Queryx(`
|
rows, err = db.Query(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
SELECT
|
SELECT
|
||||||
id, name, datatype, last_value, "group", comment, nodata_problem_seconds,
|
id, name, datatype, last_value, "group", comment, nodata_problem_seconds,
|
||||||
last_value_id AS v_id,
|
last_value_id AS v_id,
|
||||||
|
|
@ -205,11 +210,12 @@ func DatapointsRetrieve() (dps []Datapoint, err error) { // {{{
|
||||||
ValueDateTime sql.NullTime `db:"value_datetime"`
|
ValueDateTime sql.NullTime `db:"value_datetime"`
|
||||||
}
|
}
|
||||||
|
|
||||||
for rows.Next() {
|
dps, err = pgx.CollectRows(
|
||||||
dp := Datapoint{}
|
rows,
|
||||||
dpv := DatapointValue{}
|
func(row pgx.CollectableRow) (dp Datapoint, err error) {
|
||||||
res := DbRes{}
|
var dpv DatapointValue
|
||||||
err = rows.StructScan(&res)
|
var res DbRes
|
||||||
|
res, err = pgx.RowToStructByName[DbRes](row)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err)
|
err = werr.Wrap(err)
|
||||||
return
|
return
|
||||||
|
|
@ -233,9 +239,14 @@ func DatapointsRetrieve() (dps []Datapoint, err error) { // {{{
|
||||||
|
|
||||||
dp.LastDatapointValue = dpv
|
dp.LastDatapointValue = dpv
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
})
|
||||||
|
|
||||||
dps = append(dps, dp)
|
if err != nil {
|
||||||
|
err = werr.Wrap(err)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
||||||
|
|
@ -250,8 +261,12 @@ func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
||||||
param = name
|
param = name
|
||||||
}
|
}
|
||||||
|
|
||||||
row := service.Db.Conn.QueryRowx(query, param)
|
rows, _ := db.Query(context.Background(), query, param)
|
||||||
err = row.StructScan(&dp)
|
dp, err = pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Datapoint])
|
||||||
|
if err != nil {
|
||||||
|
err = werr.Wrap(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
dp = Datapoint{
|
dp = Datapoint{
|
||||||
|
|
@ -266,7 +281,9 @@ func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
row = service.Db.Conn.QueryRowx(`
|
rows, _ = db.Query(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
SELECT *
|
SELECT *
|
||||||
FROM datapoint_value
|
FROM datapoint_value
|
||||||
WHERE datapoint_id = $1
|
WHERE datapoint_id = $1
|
||||||
|
|
@ -275,7 +292,7 @@ func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
||||||
`,
|
`,
|
||||||
dp.ID,
|
dp.ID,
|
||||||
)
|
)
|
||||||
err = row.StructScan(&dp.LastDatapointValue)
|
dp, err = pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Datapoint])
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
err = nil
|
err = nil
|
||||||
return
|
return
|
||||||
|
|
@ -290,50 +307,41 @@ func DatapointRetrieve(id int, name string) (dp Datapoint, err error) { // {{{
|
||||||
} // }}}
|
} // }}}
|
||||||
func DatapointDelete(id int) (err error) { // {{{
|
func DatapointDelete(id int) (err error) { // {{{
|
||||||
var dpName string
|
var dpName string
|
||||||
row := service.Db.Conn.QueryRow(`SELECT name FROM public.datapoint WHERE id = $1`, id)
|
err = db.QueryRow(context.Background(), `SELECT name FROM public.datapoint WHERE id = $1`, id).Scan(&dpName)
|
||||||
err = row.Scan(&dpName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(id)
|
err = werr.Wrap(err).WithData(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var rows *sql.Rows
|
|
||||||
rows, err = service.Db.Conn.Query(`SELECT name FROM public.trigger WHERE datapoints ? $1`, dpName)
|
|
||||||
if err != nil {
|
|
||||||
err = werr.Wrap(err).WithData(dpName)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var triggerNames []string
|
var triggerNames []string
|
||||||
var name string
|
rows, _ := db.Query(context.Background(), `SELECT name FROM public.trigger WHERE datapoints ? $1`, dpName)
|
||||||
for rows.Next() {
|
triggerNames, err = pgx.CollectRows(rows, pgx.RowTo[string])
|
||||||
err = rows.Scan(&name)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err)
|
err = werr.Wrap(err).WithData(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
triggerNames = append(triggerNames, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(triggerNames) > 0 {
|
if len(triggerNames) > 0 {
|
||||||
return werr.New("Datapoint '%s' used in the following triggers: %s", dpName, strings.Join(triggerNames, ", "))
|
return werr.New("Datapoint '%s' used in the following triggers: %s", dpName, strings.Join(triggerNames, ", "))
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = service.Db.Conn.Exec(`DELETE FROM datapoint WHERE id=$1`, id)
|
_, err = db.Exec(context.Background(), `DELETE FROM datapoint WHERE id=$1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(id)
|
err = werr.Wrap(err).WithData(id)
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func DatapointValues(id int, from, to time.Time) (values []DatapointValue, err error) { // {{{
|
func DatapointValues(id int, from, to time.Time) (values []DatapointValue, err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`SELECT set_config('timezone', $1, false)`, smonConfig.Timezone().String())
|
_, err = db.Exec(context.Background(), `SELECT set_config('timezone', $1, false)`, smonConfig.Timezone().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(smonConfig.Timezone().String())
|
err = werr.Wrap(err).WithData(smonConfig.Timezone().String())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
rows, err := service.Db.Conn.Queryx(
|
rows, _ := db.Query(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
|
|
@ -354,20 +362,11 @@ func DatapointValues(id int, from, to time.Time) (values []DatapointValue, err e
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
)
|
)
|
||||||
|
values, err = pgx.CollectRows(rows, pgx.RowToStructByName[DatapointValue])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(id)
|
err = werr.Wrap(err).WithData(id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
dpv := DatapointValue{}
|
|
||||||
err = rows.StructScan(&dpv)
|
|
||||||
if err != nil {
|
|
||||||
err = werr.Wrap(err).WithData(id)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
values = append(values, dpv)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
|
||||||
19
go.mod
19
go.mod
|
|
@ -1,19 +1,18 @@
|
||||||
module smon
|
module smon
|
||||||
|
|
||||||
go 1.22.0
|
go 1.25.0
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.gibonuddevalla.se/go/webservice v0.2.16
|
git.ahall.se/go/html_template v0.1.1
|
||||||
git.gibonuddevalla.se/go/wrappederror v0.3.4
|
git.ahall.se/go/wrappederror v1.0.0
|
||||||
github.com/expr-lang/expr v1.16.5
|
github.com/expr-lang/expr v1.16.5
|
||||||
github.com/jmoiron/sqlx v1.3.5
|
github.com/jackc/pgx/v5 v5.9.1
|
||||||
github.com/lib/pq v1.10.9
|
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.gibonuddevalla.se/go/dbschema v1.3.0 // indirect
|
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||||
github.com/google/uuid v1.5.0 // indirect
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||||
github.com/gorilla/websocket v1.5.1 // indirect
|
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||||
golang.org/x/net v0.17.0 // indirect
|
golang.org/x/sync v0.17.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
golang.org/x/text v0.29.0 // indirect
|
||||||
)
|
)
|
||||||
|
|
|
||||||
47
go.sum
47
go.sum
|
|
@ -1,33 +1,32 @@
|
||||||
git.gibonuddevalla.se/go/dbschema v1.3.0 h1:HzFMR29tWfy/ibIjltTbIMI4inVktj/rh8bESALibgM=
|
git.ahall.se/go/html_template v0.1.1 h1:GrSNvs/ZAWKkuxQ4OEOTqHBTtYnx8C88JBxVERDxv18=
|
||||||
git.gibonuddevalla.se/go/dbschema v1.3.0/go.mod h1:BNw3q/574nXbGoeWyK+tLhRfggVkw2j2aXZzrBKC3ig=
|
git.ahall.se/go/html_template v0.1.1/go.mod h1:bBpM0K1HXZadhZg4VeT39IgyGwwhWoZet99nw8QeZKg=
|
||||||
git.gibonuddevalla.se/go/webservice v0.2.15 h1:ECe63fRDSrg3RJcgYV2pG+WsAQLVG8wvfHennz7aHsY=
|
git.ahall.se/go/wrappederror v1.0.0 h1:TxiAUTZUnmkVpaPKQjhTGSFsvc0qLkULsIj4Rwh4UsY=
|
||||||
git.gibonuddevalla.se/go/webservice v0.2.15/go.mod h1:3uBS6nLbK9qbuGzDls8MZD5Xr9ORY1Srbj6v06BIhws=
|
git.ahall.se/go/wrappederror v1.0.0/go.mod h1:trMBDaw5SdUrsZu3MCh1q+INsrmB4T9L+3DuV7JM+c8=
|
||||||
git.gibonuddevalla.se/go/wrappederror v0.3.4 h1:dcKp9/+QrZSO3S4fVnq7yG2p7DUZVmlztBAb/OzoZNY=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
git.gibonuddevalla.se/go/wrappederror v0.3.4/go.mod h1:j4w320Hk1wvhOPjUaK4GgLvmtnjUUM5yVu6JFO1OCSc=
|
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/expr-lang/expr v1.16.5 h1:m2hvtguFeVaVNTHj8L7BoAyt7O0PAIBaSVbjdHgRXMs=
|
github.com/expr-lang/expr v1.16.5 h1:m2hvtguFeVaVNTHj8L7BoAyt7O0PAIBaSVbjdHgRXMs=
|
||||||
github.com/expr-lang/expr v1.16.5/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
github.com/expr-lang/expr v1.16.5/go.mod h1:uCkhfG+x7fcZ5A5sXHKuQ07jGZRl6J0FCAaf2k4PtVQ=
|
||||||
github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE=
|
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||||
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
|
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||||
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||||
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/jackc/pgx/v5 v5.9.1 h1:uwrxJXBnx76nyISkhr33kQLlUqjv7et7b9FjCen/tdc=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/jackc/pgx/v5 v5.9.1/go.mod h1:mal1tBGAFfLHvZzaYh77YS/eC6IX9OWbRV1QIIM0Jn4=
|
||||||
github.com/jmoiron/sqlx v1.3.5 h1:vFFPA71p1o5gAeqtEAwLU4dnX2napprKtHr7PYIcN3g=
|
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||||
github.com/jmoiron/sqlx v1.3.5/go.mod h1:nRVWtLre0KfCLJvgxzCsLVMogSvQ1zNJtpYr2Ccp0mQ=
|
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||||
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
|
||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
|
||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.6 h1:dNPt6NO46WmLVt2DLNpwczCmdV5boIZ6g/tlDrlRUbg=
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
|
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||||
|
golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug=
|
||||||
|
golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI=
|
||||||
|
golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk=
|
||||||
|
golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"regexp"
|
"regexp"
|
||||||
|
|
|
||||||
197
main.go
197
main.go
|
|
@ -2,14 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
ws "git.gibonuddevalla.se/go/webservice"
|
"git.ahall.se/go/html_template"
|
||||||
"git.gibonuddevalla.se/go/webservice/session"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
"smon/notification"
|
"smon/notification"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"embed"
|
"embed"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
|
|
@ -36,12 +36,11 @@ var (
|
||||||
flagConfigFile string
|
flagConfigFile string
|
||||||
flagDev bool
|
flagDev bool
|
||||||
flagVersion bool
|
flagVersion bool
|
||||||
service *ws.Service
|
|
||||||
logFile *os.File
|
|
||||||
parsedTemplates map[string]*template.Template
|
parsedTemplates map[string]*template.Template
|
||||||
componentFilenames []string
|
componentFilenames []string
|
||||||
notificationManager notification.Manager
|
notificationManager notification.Manager
|
||||||
fileConf FileConfiguration
|
config Config
|
||||||
|
htmlEngine HTMLTemplate.Engine
|
||||||
|
|
||||||
//go:embed sql
|
//go:embed sql
|
||||||
sqlFS embed.FS
|
sqlFS embed.FS
|
||||||
|
|
@ -61,8 +60,8 @@ func init() { // {{{
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("application", "error", werr.Wrap(err))
|
logger.Error("application", "error", werr.Wrap(err))
|
||||||
}
|
}
|
||||||
cfgPath := path.Join(confDir, "smon.yaml")
|
cfgPath := path.Join(confDir, "smon.json")
|
||||||
flag.StringVar(&flagConfigFile, "config", cfgPath, "Path and filename of the YAML configuration file")
|
flag.StringVar(&flagConfigFile, "config", cfgPath, "Path and filename of the JSON configuration file")
|
||||||
flag.BoolVar(&flagDev, "dev", false, "reload templates on each request")
|
flag.BoolVar(&flagDev, "dev", false, "reload templates on each request")
|
||||||
flag.BoolVar(&flagVersion, "version", false, "Display version and exit")
|
flag.BoolVar(&flagVersion, "version", false, "Display version and exit")
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
@ -81,84 +80,85 @@ func main() { // {{{
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger.Info("application", "version", VERSION)
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
werr.Init()
|
werr.Init()
|
||||||
werr.SetLogCallback(logHandler)
|
|
||||||
|
|
||||||
service, err = ws.New(flagConfigFile, VERSION, logger)
|
logger.Info("application", "config", flagConfigFile)
|
||||||
|
config, err = initConfig(flagConfigFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("application", "error", err)
|
logger.Error("application", "op", "read_config", "error", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
if config.NodataInterval < 10 {
|
||||||
|
logger.Error("application → nodata_interval has to be larger or equal to 10.")
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
j, _ := json.Marshal(service.Config.Application)
|
err = initDb(
|
||||||
json.Unmarshal(j, &fileConf)
|
config.Database.Host,
|
||||||
logFile, err = os.OpenFile(fileConf.LogFile, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
|
config.Database.Port,
|
||||||
|
config.Database.Name,
|
||||||
|
config.Database.Username,
|
||||||
|
config.Database.Password,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("application", "error", err)
|
logger.Error("database", "error", err)
|
||||||
return
|
os.Exit(1)
|
||||||
}
|
|
||||||
if fileConf.NodataInterval < 10 {
|
|
||||||
logger.Error("application → nodata_interval has to be larger or equal to 10.")
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
service.SetDatabase(sqlProvider)
|
htmlEngine, err = initHTMLTemplate()
|
||||||
service.SetStaticFS(staticFS, "static")
|
|
||||||
service.SetStaticDirectory("static", flagDev)
|
|
||||||
service.InitDatabaseConnection()
|
|
||||||
err = service.Db.Connect()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("application", "error", err)
|
logger.Error("application", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
notificationManager, err = InitNotificationManager()
|
notificationManager, err = initNotificationManager()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).Log()
|
err = werr.Wrap(err).Log()
|
||||||
logger.Error("notification", "error", err)
|
logger.Error("notification", "error", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
service.Register("/", false, false, staticHandler)
|
http.HandleFunc("/", staticHandler)
|
||||||
|
|
||||||
service.Register("/area/new/{name}", false, false, actionAreaNew)
|
http.HandleFunc("/area/new/{name}", actionAreaNew)
|
||||||
service.Register("/area/rename/{id}/{name}", false, false, actionAreaRename)
|
http.HandleFunc("/area/rename/{id}/{name}", actionAreaRename)
|
||||||
service.Register("/area/delete/{id}", false, false, actionAreaDelete)
|
http.HandleFunc("/area/delete/{id}", actionAreaDelete)
|
||||||
|
|
||||||
service.Register("/section/new/{areaID}/{name}", false, false, actionSectionNew)
|
http.HandleFunc("/section/new/{areaID}/{name}", actionSectionNew)
|
||||||
service.Register("/section/rename/{id}/{name}", false, false, actionSectionRename)
|
http.HandleFunc("/section/rename/{id}/{name}", actionSectionRename)
|
||||||
service.Register("/section/delete/{id}", false, false, actionSectionDelete)
|
http.HandleFunc("/section/delete/{id}", actionSectionDelete)
|
||||||
|
|
||||||
service.Register("/problems", false, false, pageProblems)
|
http.HandleFunc("/problems", pageProblems)
|
||||||
service.Register("/problem/acknowledge/{id}", false, false, actionProblemAcknowledge)
|
http.HandleFunc("/problem/acknowledge/{id}", actionProblemAcknowledge)
|
||||||
service.Register("/problem/unacknowledge/{id}", false, false, actionProblemUnacknowledge)
|
http.HandleFunc("/problem/unacknowledge/{id}", actionProblemUnacknowledge)
|
||||||
|
|
||||||
service.Register("/datapoints", false, false, pageDatapoints)
|
http.HandleFunc("/datapoints", pageDatapoints)
|
||||||
service.Register("/datapoint/edit/{id}", false, false, pageDatapointEdit)
|
http.HandleFunc("/datapoint/edit/{id}", pageDatapointEdit)
|
||||||
service.Register("/datapoint/update/{id}", false, false, actionDatapointUpdate)
|
http.HandleFunc("/datapoint/update/{id}", actionDatapointUpdate)
|
||||||
service.Register("/datapoint/delete/{id}", false, false, actionDatapointDelete)
|
http.HandleFunc("/datapoint/delete/{id}", actionDatapointDelete)
|
||||||
service.Register("/datapoint/values/{id}", false, false, pageDatapointValues)
|
http.HandleFunc("/datapoint/values/{id}", pageDatapointValues)
|
||||||
service.Register("/datapoint/json/{id}", false, false, actionDatapointJson)
|
http.HandleFunc("/datapoint/json/{id}", actionDatapointJson)
|
||||||
|
|
||||||
service.Register("/triggers", false, false, pageTriggers)
|
http.HandleFunc("/triggers", pageTriggers)
|
||||||
service.Register("/trigger/create/{sectionID}/{name}", false, false, actionTriggerCreate)
|
http.HandleFunc("/trigger/create/{sectionID}/{name}", actionTriggerCreate)
|
||||||
service.Register("/trigger/edit/{id}", false, false, pageTriggerEdit)
|
http.HandleFunc("/trigger/edit/{id}", pageTriggerEdit)
|
||||||
service.Register("/trigger/edit/{id}/{sectionID}", false, false, pageTriggerEdit)
|
http.HandleFunc("/trigger/edit/{id}/{sectionID}", pageTriggerEdit)
|
||||||
service.Register("/trigger/addDatapoint/{id}/{datapointName}", false, false, actionTriggerDatapointAdd)
|
http.HandleFunc("/trigger/addDatapoint/{id}/{datapointName}", actionTriggerDatapointAdd)
|
||||||
service.Register("/trigger/update/{id}", false, false, actionTriggerUpdate)
|
http.HandleFunc("/trigger/update/{id}", actionTriggerUpdate)
|
||||||
service.Register("/trigger/run/{id}", false, false, actionTriggerRun)
|
http.HandleFunc("/trigger/run/{id}", actionTriggerRun)
|
||||||
service.Register("/trigger/delete/{id}", false, false, actionTriggerDelete)
|
http.HandleFunc("/trigger/delete/{id}", actionTriggerDelete)
|
||||||
|
|
||||||
service.Register("/notifications", false, false, pageNotifications)
|
http.HandleFunc("/notifications", pageNotifications)
|
||||||
|
|
||||||
service.Register("/configuration", false, false, pageConfiguration)
|
http.HandleFunc("/configuration", pageConfiguration)
|
||||||
service.Register("/configuration/theme", false, false, actionConfigurationTheme)
|
http.HandleFunc("/configuration/theme", actionConfigurationTheme)
|
||||||
service.Register("/configuration/timezone", false, false, actionConfigurationTimezone)
|
http.HandleFunc("/configuration/timezone", actionConfigurationTimezone)
|
||||||
service.Register("/configuration/notification", false, false, pageConfigurationNotification)
|
http.HandleFunc("/configuration/notification", pageConfigurationNotification)
|
||||||
service.Register("/configuration/notification/update/{prio}", false, false, actionConfigurationNotificationUpdate)
|
http.HandleFunc("/configuration/notification/update/{prio}", actionConfigurationNotificationUpdate)
|
||||||
service.Register("/configuration/notification/delete/{prio}", false, false, actionConfigurationNotificationDelete)
|
http.HandleFunc("/configuration/notification/delete/{prio}", actionConfigurationNotificationDelete)
|
||||||
service.Register("/entry/{datapoint}", false, false, actionEntryDatapoint)
|
http.HandleFunc("/entry/{datapoint}", actionEntryDatapoint)
|
||||||
|
|
||||||
go nodataLoop()
|
go nodataLoop()
|
||||||
|
|
||||||
|
|
@ -174,7 +174,9 @@ func main() { // {{{
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = service.Start()
|
listen := fmt.Sprintf("%s:%d", config.Network.Address, config.Network.Port)
|
||||||
|
logger.Info("webserver", "listen", listen)
|
||||||
|
err = http.ListenAndServe(listen, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("webserver", "error", werr.Wrap(err))
|
logger.Error("webserver", "error", werr.Wrap(err))
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
@ -191,10 +193,8 @@ func sqlProvider(dbname string, version int) (sql []byte, found bool) { // {{{
|
||||||
found = true
|
found = true
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func logHandler(err werr.Error) { // {{{
|
func initHTMLTemplate() (HTMLTemplate.Engine, error) { // {{{
|
||||||
j, _ := json.Marshal(err)
|
return HTMLTemplate.NewEngine(viewFS, staticFS, flagDev)
|
||||||
logFile.Write(j)
|
|
||||||
logFile.Write([]byte("\n"))
|
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func httpError(w http.ResponseWriter, err error) { // {{{
|
func httpError(w http.ResponseWriter, err error) { // {{{
|
||||||
|
|
@ -223,19 +223,19 @@ func pageError(w http.ResponseWriter, redirectURL string, pageErr error) { // {{
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func staticHandler(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{
|
func staticHandler(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
if flagDev && !reloadTemplates(w) {
|
if flagDev && !reloadTemplates(w) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.URL.Path == "/" {
|
if r.URL.Path == "/" {
|
||||||
pageIndex(w, r, sess)
|
pageIndex(w, r)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
service.StaticHandler(w, r, sess)
|
htmlEngine.StaticResource(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionEntryDatapoint(w http.ResponseWriter, r *http.Request, sess *session.T) { // {{{
|
func actionEntryDatapoint(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
dpoint := r.PathValue("datapoint")
|
dpoint := r.PathValue("datapoint")
|
||||||
value, _ := io.ReadAll(r.Body)
|
value, _ := io.ReadAll(r.Body)
|
||||||
|
|
||||||
|
|
@ -307,7 +307,8 @@ func actionEntryDatapoint(w http.ResponseWriter, r *http.Request, sess *session.
|
||||||
} else {
|
} else {
|
||||||
errBody = nil
|
errBody = nil
|
||||||
}
|
}
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
INSERT INTO notification_send(notification_id, problem_id, uuid, ok, error)
|
INSERT INTO notification_send(notification_id, problem_id, uuid, ok, error)
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -398,7 +399,7 @@ func getPage(layout, page string) (tmpl *template.Template, err error) { // {{{
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageIndex(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageIndex(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
page := Page{
|
page := Page{
|
||||||
LAYOUT: "main",
|
LAYOUT: "main",
|
||||||
PAGE: "index",
|
PAGE: "index",
|
||||||
|
|
@ -407,7 +408,7 @@ func pageIndex(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func actionAreaNew(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionAreaNew(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
name := r.PathValue("name")
|
name := r.PathValue("name")
|
||||||
err := AreaCreate(name)
|
err := AreaCreate(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -419,7 +420,7 @@ func actionAreaNew(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionAreaRename(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionAreaRename(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -438,7 +439,7 @@ func actionAreaRename(w http.ResponseWriter, r *http.Request, _ *session.T) { //
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionAreaDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionAreaDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -457,7 +458,7 @@ func actionAreaDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { //
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func actionSectionNew(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionSectionNew(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("areaID")
|
idStr := r.PathValue("areaID")
|
||||||
areaID, err := strconv.Atoi(idStr)
|
areaID, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -476,7 +477,7 @@ func actionSectionNew(w http.ResponseWriter, r *http.Request, _ *session.T) { //
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionSectionRename(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionSectionRename(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -495,7 +496,7 @@ func actionSectionRename(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionSectionDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionSectionDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -514,7 +515,7 @@ func actionSectionDelete(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageProblems(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageProblems(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
page := Page{
|
page := Page{
|
||||||
LAYOUT: "main",
|
LAYOUT: "main",
|
||||||
PAGE: "problems",
|
PAGE: "problems",
|
||||||
|
|
@ -578,7 +579,7 @@ func pageProblems(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionProblemAcknowledge(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionProblemAcknowledge(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -597,7 +598,7 @@ func actionProblemAcknowledge(w http.ResponseWriter, r *http.Request, _ *session
|
||||||
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionProblemUnacknowledge(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionProblemUnacknowledge(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -617,7 +618,7 @@ func actionProblemUnacknowledge(w http.ResponseWriter, r *http.Request, _ *sessi
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageDatapoints(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageDatapoints(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
page := Page{
|
page := Page{
|
||||||
LAYOUT: "main",
|
LAYOUT: "main",
|
||||||
PAGE: "datapoints",
|
PAGE: "datapoints",
|
||||||
|
|
@ -643,7 +644,7 @@ func pageDatapoints(w http.ResponseWriter, r *http.Request, _ *session.T) { // {
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func pageDatapointEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageDatapointEdit(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -700,7 +701,7 @@ func pageDatapointEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { /
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionDatapointUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionDatapointUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -757,7 +758,7 @@ func actionDatapointUpdate(w http.ResponseWriter, r *http.Request, _ *session.T)
|
||||||
w.Header().Add("Location", "/datapoints")
|
w.Header().Add("Location", "/datapoints")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionDatapointDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionDatapointDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -774,7 +775,7 @@ func actionDatapointDelete(w http.ResponseWriter, r *http.Request, _ *session.T)
|
||||||
w.Header().Add("Location", "/datapoints")
|
w.Header().Add("Location", "/datapoints")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageDatapointValues(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -833,7 +834,7 @@ func pageDatapointValues(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionDatapointJson(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionDatapointJson(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -865,7 +866,7 @@ func actionDatapointJson(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageTriggers(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageTriggers(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
areas, err := TriggersRetrieve()
|
areas, err := TriggersRetrieve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, werr.Wrap(err).Log())
|
httpError(w, werr.Wrap(err).Log())
|
||||||
|
|
@ -887,7 +888,7 @@ func pageTriggers(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
||||||
|
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionTriggerCreate(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionTriggerCreate(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
name := r.PathValue("name")
|
name := r.PathValue("name")
|
||||||
sectionIDStr := r.PathValue("sectionID")
|
sectionIDStr := r.PathValue("sectionID")
|
||||||
sectionID, err := strconv.Atoi(sectionIDStr)
|
sectionID, err := strconv.Atoi(sectionIDStr)
|
||||||
|
|
@ -919,7 +920,7 @@ func actionTriggerCreate(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
} // }}}
|
} // }}}
|
||||||
func pageTriggerEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageTriggerEdit(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -975,7 +976,7 @@ func pageTriggerEdit(w http.ResponseWriter, r *http.Request, _ *session.T) { //
|
||||||
|
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionTriggerDatapointAdd(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionTriggerDatapointAdd(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
triggerID := r.PathValue("id")
|
triggerID := r.PathValue("id")
|
||||||
dpName := r.PathValue("datapointName")
|
dpName := r.PathValue("datapointName")
|
||||||
|
|
||||||
|
|
@ -1022,7 +1023,7 @@ func actionTriggerDatapointAdd(w http.ResponseWriter, r *http.Request, _ *sessio
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionTriggerUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionTriggerUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1057,7 +1058,7 @@ func actionTriggerUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
w.Header().Add("Location", "/triggers")
|
w.Header().Add("Location", "/triggers")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionTriggerRun(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionTriggerRun(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1092,7 +1093,7 @@ func actionTriggerRun(w http.ResponseWriter, r *http.Request, _ *session.T) { //
|
||||||
w.Header().Add("Content-Type", "application/json")
|
w.Header().Add("Content-Type", "application/json")
|
||||||
w.Write(j)
|
w.Write(j)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionTriggerDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionTriggerDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
idStr := r.PathValue("id")
|
idStr := r.PathValue("id")
|
||||||
id, err := strconv.Atoi(idStr)
|
id, err := strconv.Atoi(idStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1110,7 +1111,7 @@ func actionTriggerDelete(w http.ResponseWriter, r *http.Request, _ *session.T) {
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageConfiguration(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageConfiguration(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
areas, err := AreaRetrieve()
|
areas, err := AreaRetrieve()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
httpError(w, werr.Wrap(err).Log())
|
httpError(w, werr.Wrap(err).Log())
|
||||||
|
|
@ -1134,7 +1135,7 @@ func pageConfiguration(w http.ResponseWriter, r *http.Request, _ *session.T) { /
|
||||||
|
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionConfigurationTheme(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionConfigurationTheme(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
theme := r.FormValue("theme")
|
theme := r.FormValue("theme")
|
||||||
err := smonConfig.SetTheme(theme)
|
err := smonConfig.SetTheme(theme)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1145,7 +1146,7 @@ func actionConfigurationTheme(w http.ResponseWriter, r *http.Request, _ *session
|
||||||
w.Header().Add("Location", "/configuration")
|
w.Header().Add("Location", "/configuration")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionConfigurationTimezone(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionConfigurationTimezone(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
timezone := r.FormValue("timezone")
|
timezone := r.FormValue("timezone")
|
||||||
|
|
||||||
_, err := time.LoadLocation(timezone)
|
_, err := time.LoadLocation(timezone)
|
||||||
|
|
@ -1163,7 +1164,7 @@ func actionConfigurationTimezone(w http.ResponseWriter, r *http.Request, _ *sess
|
||||||
w.Header().Add("Location", "/configuration")
|
w.Header().Add("Location", "/configuration")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func pageConfigurationNotification(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageConfigurationNotification(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
// This function is either receiving a type when creating a new service,
|
// This function is either receiving a type when creating a new service,
|
||||||
// or a prio when editing an existing.
|
// or a prio when editing an existing.
|
||||||
notificationType := r.URL.Query().Get("type")
|
notificationType := r.URL.Query().Get("type")
|
||||||
|
|
@ -1215,7 +1216,7 @@ func pageConfigurationNotification(w http.ResponseWriter, r *http.Request, _ *se
|
||||||
|
|
||||||
page.Render(w, r)
|
page.Render(w, r)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionConfigurationNotificationUpdate(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionConfigurationNotificationUpdate(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
prioStr := r.PathValue("prio")
|
prioStr := r.PathValue("prio")
|
||||||
prio, err := strconv.Atoi(prioStr)
|
prio, err := strconv.Atoi(prioStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1268,7 +1269,7 @@ func actionConfigurationNotificationUpdate(w http.ResponseWriter, r *http.Reques
|
||||||
w.Header().Add("Location", "/configuration")
|
w.Header().Add("Location", "/configuration")
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
func actionConfigurationNotificationDelete(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func actionConfigurationNotificationDelete(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
prioStr := r.PathValue("prio")
|
prioStr := r.PathValue("prio")
|
||||||
prio, err := strconv.Atoi(prioStr)
|
prio, err := strconv.Atoi(prioStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -1283,7 +1284,7 @@ func actionConfigurationNotificationDelete(w http.ResponseWriter, r *http.Reques
|
||||||
w.WriteHeader(302)
|
w.WriteHeader(302)
|
||||||
} // }}}
|
} // }}}
|
||||||
|
|
||||||
func pageNotifications(w http.ResponseWriter, r *http.Request, _ *session.T) { // {{{
|
func pageNotifications(w http.ResponseWriter, r *http.Request) { // {{{
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// Manage the values from the timefilter component
|
// Manage the values from the timefilter component
|
||||||
|
|
|
||||||
25
nodata.go
25
nodata.go
|
|
@ -2,13 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
"smon/notification"
|
"smon/notification"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"database/sql"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
@ -24,7 +25,7 @@ func nodataLoop() {
|
||||||
var datapoints []Datapoint
|
var datapoints []Datapoint
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
ticker := time.NewTicker(time.Second * time.Duration(fileConf.NodataInterval))
|
ticker := time.NewTicker(time.Second * time.Duration(config.NodataInterval))
|
||||||
for {
|
for {
|
||||||
<-ticker.C
|
<-ticker.C
|
||||||
datapoints, err = nodataDatapoints()
|
datapoints, err = nodataDatapoints()
|
||||||
|
|
@ -62,7 +63,8 @@ func nodataNotify(datapoint Datapoint, state string) (err error) {
|
||||||
} else {
|
} else {
|
||||||
errBody = nil
|
errBody = nil
|
||||||
}
|
}
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
INSERT INTO notification_send(notification_id, datapoint_nodata_id, uuid, ok, error)
|
INSERT INTO notification_send(notification_id, datapoint_nodata_id, uuid, ok, error)
|
||||||
SELECT
|
SELECT
|
||||||
|
|
@ -93,8 +95,9 @@ func nodataNotify(datapoint Datapoint, state string) (err error) {
|
||||||
func nodataDatapoints() (datapoints []Datapoint, err error) {
|
func nodataDatapoints() (datapoints []Datapoint, err error) {
|
||||||
datapoints = []Datapoint{}
|
datapoints = []Datapoint{}
|
||||||
|
|
||||||
var rows *sql.Rows
|
rows, _ := db.Query(
|
||||||
rows, err = service.Db.Conn.Query(`
|
context.Background(),
|
||||||
|
`
|
||||||
UPDATE datapoint
|
UPDATE datapoint
|
||||||
SET
|
SET
|
||||||
nodata_is_problem = true
|
nodata_is_problem = true
|
||||||
|
|
@ -115,19 +118,11 @@ func nodataDatapoints() (datapoints []Datapoint, err error) {
|
||||||
datapoint.name
|
datapoint.name
|
||||||
|
|
||||||
`)
|
`)
|
||||||
|
datapoints, err = pgx.CollectRows(rows, pgx.RowToStructByName[Datapoint])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err)
|
err = werr.Wrap(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
var dp Datapoint
|
|
||||||
for rows.Next() {
|
|
||||||
if err = rows.Scan(&dp.ID, &dp.Name); err != nil {
|
|
||||||
err = werr.Wrap(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
datapoints = append(datapoints, dp)
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"bytes"
|
"bytes"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package notification
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
|
|
||||||
|
|
@ -2,13 +2,14 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
"github.com/jmoiron/sqlx"
|
"github.com/jackc/pgx/v5"
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
"smon/notification"
|
"smon/notification"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -30,19 +31,24 @@ type NotificationSend struct {
|
||||||
func notificationLog(notificationService *notification.Service, problemID int, err error) {
|
func notificationLog(notificationService *notification.Service, problemID int, err error) {
|
||||||
if err == nil {
|
if err == nil {
|
||||||
logger.Info("notification", "service", (*notificationService).GetType(), "problemID", problemID, "prio", (*notificationService).GetPrio(), "ok", true)
|
logger.Info("notification", "service", (*notificationService).GetType(), "problemID", problemID, "prio", (*notificationService).GetPrio(), "ok", true)
|
||||||
service.Db.Conn.Query(
|
_, dbErr := db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
INSERT INTO notification_send()
|
INSERT INTO notification_send()
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
|
if dbErr != nil {
|
||||||
|
logger.Error("notification", "op", "notification_send", "error", werr.Wrap(err))
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
logger.Error("notification", "service", (*notificationService).GetType(), "problemID", problemID, "prio", (*notificationService).GetPrio(), "ok", false, "error", err)
|
logger.Error("notification", "service", (*notificationService).GetType(), "problemID", problemID, "prio", (*notificationService).GetPrio(), "ok", false, "error", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func notificationsSent(from, to time.Time) (nss []NotificationSend, err error) {
|
func notificationsSent(from, to time.Time) (nss []NotificationSend, err error) {
|
||||||
var rows *sqlx.Rows
|
rows, _ := db.Query(
|
||||||
rows, err = service.Db.Conn.Queryx(
|
context.Background(),
|
||||||
`
|
`
|
||||||
SELECT
|
SELECT
|
||||||
n.prio,
|
n.prio,
|
||||||
|
|
@ -71,15 +77,8 @@ func notificationsSent(from, to time.Time) (nss []NotificationSend, err error) {
|
||||||
from,
|
from,
|
||||||
to,
|
to,
|
||||||
)
|
)
|
||||||
if err != nil {
|
nss, err = pgx.CollectRows(rows, func(row pgx.CollectableRow) (ns NotificationSend, err error) {
|
||||||
err = werr.Wrap(err)
|
ns, err = pgx.RowToStructByName[NotificationSend](row)
|
||||||
return
|
|
||||||
}
|
|
||||||
defer rows.Close()
|
|
||||||
|
|
||||||
for rows.Next() {
|
|
||||||
ns := NotificationSend{}
|
|
||||||
err = rows.StructScan(&ns)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err)
|
err = werr.Wrap(err)
|
||||||
return
|
return
|
||||||
|
|
@ -93,7 +92,12 @@ func notificationsSent(from, to time.Time) (nss []NotificationSend, err error) {
|
||||||
j, err = json.MarshalIndent(foo, "", " ")
|
j, err = json.MarshalIndent(foo, "", " ")
|
||||||
ns.ErrorIndented = string(j)
|
ns.ErrorIndented = string(j)
|
||||||
|
|
||||||
nss = append(nss, ns)
|
return
|
||||||
}
|
})
|
||||||
|
if err != nil {
|
||||||
|
err = werr.Wrap(err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,16 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
"github.com/lib/pq"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
|
||||||
// Internal
|
// Internal
|
||||||
"smon/notification"
|
"smon/notification"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DbNotificationService struct {
|
type DbNotificationService struct {
|
||||||
|
|
@ -19,9 +21,11 @@ type DbNotificationService struct {
|
||||||
Prio int
|
Prio int
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitNotificationManager() (nm notification.Manager, err error) { // {{{
|
func initNotificationManager() (nm notification.Manager, err error) { // {{{
|
||||||
var dbServices []DbNotificationService
|
var dbServices []DbNotificationService
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
WITH services AS (
|
WITH services AS (
|
||||||
SELECT
|
SELECT
|
||||||
id,
|
id,
|
||||||
|
|
@ -36,6 +40,7 @@ func InitNotificationManager() (nm notification.Manager, err error) { // {{{
|
||||||
FROM services s
|
FROM services s
|
||||||
`,
|
`,
|
||||||
)
|
)
|
||||||
|
|
||||||
var dbData []byte
|
var dbData []byte
|
||||||
err = row.Scan(&dbData)
|
err = row.Scan(&dbData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -70,7 +75,8 @@ func InitNotificationManager() (nm notification.Manager, err error) { // {{{
|
||||||
} // }}}
|
} // }}}
|
||||||
func UpdateNotificationService(svc notification.Service) (created bool, err error) { // {{{
|
func UpdateNotificationService(svc notification.Service) (created bool, err error) { // {{{
|
||||||
if svc.Exists() {
|
if svc.Exists() {
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
UPDATE public.notification
|
UPDATE public.notification
|
||||||
SET
|
SET
|
||||||
|
|
@ -84,11 +90,11 @@ func UpdateNotificationService(svc notification.Service) (created bool, err erro
|
||||||
svc.Updated().JSON(),
|
svc.Updated().JSON(),
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
INSERT INTO public.notification(prio, configuration, service)
|
INSERT INTO public.notification(prio, configuration, service)
|
||||||
VALUES($1, $2, $3)
|
VALUES($1, $2, $3)
|
||||||
|
|
||||||
`,
|
`,
|
||||||
svc.Updated().GetPrio(),
|
svc.Updated().GetPrio(),
|
||||||
svc.Updated().JSON(),
|
svc.Updated().JSON(),
|
||||||
|
|
@ -99,8 +105,8 @@ func UpdateNotificationService(svc notification.Service) (created bool, err erro
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Check if this is just a duplicated prio, which isn't allowed.
|
// Check if this is just a duplicated prio, which isn't allowed.
|
||||||
pgErr, isPgErr := err.(*pq.Error)
|
var pgErr *pgconn.PgError
|
||||||
if isPgErr && pgErr.Code == "23505" {
|
if errors.As(err, &pgErr); pgErr.Code == "23505" {
|
||||||
return false, werr.New("Prio %d is already used by another service", svc.Updated().GetPrio())
|
return false, werr.New("Prio %d is already used by another service", svc.Updated().GetPrio())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,12 +123,12 @@ func UpdateNotificationService(svc notification.Service) (created bool, err erro
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func DeleteNotificationService(prio int) (err error) { // {{{
|
func DeleteNotificationService(prio int) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
`
|
`
|
||||||
DELETE FROM public.notification
|
DELETE FROM public.notification
|
||||||
WHERE
|
WHERE
|
||||||
prio = $1
|
prio = $1
|
||||||
|
|
||||||
`,
|
`,
|
||||||
prio,
|
prio,
|
||||||
)
|
)
|
||||||
|
|
@ -135,7 +141,7 @@ func DeleteNotificationService(prio int) (err error) { // {{{
|
||||||
|
|
||||||
func AcknowledgeNotification(uuid string) (err error) { // {{{
|
func AcknowledgeNotification(uuid string) (err error) { // {{{
|
||||||
/*
|
/*
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE schedule SET acknowledged=true WHERE schedule_uuid=$1`, uuid)
|
_, err = db.Exec(context.Background(), `UPDATE schedule SET acknowledged=true WHERE schedule_uuid=$1`, uuid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(uuid)
|
err = werr.Wrap(err).WithData(uuid)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
page.go
2
page.go
|
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
|
||||||
24
problem.go
24
problem.go
|
|
@ -2,9 +2,10 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
@ -28,7 +29,9 @@ type Problem struct { // {{{
|
||||||
|
|
||||||
func ProblemsRetrieve(showCurrent bool, from, to time.Time) (problems []Problem, err error) { // {{{
|
func ProblemsRetrieve(showCurrent bool, from, to time.Time) (problems []Problem, err error) { // {{{
|
||||||
problems = []Problem{}
|
problems = []Problem{}
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
SELECT
|
SELECT
|
||||||
jsonb_agg(problems.*)
|
jsonb_agg(problems.*)
|
||||||
FROM (
|
FROM (
|
||||||
|
|
@ -104,7 +107,9 @@ func ProblemsRetrieve(showCurrent bool, from, to time.Time) (problems []Problem,
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{
|
func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
SELECT COUNT(id)
|
SELECT COUNT(id)
|
||||||
FROM problem
|
FROM problem
|
||||||
WHERE
|
WHERE
|
||||||
|
|
@ -124,7 +129,8 @@ func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{
|
||||||
// Open up a new problem if no open exists.
|
// Open up a new problem if no open exists.
|
||||||
if openProblems == 0 {
|
if openProblems == 0 {
|
||||||
datapointValuesJson, _ := json.Marshal(trigger.DatapointValues)
|
datapointValuesJson, _ := json.Marshal(trigger.DatapointValues)
|
||||||
row = service.Db.Conn.QueryRow(
|
row = db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
`INSERT INTO problem(trigger_id, trigger_name, datapoints, trigger_expression) VALUES($1, $2, $3, $4) RETURNING id`,
|
`INSERT INTO problem(trigger_id, trigger_name, datapoints, trigger_expression) VALUES($1, $2, $3, $4) RETURNING id`,
|
||||||
trigger.ID,
|
trigger.ID,
|
||||||
trigger.Name,
|
trigger.Name,
|
||||||
|
|
@ -139,9 +145,13 @@ func ProblemStart(trigger Trigger) (problemID int, err error) { // {{{
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{
|
func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{
|
||||||
row := service.Db.Conn.QueryRow(`UPDATE problem SET "end"=NOW() WHERE trigger_id=$1 AND "end" IS NULL RETURNING id`, trigger.ID)
|
row := db.QueryRow(
|
||||||
err = row.Scan(&problemID)
|
context.Background(),
|
||||||
|
`UPDATE problem SET "end"=NOW() WHERE trigger_id=$1 AND "end" IS NULL RETURNING id`,
|
||||||
|
trigger.ID,
|
||||||
|
)
|
||||||
|
|
||||||
|
err = row.Scan(&problemID)
|
||||||
if err == sql.ErrNoRows {
|
if err == sql.ErrNoRows {
|
||||||
err = nil
|
err = nil
|
||||||
return
|
return
|
||||||
|
|
@ -154,7 +164,7 @@ func ProblemClose(trigger Trigger) (problemID int, err error) { // {{{
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func ProblemAcknowledge(id int, state bool) (err error) { // {{{
|
func ProblemAcknowledge(id int, state bool) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE problem SET "acknowledged"=$2 WHERE id=$1`, id, state)
|
_, err = db.Exec(context.Background(), `UPDATE problem SET "acknowledged"=$2 WHERE id=$1`, id, state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = werr.Wrap(err).WithData(id)
|
err = werr.Wrap(err).WithData(id)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
17
section.go
17
section.go
|
|
@ -2,9 +2,10 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
|
"context"
|
||||||
"sort"
|
"sort"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -26,20 +27,26 @@ func (s *Section) SortedTriggers() []Trigger {
|
||||||
}
|
}
|
||||||
|
|
||||||
func SectionCreate(areaID int, name string) (err error) { // {{{
|
func SectionCreate(areaID int, name string) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`INSERT INTO section(area_id, name) VALUES($1, $2)`, areaID, name)
|
_, err = db.Exec(context.Background(), `INSERT INTO section(area_id, name) VALUES($1, $2)`, areaID, name)
|
||||||
|
if err != nil {
|
||||||
|
err = werr.Wrap(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func SectionRename(id int, name string) (err error) { // {{{
|
func SectionRename(id int, name string) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`UPDATE section SET name=$2 WHERE id=$1`, id, name)
|
_, err = db.Exec(context.Background(), `UPDATE section SET name=$2 WHERE id=$1`, id, name)
|
||||||
|
if err != nil {
|
||||||
|
err = werr.Wrap(err)
|
||||||
|
}
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func SectionDelete(id int) (err error) { // {{{
|
func SectionDelete(id int) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`DELETE FROM public.trigger WHERE section_id = $1`, id)
|
_, err = db.Exec(context.Background(), `DELETE FROM public.trigger WHERE section_id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = service.Db.Conn.Exec(`DELETE FROM public.section WHERE id = $1`, id)
|
_, err = db.Exec(context.Background(), `DELETE FROM public.section WHERE id = $1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"time"
|
"time"
|
||||||
|
|
|
||||||
46
trigger.go
46
trigger.go
|
|
@ -2,15 +2,16 @@ package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
// External
|
// External
|
||||||
werr "git.gibonuddevalla.se/go/wrappederror"
|
werr "git.ahall.se/go/wrappederror"
|
||||||
"github.com/expr-lang/expr"
|
"github.com/expr-lang/expr"
|
||||||
"github.com/expr-lang/expr/ast"
|
"github.com/expr-lang/expr/ast"
|
||||||
"github.com/expr-lang/expr/parser"
|
"github.com/expr-lang/expr/parser"
|
||||||
"github.com/lib/pq"
|
"github.com/jackc/pgx/v5/pgconn"
|
||||||
|
|
||||||
// Standard
|
// Standard
|
||||||
"database/sql"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
@ -45,7 +46,9 @@ func TriggerCreate(sectionID int, name string) (t Trigger, err error) { // {{{
|
||||||
func TriggersRetrieve() (areas []Area, err error) { // {{{
|
func TriggersRetrieve() (areas []Area, err error) { // {{{
|
||||||
areas = []Area{}
|
areas = []Area{}
|
||||||
|
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
WITH section_triggers AS (
|
WITH section_triggers AS (
|
||||||
SELECT
|
SELECT
|
||||||
s.id AS id,
|
s.id AS id,
|
||||||
|
|
@ -99,7 +102,9 @@ func TriggersRetrieve() (areas []Area, err error) { // {{{
|
||||||
} // }}}
|
} // }}}
|
||||||
func TriggersRetrieveByDatapoint(datapointName string) (triggers []Trigger, err error) { // {{{
|
func TriggersRetrieveByDatapoint(datapointName string) (triggers []Trigger, err error) { // {{{
|
||||||
triggers = []Trigger{}
|
triggers = []Trigger{}
|
||||||
row := service.Db.Conn.QueryRow(`
|
row := db.QueryRow(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
SELECT jsonb_agg(t.*)
|
SELECT jsonb_agg(t.*)
|
||||||
FROM public."trigger" t
|
FROM public."trigger" t
|
||||||
WHERE
|
WHERE
|
||||||
|
|
@ -129,7 +134,7 @@ func TriggersRetrieveByDatapoint(datapointName string) (triggers []Trigger, err
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func TriggerRetrieve(id int) (trigger Trigger, err error) { // {{{
|
func TriggerRetrieve(id int) (trigger Trigger, err error) { // {{{
|
||||||
row := service.Db.Conn.QueryRow(`SELECT to_jsonb(t.*) FROM "trigger" t WHERE id=$1`, id)
|
row := db.QueryRow(context.Background(), `SELECT to_jsonb(t.*) FROM "trigger" t WHERE id=$1`, id)
|
||||||
var jsonData []byte
|
var jsonData []byte
|
||||||
err = row.Scan(&jsonData)
|
err = row.Scan(&jsonData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -141,7 +146,7 @@ func TriggerRetrieve(id int) (trigger Trigger, err error) { // {{{
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func TriggerDelete(id int) (err error) { // {{{
|
func TriggerDelete(id int) (err error) { // {{{
|
||||||
_, err = service.Db.Conn.Exec(`DELETE FROM public.trigger WHERE id=$1`, id)
|
_, err = db.Exec(context.Background(), `DELETE FROM public.trigger WHERE id=$1`, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return werr.Wrap(err).WithData(id)
|
return werr.Wrap(err).WithData(id)
|
||||||
}
|
}
|
||||||
|
|
@ -172,8 +177,9 @@ func (t *Trigger) Update() (err error) { // {{{
|
||||||
}
|
}
|
||||||
jsonDatapoints, _ := json.Marshal(t.Datapoints)
|
jsonDatapoints, _ := json.Marshal(t.Datapoints)
|
||||||
if t.ID == 0 {
|
if t.ID == 0 {
|
||||||
var row *sql.Row
|
row := db.QueryRow(
|
||||||
row = service.Db.Conn.QueryRow(`
|
context.Background(),
|
||||||
|
`
|
||||||
INSERT INTO "trigger"(name, section_id, expression, datapoints)
|
INSERT INTO "trigger"(name, section_id, expression, datapoints)
|
||||||
VALUES($1, $2, $3, $4)
|
VALUES($1, $2, $3, $4)
|
||||||
RETURNING id
|
RETURNING id
|
||||||
|
|
@ -201,7 +207,9 @@ func (t *Trigger) Update() (err error) { // {{{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
_, err = service.Db.Conn.Exec(`
|
_, err = db.Exec(
|
||||||
|
context.Background(),
|
||||||
|
`
|
||||||
UPDATE "trigger"
|
UPDATE "trigger"
|
||||||
SET
|
SET
|
||||||
name=$2,
|
name=$2,
|
||||||
|
|
@ -217,20 +225,26 @@ func (t *Trigger) Update() (err error) { // {{{
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
if pqErr, ok := err.(*pq.Error); ok {
|
var pgErr *pgconn.PgError
|
||||||
|
if errors.As(err, &pgErr) {
|
||||||
err = werr.Wrap(err).WithData(
|
err = werr.Wrap(err).WithData(
|
||||||
struct {
|
struct {
|
||||||
Trigger *Trigger
|
Trigger *Trigger
|
||||||
PostgresCode pq.ErrorCode
|
PostgresCode string
|
||||||
PostgresMsg string
|
PostgresMsg string
|
||||||
}{
|
}{
|
||||||
t,
|
t,
|
||||||
pqErr.Code,
|
pgErr.Code,
|
||||||
pqErr.Code.Name(),
|
pgErr.Message,
|
||||||
})
|
})
|
||||||
} else if err != nil {
|
return
|
||||||
err = werr.Wrap(err).WithData(t)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
err = werr.Wrap(err).WithData(t)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
} // }}}
|
} // }}}
|
||||||
func (t *Trigger) Run() (output any, err error) { // {{{
|
func (t *Trigger) Run() (output any, err error) { // {{{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue