From 4255c3b69d2d884d276f85cf85ea7b992215017c Mon Sep 17 00:00:00 2001 From: Tine Date: Sun, 28 Apr 2024 21:24:00 +0200 Subject: [PATCH] feat(triggers): initial get/describe/create/update pages --- CONTRIBUTING.md | 11 + database/models/models.go | 27 ++ .../sqlite/migrations/2024-04-28_triggers.sql | 29 +++ go.mod | 24 ++ go.sum | 75 ++++++ internal/handlers/settings.go | 6 +- internal/handlers/settings_incidents.go | 30 --- internal/handlers/settings_triggers.go | 234 ++++++++++++++++++ internal/services/trigger.go | 61 +++++ justfile | 15 ++ pkg/server/routes.go | 14 +- ..._incidents.tmpl => settings_triggers.tmpl} | 28 +-- .../pages/settings_triggers_create.tmpl | 55 ++++ .../pages/settings_triggers_describe.tmpl | 142 +++++++++++ web/templates/tempaltes.go | 4 +- 15 files changed, 700 insertions(+), 55 deletions(-) create mode 100644 CONTRIBUTING.md create mode 100644 database/sqlite/migrations/2024-04-28_triggers.sql delete mode 100644 internal/handlers/settings_incidents.go create mode 100644 internal/handlers/settings_triggers.go create mode 100644 internal/services/trigger.go rename web/templates/pages/{settings_incidents.tmpl => settings_triggers.tmpl} (70%) create mode 100644 web/templates/pages/settings_triggers_create.tmpl create mode 100644 web/templates/pages/settings_triggers_describe.tmpl diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..f97341f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,11 @@ +# `CONTRIBUTING.md` + +Hello, and thank you for choosing to contribute to this project. + +## Changing database schema. + +### Create new migration file. + +You can read about the syntax in the [rubenv/sql-migrate](https://github.com/rubenv/sql-migrate?tab=readme-ov-file#writing-migrations) repo. The files are located in `database/sqlite/migrations/` folder. + +To create a new migration file, run `just migration-new creating-something-new`. diff --git a/database/models/models.go b/database/models/models.go index 99c4f97..fbb3dbd 100644 --- a/database/models/models.go +++ b/database/models/models.go @@ -98,3 +98,30 @@ type WorkerGroupWithMonitors struct { // List of worker group names Monitors []string } + +type TriggerStatus string + +const ( + TriggerSuccess TriggerStatus = "SUCCESS" + TriggerFailure TriggerStatus = "FAILURE" + TriggerError TriggerStatus = "ERROR" + TriggerUnknown TriggerStatus = "UNKNOWN" +) + +type Trigger struct { + CreatedAt *Time `db:"created_at"` + UpdatedAt *Time `db:"updated_at"` + + Id string `db:"id"` + Name string `db:"name"` + Script string `db:"script"` + Status TriggerStatus `db:"status"` +} + +type TriggerHistory struct { + CreatedAt *Time `db:"created_at"` + + TriggerId string `db:"trigger_id"` + Status TriggerStatus `db:"status"` + Note string `db:"note"` +} diff --git a/database/sqlite/migrations/2024-04-28_triggers.sql b/database/sqlite/migrations/2024-04-28_triggers.sql new file mode 100644 index 0000000..ff3c9de --- /dev/null +++ b/database/sqlite/migrations/2024-04-28_triggers.sql @@ -0,0 +1,29 @@ +-- +migrate Up +CREATE TABLE triggers ( + id TEXT NOT NULL, + name TEXT NOT NULL, + script TEXT NOT NULL, + status TEXT NOT NULL, + + created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ')), + updated_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ')), + + PRIMARY KEY (id), + CONSTRAINT unique_triggers_name UNIQUE (name) +) STRICT; + +CREATE TABLE trigger_histories ( + trigger_id TEXT NOT NULL, + + status TEXT NOT NULL, + note TEXT NOT NULL, + + created_at TEXT NOT NULL DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ')), + + PRIMARY KEY (trigger_id, created_at), + CONSTRAINT fk_trigger_histories_trigger FOREIGN KEY (trigger_id) REFERENCES triggers(id) ON DELETE CASCADE +) STRICT; + +-- +migrate Down +DROP TABLE triggers; +DROP TABLE trigger_histories; diff --git a/go.mod b/go.mod index 3ea50d7..3451805 100644 --- a/go.mod +++ b/go.mod @@ -33,14 +33,19 @@ require ( cloud.google.com/go/iam v1.1.5 // indirect cloud.google.com/go/storage v1.36.0 // indirect github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect + github.com/Masterminds/goutils v1.1.1 // indirect + github.com/Masterminds/semver/v3 v3.2.0 // indirect + github.com/Masterminds/sprig/v3 v3.2.3 // indirect github.com/PuerkitoBio/goquery v1.8.1 // indirect github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5 // indirect github.com/andybalholm/brotli v1.0.6 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect github.com/apache/thrift v0.18.1 // indirect + github.com/armon/go-radix v1.0.0 // indirect github.com/aws/aws-sdk-go v1.44.289 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect + github.com/bgentry/speakeasy v0.1.0 // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/bufbuild/protocompile v0.7.1 // indirect github.com/cactus/go-statsd-client/statsd v0.0.0-20200423205355-cb0885a1018c // indirect @@ -51,6 +56,7 @@ require ( github.com/chromedp/sysutil v1.0.0 // indirect github.com/coreos/go-oidc/v3 v3.1.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/denisenkom/go-mssqldb v0.9.0 // indirect github.com/dgraph-io/ristretto v0.1.1 // indirect github.com/dgryski/go-farm v0.0.0-20200201041132-a6ae2369ad13 // indirect github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect @@ -64,6 +70,7 @@ require ( github.com/fsnotify/fsnotify v1.7.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/go-gorp/gorp/v3 v3.1.0 // indirect + github.com/go-logfmt/logfmt v0.6.0 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -71,9 +78,12 @@ require ( github.com/go-sourcemap/sourcemap v2.1.4-0.20211119122758-180fcef48034+incompatible // indirect github.com/go-sql-driver/mysql v1.7.1 // indirect github.com/gocql/gocql v1.5.2 // indirect + github.com/godror/godror v0.40.4 // indirect + github.com/godror/knownpb v0.1.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect + github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe // indirect github.com/golang/glog v1.1.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/mock v1.7.0-rc.1 // indirect @@ -96,8 +106,12 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 // indirect github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed // indirect + github.com/hashicorp/errwrap v1.1.0 // indirect + github.com/hashicorp/go-multierror v1.1.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect + github.com/huandu/xstrings v1.4.0 // indirect github.com/iancoleman/strcase v0.3.0 // indirect + github.com/imdario/mergo v0.3.13 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect github.com/jackc/pgx/v5 v5.4.3 // indirect @@ -113,18 +127,25 @@ require ( github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-oci8 v0.1.1 // indirect + github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mccutchen/go-httpbin v1.1.2-0.20190116014521-c5cb2f4802fa // indirect + github.com/mitchellh/cli v1.1.5 // indirect + github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect + github.com/mitchellh/reflectwalk v1.0.2 // indirect github.com/mstoykov/atlas v0.0.0-20220811071828-388f114305dd // indirect github.com/mstoykov/k6-taskqueue-lib v0.1.0 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/olivere/elastic/v7 v7.0.32 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pborman/uuid v1.2.1 // indirect github.com/pelletier/go-toml/v2 v2.1.0 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect + github.com/posener/complete v1.2.3 // indirect github.com/prometheus/client_golang v1.16.0 // indirect github.com/prometheus/client_model v0.4.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -132,11 +153,13 @@ require ( github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect github.com/redis/go-redis/v9 v9.0.5 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect + github.com/rivo/uniseg v0.4.4 // indirect github.com/robfig/cron v1.2.0 // indirect github.com/robfig/cron/v3 v3.0.1 // indirect github.com/sagikazarmark/locafero v0.4.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e // indirect + github.com/shopspring/decimal v1.3.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect github.com/spf13/afero v1.11.0 // indirect github.com/spf13/cast v1.6.0 // indirect @@ -197,6 +220,7 @@ require ( gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/validator.v2 v2.0.1 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect lukechampine.com/uint128 v1.3.0 // indirect modernc.org/cc/v3 v3.41.0 // indirect diff --git a/go.sum b/go.sum index 1938e84..587e2ed 100644 --- a/go.sum +++ b/go.sum @@ -16,6 +16,14 @@ github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzS github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= +github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= +github.com/Masterminds/sprig/v3 v3.2.1/go.mod h1:UoaO7Yp8KlPnJIYWTFkMaqPUYKTfGFPhxNuwnnxkKlk= +github.com/Masterminds/sprig/v3 v3.2.3 h1:eL2fZNezLomi0uOLqjQoN6BfsDD+fyLtgbJMAj9n6YA= +github.com/Masterminds/sprig/v3 v3.2.3/go.mod h1:rXcFaZ2zZbLRJv/xSysmlgIM1u11eBaRMhvYXJNkGuM= github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/Soontao/goHttpDigestClient v0.0.0-20170320082612-6d28bb1415c5 h1:k+1+doEm31k0rRjCjLnGG3YRkuO9ljaEyS2ajZd6GK8= @@ -33,6 +41,9 @@ github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEq github.com/apache/thrift v0.16.0/go.mod h1:PHK3hniurgQaNMZYaCLEqXKsYK8upmhPbmdP2FXSqgU= github.com/apache/thrift v0.18.1 h1:lNhK/1nqjbwbiOPDBPFJVKxgDEGSepKuTh6OLiXW8kg= github.com/apache/thrift v0.18.1/go.mod h1:rdQn/dCcDKEWjjylUeueum4vQEjG2v8v2PqriUnbr+I= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/armon/go-radix v1.0.0 h1:F4z6KzEeeQIMeLFa97iZU6vupzoecKdU5TX24SNppXI= +github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/aws/aws-sdk-go v1.44.289 h1:5CVEjiHFvdiVlKPBzv0rjG4zH/21W/onT18R5AH/qx0= github.com/aws/aws-sdk-go v1.44.289/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI= github.com/benbjohnson/clock v0.0.0-20160125162948-a620c1cc9866/go.mod h1:UMqtWQTnOe4byzwe7Zhwh8f8s+36uszN51sJrSIZlTE= @@ -43,6 +54,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bitly/go-hostpool v0.0.0-20171023180738-a3a6125de932/go.mod h1:NOuUCSz6Q9T7+igc/hlvDOUdtWKryOrtFyIVABv/p7k= github.com/bitly/go-hostpool v0.1.0 h1:XKmsF6k5el6xHG3WPJ8U0Ku/ye7njX7W81Ng7O2ioR0= github.com/bitly/go-hostpool v0.1.0/go.mod h1:4gOCgp6+NZnVqlKyZ/iBZFTAJKembaVENUpMkpg42fw= @@ -89,6 +102,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= +github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= github.com/dgraph-io/badger/v4 v4.2.0 h1:kJrlajbXXL9DFTNuhhu9yCx7JJa4qpYWxtE8BzuWsEs= github.com/dgraph-io/badger/v4 v4.2.0/go.mod h1:qfCqhPoWDFJRx1gp5QwwyGo8xk1lbHUxvK9nK0OGAak= github.com/dgraph-io/ristretto v0.1.1 h1:6CWw5tJNgpegArSHpNHJKldNeq03FQCwYvfMVWajOK8= @@ -121,6 +136,7 @@ github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBF github.com/envoyproxy/protoc-gen-validate v1.0.2/go.mod h1:GpiZQP3dDbg4JouG/NNS7QWXpgx6x8QiMKdmN72jogE= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a h1:yDWHCSQ40h88yih2JAcL6Ls/kVkSE8GFACTGVnMPruw= github.com/facebookgo/clock v0.0.0-20150410010913-600d898af40a/go.mod h1:7Ga40egUymuWXxAe151lTNnCv97MddSOVsjpPPkityA= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= @@ -145,6 +161,8 @@ github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vb github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-logfmt/logfmt v0.6.0 h1:wGYYu3uicYdqXVgoYbvnkrPVXkuLM1p1ifugDMEdRi4= +github.com/go-logfmt/logfmt v0.6.0/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -167,6 +185,10 @@ github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gocql/gocql v1.5.2 h1:WnKf8xRQImcT/KLaEWG2pjEeryDB7K0qQN9mPs1C58Q= github.com/gocql/gocql v1.5.2/go.mod h1:3gM2c4D3AnkISwBxGnMMsS8Oy4y2lhbPRsH4xnJrHG8= +github.com/godror/godror v0.40.4 h1:X1e7hUd02GDaLWKZj40Z7L0CP0W9TrGgmPQZw6+anBg= +github.com/godror/godror v0.40.4/go.mod h1:i8YtVTHUJKfFT3wTat4A9UoqScUtZXiYB9Rf3SVARgc= +github.com/godror/knownpb v0.1.1 h1:A4J7jdx7jWBhJm18NntafzSC//iZDHkDi1+juwQ5pTI= +github.com/godror/knownpb v0.1.1/go.mod h1:4nRFbQo1dDuwKnblRXDxrfCFYeT4hjg3GjMqef58eRE= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= @@ -176,6 +198,8 @@ github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOW github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v5 v5.2.0 h1:d/ix8ftRUorsN+5eMIlF4T6J8CAt9rch3My2winC1Jw= github.com/golang-jwt/jwt/v5 v5.2.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.1.2 h1:DVjP2PbBOzHyzA+dn3WhHIq4NdVu3Q+pvivFICf/7fo= @@ -230,6 +254,7 @@ github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm4 github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -263,11 +288,25 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1 h1:/c3QmbOGMGTOumP2iT/rCwB7b0Q github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.1/go.mod h1:5SN9VR2LTsRFsrEC6FHgRbTWrTHu6tqPeKxEQv15giM= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed h1:5upAirOpQc1Q53c0bnx2ufif5kANL7bfZWcc6VJWJd8= github.com/hailocab/go-hostpool v0.0.0-20160125115350-e80d13ce29ed/go.mod h1:tMWxXQ9wFIaZeTI9F+hmhFiGpFmhOHzyShyFUhRm0H4= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I= +github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo= +github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM= github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.3.3/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= +github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= +github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI= github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= +github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= +github.com/imdario/mergo v0.3.13 h1:lFzP57bqS/wsqKssCGmtLAb8A0wKjLGrve2q3PPVcBk= +github.com/imdario/mergo v0.3.13/go.mod h1:4lJ1jqUDcsbIECGy0RUJAXNIhg+6ocWgb1ALK2O4oXg= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= @@ -325,11 +364,18 @@ github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0V github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +github.com/mattn/go-oci8 v0.1.1 h1:aEUDxNAyDG0tv8CA3TArnDQNyc4EhnWlsfxRgDHABHM= +github.com/mattn/go-oci8 v0.1.1/go.mod h1:wjDx6Xm9q7dFtHJvIlrI99JytznLw5wQ4R+9mNXJwGI= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= +github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.19 h1:fhGleo2h1p8tVChob4I9HpmVFIAkKGpiukdrgQbWfGI= github.com/mattn/go-sqlite3 v1.14.19/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= @@ -338,8 +384,16 @@ github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zk github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mccutchen/go-httpbin v1.1.2-0.20190116014521-c5cb2f4802fa h1:lx8ZnNPwjkXSzOROz0cg69RlErRXs+L3eDkggASWKLo= github.com/mccutchen/go-httpbin v1.1.2-0.20190116014521-c5cb2f4802fa/go.mod h1:fhpOYavp5g2K74XDl/ao2y4KvhqVtKlkg1e+0UaQv7I= +github.com/mitchellh/cli v1.1.5 h1:OxRIeJXpAMztws/XHlN2vu6imG5Dpq+j61AzAX5fLng= +github.com/mitchellh/cli v1.1.5/go.mod h1:v8+iFts2sPIKUV1ltktPXMCC8fumSKFItNcD2cLtRR4= +github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw= +github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= +github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= +github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= @@ -359,6 +413,8 @@ github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d h1:VhgPp6v9qf9Agr/ github.com/nu7hatch/gouuid v0.0.0-20131221200532-179d4d0c4d8d/go.mod h1:YUTz3bUH2ZwIWBy3CJBeOBEugqcmXREj14T+iG/4k4U= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/olivere/elastic/v7 v7.0.32 h1:R7CXvbu8Eq+WlsLgxmKVKPox0oOwAE/2T9Si5BnvK6E= github.com/olivere/elastic/v7 v7.0.32/go.mod h1:c7PVmLe3Fxq77PIfY/bZmxY/TAamBhCzZ8xDOE09a9k= github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= @@ -379,6 +435,9 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo= +github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/poy/onpar v1.1.2 h1:QaNrNiZx0+Nar5dLgTVp5mXkyoVFIbepjyEoGSnhbAY= github.com/poy/onpar v1.1.2/go.mod h1:6X8FLNoxyr9kkmnlqpK6LSoiOtrO6MICtWwEuWkLjzg= github.com/prashantv/protectmem v0.0.0-20171002184600-e20412882b3a h1:AA9vgIBDjMHPC2McaGPojgV2dcI78ZC0TLNhYCXEKH8= @@ -413,6 +472,9 @@ github.com/redis/go-redis/v9 v9.0.5 h1:CuQcn5HIEeK7BgElubPP8CGtE0KakrnbBSTLjathl github.com/redis/go-redis/v9 v9.0.5/go.mod h1:WqMKv5vnQbRuZstUwxQI195wHy+t4PuXDOjzMvcuQHk= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= +github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ= github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= @@ -430,6 +492,9 @@ github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWR github.com/samuel/go-thrift v0.0.0-20190219015601-e8b6b52668fe/go.mod h1:Vrkh1pnjV9Bl8c3P9zH0/D4NlOHWP5d4/hF4YTULaec= github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e h1:zWKUYT07mGmVBH+9UgnHXd/ekCK99C8EbDSAt5qsjXE= github.com/serenize/snaker v0.0.0-20201027110005-a7ad2135616e/go.mod h1:Yow6lPLSAXx2ifx470yD/nUe22Dv5vBvxK/UK9UUTVs= +github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/sirupsen/logrus v1.0.2-0.20170726183946-abee6f9b0679/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= @@ -440,6 +505,7 @@ github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9yS github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= +github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= @@ -455,6 +521,7 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= @@ -565,10 +632,14 @@ go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo= go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200414173820-0848c9571904/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -615,6 +686,7 @@ golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= @@ -665,6 +737,7 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20221010170243-090e33056c14/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -673,6 +746,7 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -787,6 +861,7 @@ gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/internal/handlers/settings.go b/internal/handlers/settings.go index 359774a..48442a0 100644 --- a/internal/handlers/settings.go +++ b/internal/handlers/settings.go @@ -37,15 +37,15 @@ var SettingsPages = []*components.Page{ {Path: "/settings/worker-groups/create", Title: "Worker Groups Create", Breadcrumb: "Create"}, {Path: "/settings/notifications", Title: "Notifications", Breadcrumb: "Notifications"}, {Path: "/settings/notifications/create", Title: "Notifications Create", Breadcrumb: "Create"}, - {Path: "/settings/incidents", Title: "Incidents", Breadcrumb: "Incidents"}, - {Path: "/settings/incidents/create", Title: "Incidents Create", Breadcrumb: "Create"}, + {Path: "/settings/triggers", Title: "Triggers", Breadcrumb: "Triggers"}, + {Path: "/settings/triggers/create", Title: "Triggers Create", Breadcrumb: "Create"}, {Path: "/settings/temporal", Title: "Temporal", Breadcrumb: "Temporal"}, {Path: "/oauth2/logout", Title: "Logout", Breadcrumb: "Logout"}, } var SettingsNavbar = []*components.Page{ GetPageByTitle(SettingsPages, "Overview"), - GetPageByTitle(SettingsPages, "Incidents"), + GetPageByTitle(SettingsPages, "Triggers"), GetPageByTitle(SettingsPages, "Monitors"), GetPageByTitle(SettingsPages, "Notifications"), GetPageByTitle(SettingsPages, "Worker Groups"), diff --git a/internal/handlers/settings_incidents.go b/internal/handlers/settings_incidents.go deleted file mode 100644 index 856b318..0000000 --- a/internal/handlers/settings_incidents.go +++ /dev/null @@ -1,30 +0,0 @@ -package handlers - -import ( - "net/http" - - "code.tjo.space/mentos1386/zdravko/web/templates/components" - "github.com/labstack/echo/v4" -) - -type Incident struct{} - -type SettingsIncidents struct { - *Settings - Incidents []*Incident -} - -func (h *BaseHandler) SettingsIncidentsGET(c echo.Context) error { - cc := c.(AuthenticatedContext) - - incidents := make([]*Incident, 0) - - return c.Render(http.StatusOK, "settings_incidents.tmpl", &SettingsIncidents{ - Settings: NewSettings( - cc.Principal.User, - GetPageByTitle(SettingsPages, "Incidents"), - []*components.Page{GetPageByTitle(SettingsPages, "Incidents")}, - ), - Incidents: incidents, - }) -} diff --git a/internal/handlers/settings_triggers.go b/internal/handlers/settings_triggers.go new file mode 100644 index 0000000..b6fe172 --- /dev/null +++ b/internal/handlers/settings_triggers.go @@ -0,0 +1,234 @@ +package handlers + +import ( + "context" + "fmt" + "net/http" + + "code.tjo.space/mentos1386/zdravko/database/models" + "code.tjo.space/mentos1386/zdravko/internal/services" + "code.tjo.space/mentos1386/zdravko/web/templates/components" + "github.com/go-playground/validator/v10" + "github.com/gosimple/slug" + "github.com/labstack/echo/v4" +) + +type Incident struct{} + +type SettingsIncidents struct { + *Settings + Incidents []*Incident +} + +// FIXME: This should be moved in to a files to not worry about so much escaping. +const exampleTrigger = ` +import kv from 'zdravko/kv'; +import slack from 'zdravko/notify/slack'; + +export default function (monitor, outcome) { + // If the outcome is not failure, we can reset the counter. + if (outcome.status !== 'FAILURE') { + return kv.delete(` + "\\`\\${monitor.name}:issues:5min\\`" + `); + } + + const count = kv.get(` + "\\`\\${monitor.name}:issues:5min\\`" + `) || 0; + + if (count > 5) { + slack.notify(` + "\\`\\${monitor.name} has had more than 5 issues in the last 5 minutes\\`" + `); + } + + // Increment and set TTL to 5 minutes + kv.increment(` + "\\`\\${monitor.name}:issues:5min\\`" + `, count + 1); +} +` + +type CreateTrigger struct { + Name string `validate:"required"` + Script string `validate:"required"` +} + +type UpdateTrigger struct { + Script string `validate:"required"` +} + +type SettingsTriggers struct { + *Settings + Triggers []*models.Trigger +} + +type SettingsTrigger struct { + *Settings + Trigger *models.Trigger + History []*models.TriggerHistory +} + +type SettingsTriggerCreate struct { + *Settings + Example string +} + +func (h *BaseHandler) SettingsTriggersGET(c echo.Context) error { + cc := c.(AuthenticatedContext) + + triggers, err := services.GetTriggers(context.Background(), h.db) + if err != nil { + return err + } + return c.Render(http.StatusOK, "settings_triggers.tmpl", &SettingsTriggers{ + Settings: NewSettings( + cc.Principal.User, + GetPageByTitle(SettingsPages, "Triggers"), + []*components.Page{GetPageByTitle(SettingsPages, "Triggers")}, + ), + Triggers: triggers, + }) +} + +func (h *BaseHandler) SettingsTriggersDescribeGET(c echo.Context) error { + cc := c.(AuthenticatedContext) + + slug := c.Param("id") + + trigger, err := services.GetTrigger(context.Background(), h.db, slug) + if err != nil { + return err + } + + return c.Render(http.StatusOK, "settings_triggers_describe.tmpl", &SettingsTrigger{ + Settings: NewSettings( + cc.Principal.User, + GetPageByTitle(SettingsPages, "Triggers"), + []*components.Page{ + GetPageByTitle(SettingsPages, "Triggers"), + { + Path: fmt.Sprintf("/settings/triggers/%s", slug), + Title: "Describe", + Breadcrumb: trigger.Name, + }, + }), + Trigger: trigger, + }) +} + +func (h *BaseHandler) SettingsTriggersDescribeDELETE(c echo.Context) error { + slug := c.Param("id") + + err := services.DeleteTrigger(context.Background(), h.db, slug) + if err != nil { + return err + } + + return c.Redirect(http.StatusSeeOther, "/settings/triggers") +} + +func (h *BaseHandler) SettingsTriggersDisableGET(c echo.Context) error { + slug := c.Param("id") + + trigger, err := services.GetTrigger(context.Background(), h.db, slug) + if err != nil { + return err + } + + trigger.Status = services.TriggerStatusPaused + err = services.UpdateTrigger(context.Background(), h.db, trigger) + if err != nil { + return err + } + + return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/triggers/%s", slug)) +} + +func (h *BaseHandler) SettingsTriggersEnableGET(c echo.Context) error { + slug := c.Param("id") + + trigger, err := services.GetTrigger(context.Background(), h.db, slug) + if err != nil { + return err + } + + trigger.Status = services.TriggerStatusActive + err = services.UpdateTrigger(context.Background(), h.db, trigger) + if err != nil { + return err + } + + return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/triggers/%s", slug)) +} + +func (h *BaseHandler) SettingsTriggersDescribePOST(c echo.Context) error { + ctx := context.Background() + triggerId := c.Param("id") + + update := UpdateTrigger{ + Script: c.FormValue("script"), + } + err := validator.New(validator.WithRequiredStructEnabled()).Struct(update) + if err != nil { + return err + } + + trigger, err := services.GetTrigger(ctx, h.db, triggerId) + if err != nil { + return err + } + trigger.Script = update.Script + + err = services.UpdateTrigger( + ctx, + h.db, + trigger, + ) + if err != nil { + return err + } + + return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/settings/triggers/%s", triggerId)) +} + +func (h *BaseHandler) SettingsTriggersCreateGET(c echo.Context) error { + cc := c.(AuthenticatedContext) + + return c.Render(http.StatusOK, "settings_triggers_create.tmpl", &SettingsTriggerCreate{ + Settings: NewSettings( + cc.Principal.User, + GetPageByTitle(SettingsPages, "Triggers"), + []*components.Page{ + GetPageByTitle(SettingsPages, "Triggers"), + GetPageByTitle(SettingsPages, "Triggers Create"), + }, + ), + Example: exampleTrigger, + }) +} + +func (h *BaseHandler) SettingsTriggersCreatePOST(c echo.Context) error { + ctx := context.Background() + triggerId := slug.Make(c.FormValue("name")) + + create := CreateTrigger{ + Name: c.FormValue("name"), + Script: c.FormValue("script"), + } + err := validator.New(validator.WithRequiredStructEnabled()).Struct(create) + if err != nil { + return err + } + + trigger := &models.Trigger{ + Name: create.Name, + Id: triggerId, + Script: create.Script, + Status: services.TriggerStatusActive, + } + + err = services.CreateTrigger( + ctx, + h.db, + trigger, + ) + if err != nil { + return err + } + + return c.Redirect(http.StatusSeeOther, "/settings/triggers") +} diff --git a/internal/services/trigger.go b/internal/services/trigger.go new file mode 100644 index 0000000..55e8769 --- /dev/null +++ b/internal/services/trigger.go @@ -0,0 +1,61 @@ +package services + +import ( + "context" + + "code.tjo.space/mentos1386/zdravko/database/models" + "github.com/jmoiron/sqlx" +) + +const ( + TriggerStatusUnknown models.TriggerStatus = "UNKNOWN" + TriggerStatusPaused models.TriggerStatus = "PAUSED" + TriggerStatusActive models.TriggerStatus = "ACTIVE" +) + +func CountTriggers(ctx context.Context, db *sqlx.DB) (int, error) { + var count int + err := db.GetContext(ctx, &count, "SELECT COUNT(*) FROM triggers") + return count, err +} + +func CreateTrigger(ctx context.Context, db *sqlx.DB, trigger *models.Trigger) error { + _, err := db.NamedExecContext(ctx, + `INSERT INTO triggers (id, name, status, script) VALUES (:id, :name, :status, :script)`, + trigger, + ) + return err +} + +func UpdateTrigger(ctx context.Context, db *sqlx.DB, trigger *models.Trigger) error { + _, err := db.NamedExecContext(ctx, + `UPDATE triggers SET script=:script, status=:status WHERE id=:id`, + trigger, + ) + return err +} + +func DeleteTrigger(ctx context.Context, db *sqlx.DB, id string) error { + _, err := db.ExecContext(ctx, + "DELETE FROM triggers WHERE id=$1", + id, + ) + return err +} + +func GetTrigger(ctx context.Context, db *sqlx.DB, id string) (*models.Trigger, error) { + trigger := &models.Trigger{} + err := db.GetContext(ctx, trigger, + "SELECT * FROM triggers WHERE id=$1", + id, + ) + return trigger, err +} + +func GetTriggers(ctx context.Context, db *sqlx.DB) ([]*models.Trigger, error) { + triggers := []*models.Trigger{} + err := db.SelectContext(ctx, &triggers, + "SELECT * FROM triggers ORDER BY name", + ) + return triggers, err +} diff --git a/justfile b/justfile index 8074568..63af5ed 100644 --- a/justfile +++ b/justfile @@ -87,6 +87,21 @@ run-docker: sqlite-web: sqlite_web zdravko.db +# New migration file +migration-new name: + #!/bin/bash + FILENAME="database/sqlite/migrations/`date --iso-8601`_{{name}}.sql" + + cat < $FILENAME + -- +migrate Up + -- SQL in section 'Up' is executed when this migration is applied + + -- +migrate Down + -- SQL in section 'Down' is executed when this migration is rolled back + EOF + + echo "Created migration file: $FILENAME" + # Generate and download all external dependencies. generate: go generate ./... diff --git a/pkg/server/routes.go b/pkg/server/routes.go index 4cb3ce0..31e2ccc 100644 --- a/pkg/server/routes.go +++ b/pkg/server/routes.go @@ -53,8 +53,16 @@ func Routes( settings := e.Group("/settings") settings.Use(h.Authenticated) settings.GET("", h.SettingsOverviewGET) - settings.GET("/incidents", h.SettingsIncidentsGET) - settings.GET("/monitors", h.SettingsMonitorsGET) + + settings.GET("/triggers", h.SettingsTriggersGET) + settings.GET("/triggers/:id", h.SettingsTriggersDescribeGET) + settings.POST("/triggers/:id", h.SettingsTriggersDescribePOST) + settings.GET("/triggers/create", h.SettingsTriggersCreateGET) + settings.POST("/triggers/create", h.SettingsTriggersCreatePOST) + settings.GET("/triggers/:id/delete", h.SettingsTriggersDescribeDELETE) + settings.GET("/triggers/:id/disable", h.SettingsTriggersDisableGET) + settings.GET("/triggers/:id/enable", h.SettingsTriggersEnableGET) + settings.GET("/monitors/create", h.SettingsMonitorsCreateGET) settings.POST("/monitors/create", h.SettingsMonitorsCreatePOST) settings.GET("/monitors/:id", h.SettingsMonitorsDescribeGET) @@ -62,7 +70,9 @@ func Routes( settings.GET("/monitors/:id/delete", h.SettingsMonitorsDescribeDELETE) settings.GET("/monitors/:id/disable", h.SettingsMonitorsDisableGET) settings.GET("/monitors/:id/enable", h.SettingsMonitorsEnableGET) + settings.GET("/notifications", h.SettingsNotificationsGET) + settings.GET("/worker-groups", h.SettingsWorkerGroupsGET) settings.GET("/worker-groups/create", h.SettingsWorkerGroupsCreateGET) settings.POST("/worker-groups/create", h.SettingsWorkerGroupsCreatePOST) diff --git a/web/templates/pages/settings_incidents.tmpl b/web/templates/pages/settings_triggers.tmpl similarity index 70% rename from web/templates/pages/settings_incidents.tmpl rename to web/templates/pages/settings_triggers.tmpl index df62818..05f12e0 100644 --- a/web/templates/pages/settings_incidents.tmpl +++ b/web/templates/pages/settings_triggers.tmpl @@ -1,13 +1,13 @@ {{ define "settings" }} - {{ $description := "Incidents can be manually created or based on monitors. They are used to notify about issues." }} + {{ $description := "Triggers can be manually created or based on monitors. They are used to notify about issues." }} - {{ $length := len .Incidents }} + {{ $length := len .Triggers }} {{ if eq $length 0 }}

- There are no incidents yet. + There are no triggers yet.

- Create First Incident + Create First Trigger @@ -32,13 +32,13 @@

- - {{ range .Incidents }} + {{ range .Triggers }} - diff --git a/web/templates/pages/settings_triggers_create.tmpl b/web/templates/pages/settings_triggers_create.tmpl new file mode 100644 index 0000000..957e178 --- /dev/null +++ b/web/templates/pages/settings_triggers_create.tmpl @@ -0,0 +1,55 @@ +{{ define "settings" }} +
+
+ + +

Name of the trigger can be anything.

+ + + +

+ Script is what determines the status of a service. You can read more + about it on + k6 documentation. +

+ + +
+ + + +{{ end }} diff --git a/web/templates/pages/settings_triggers_describe.tmpl b/web/templates/pages/settings_triggers_describe.tmpl new file mode 100644 index 0000000..8dd6306 --- /dev/null +++ b/web/templates/pages/settings_triggers_describe.tmpl @@ -0,0 +1,142 @@ +{{ define "settings" }} +
+
+

Configuration

+ + + +

+ Script is what determines the status of a service. You can read more + about it on + k6 documentation. +

+ + +
+ +
+
+

+ Status + {{ if eq .Trigger.Status "ACTIVE" }} + + ACTIVE + + {{ else if eq .Trigger.Status "PAUSED" }} + + PAUSED + + {{ end }} +

+

+ Pausing the trigger will stop it from executing. This can be useful in + cases of expected downtime. Or when the trigger is not needed anymore. +

+ {{ if eq .Trigger.Status "ACTIVE" }} + Pause + {{ else if eq .Trigger.Status "PAUSED" }} + Resume + {{ end }} +
+ +
+

Danger Zone

+

Permanently delete this trigger.

+ Delete +
+
+ +
+
- List of Incidents + List of Triggers
NameNotifications Action
{{ .Name }} - {{ range .Notifications }} - - {{ . }} - - {{ end }} - - Details + Details
+ + + + + + + + + + + {{ range .History }} + + + + + + + {{ end }} + +
+ History +

Last 10 executions of trigger script.

+
StatusCreated AtDurationNote
+ + {{ .Status }} + + + {{ .CreatedAt.Time.Format "2006-01-02 15:04:05" }} + { .Duration } + {{ .Note }} +
+
+ + + +{{ end }} diff --git a/web/templates/tempaltes.go b/web/templates/tempaltes.go index ca3ea82..fb3738a 100644 --- a/web/templates/tempaltes.go +++ b/web/templates/tempaltes.go @@ -44,7 +44,9 @@ func NewTemplates() *Templates { "index.tmpl": load("pages/index.tmpl"), "incidents.tmpl": load("pages/incidents.tmpl"), "settings_overview.tmpl": loadSettings("pages/settings_overview.tmpl"), - "settings_incidents.tmpl": loadSettings("pages/settings_incidents.tmpl"), + "settings_triggers.tmpl": loadSettings("pages/settings_triggers.tmpl"), + "settings_triggers_create.tmpl": loadSettings("pages/settings_triggers_create.tmpl"), + "settings_triggers_describe.tmpl": loadSettings("pages/settings_triggers_describe.tmpl"), "settings_notifications.tmpl": loadSettings("pages/settings_notifications.tmpl"), "settings_worker_groups.tmpl": loadSettings("pages/settings_worker_groups.tmpl"), "settings_worker_groups_create.tmpl": loadSettings("pages/settings_worker_groups_create.tmpl"),