Update template

Signed-off-by: AKP <tom@tdpain.net>
This commit is contained in:
akp 2022-10-02 20:44:17 +01:00
parent 7bcc5ed359
commit d78975a540
No known key found for this signature in database
GPG key ID: AA5726202C8879B7
14 changed files with 246 additions and 139 deletions

View file

@ -2,20 +2,33 @@ package config
import (
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"github.com/rs/zerolog/pkgerrors"
)
func InitLogging() {
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
zerolog.ErrorStackMarshaler = pkgerrors.MarshalStack
log.Logger = log.Logger.With().Stack().Logger()
}
var Debug = struct {
Enabled bool
}{
Enabled: asBool(get("debug.enable")),
}
var HTTP = struct {
Host string
Port int
Secure bool
Host string
Port int
}{
Host: asString(withDefault(fetchFromFile("http.host"), "0.0.0.0")),
Port: asInt(withDefault(fetchFromFile("http.port"), 8080)),
Secure: asBool(required(fetchFromFile("http.secure"))),
Host: asString(withDefault("http.host", "0.0.0.0")),
Port: asInt(withDefault("http.port", 8080)),
}
var Database = struct {
Filename string
}{
Filename: asString(withDefault("db.filename", "database.db")),
}

View file

@ -1,9 +1,10 @@
package config
import (
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"gopkg.in/yaml.v3"
"io/ioutil"
"os"
"regexp"
"strconv"
"strings"
@ -16,19 +17,31 @@ var (
lastKey string
)
func loadConfigFileFromDisk() {
func mustLoadConfigFile() {
if err := loadConfigFile(); err != nil {
log.Fatal().Err(err).Send()
}
}
func loadConfigFile() error {
if rawConfigFileContents != nil {
return
return nil
}
fcont, err := ioutil.ReadFile(configFileName)
fcont, err := os.ReadFile(configFileName)
if err != nil {
log.Fatal().Err(err).Msgf("failed to load file %s", configFileName)
return errors.Wrap(err, "failed to load config file")
}
rawConfigFileContents = make(map[string]any)
if err := yaml.Unmarshal(fcont, &rawConfigFileContents); err != nil {
log.Fatal().Err(err).Msg("could not unmarshal config file")
return errors.Wrap(err, "could not unmarshal config file")
}
return nil
}
func Reload() error {
return loadConfigFile()
}
type optionalItem struct {
@ -38,9 +51,9 @@ type optionalItem struct {
var indexedPartRegexp = regexp.MustCompile(`(?m)([a-zA-Z]+)(?:\[(\d+)\])?`)
func fetchFromFile(key string) optionalItem {
func get(key string) optionalItem {
// http[2].bananas
loadConfigFileFromDisk()
mustLoadConfigFile()
lastKey = key
parts := strings.Split(key, ".")
@ -59,7 +72,7 @@ func fetchFromFile(key string) optionalItem {
if isIndexed {
arr, conversionOk := item.([]any)
if !conversionOk {
log.Fatal().Msgf("attempted to index non-indexable item %s", key)
log.Fatal().Msgf("attempted to index non-indexable config item %s", key)
}
cursor = arr[index]
} else {
@ -70,15 +83,15 @@ func fetchFromFile(key string) optionalItem {
}
func required(key string) optionalItem {
opt := fetchFromFile(key)
opt := get(key)
if !opt.found {
log.Fatal().Msgf("required key %s not found", lastKey)
log.Fatal().Msgf("required key %s not found in config file", lastKey)
}
return opt
}
func withDefault(key string, defaultValue any) optionalItem {
opt := fetchFromFile(key)
opt := get(key)
if !opt.found {
return optionalItem{item: defaultValue, found: true}
}

View file

@ -3,69 +3,46 @@ package db
import (
"context"
"database/sql"
"github.com/codemicro/go-fiber-sql/application/config"
_ "github.com/mattn/go-sqlite3"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"math"
"net"
"github.com/uptrace/bun"
"github.com/uptrace/bun/dialect/sqlitedialect"
"github.com/uptrace/bun/extra/bundebug"
"time"
)
type DB struct {
pool *sql.DB
bun *bun.DB
ContextTimeout time.Duration
}
const maxConnectionAttempts = 4
func New() (*DB, error) {
// TODO: Setup DSN and database driver
dsn := ""
dsn := config.Database.Filename
log.Info().Msg("connecting to database")
db, err := sql.Open("postgres", dsn) // TODO: This
db, err := sql.Open("sqlite3", dsn)
if err != nil {
return nil, errors.Wrap(err, "could not open SQL connection")
}
db.SetMaxOpenConns(1) // https://github.com/mattn/go-sqlite3/issues/274#issuecomment-191597862
bundb := bun.NewDB(db, sqlitedialect.New())
bundb.AddQueryHook(bundebug.NewQueryHook(
bundebug.WithEnabled(config.Debug.Enabled),
))
rtn := &DB{
pool: db,
bun: bundb,
ContextTimeout: time.Second,
}
for i := 1; i <= maxConnectionAttempts; i += 1 {
logger := log.With().Int("attempt", i).Int("maxAttempts", maxConnectionAttempts).Logger()
ctx, cancel := context.WithTimeout(context.Background(), time.Second)
err := rtn.pool.PingContext(ctx)
if err == nil {
cancel()
break
}
if e, ok := err.(*net.OpError); ((ok && e.Op == "dial") || errors.Is(err, context.DeadlineExceeded)) && i != maxConnectionAttempts {
cancel()
retryIn := int(math.Pow(math.E, float64(i)))
logger.Warn().Err(err).Msgf("could not connect to database - retrying in %d seconds", retryIn)
time.Sleep(time.Second * time.Duration(retryIn))
continue
}
cancel()
return nil, errors.Wrapf(err, "could not ping database after %d attempts", i)
}
return rtn, nil
}
func (db *DB) newContext() (context.Context, func()) {
return context.WithTimeout(context.Background(), db.ContextTimeout)
}
func smartRollback(tx *sql.Tx) {
err := tx.Rollback()
if err != nil && !errors.Is(err, sql.ErrTxDone) {
log.Warn().Stack().Err(errors.WithStack(err)).Str("location", "smartRollback").Msg("failed to rollback transaction")
}
}

View file

@ -1,79 +1,41 @@
package db
import (
"database/sql"
"context"
_ "embed"
"github.com/codemicro/go-fiber-sql/application/db/migrations"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"github.com/uptrace/bun/migrate"
"time"
)
var migrationFunctions = []func(trans *sql.Tx) error{
migrate0to1,
}
func (db *DB) Migrate() error {
log.Info().Msg("running migrations")
// list tables
tx, err := db.pool.Begin()
if err != nil {
return errors.WithMessage(err, "could not begin transaction")
}
defer smartRollback(tx)
rows, err := db.pool.Query(`SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = 'public';`)
migs, err := migrations.GetMigrations()
if err != nil {
return errors.WithStack(err)
}
defer rows.Close()
existingTables := make(map[string]struct{})
for rows.Next() {
var tableName string
if err := rows.Scan(&tableName); err != nil {
return errors.WithStack(err)
}
existingTables[tableName] = struct{}{}
mig := migrate.NewMigrator(db.bun, migs)
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
if err := mig.Init(ctx); err != nil {
return errors.WithStack(err)
}
var databaseVersion int
if _, found := existingTables["version"]; found {
err := db.pool.QueryRow(`SELECT "version" FROM "version";`).Scan(&databaseVersion)
if err != nil && !errors.Is(err, sql.ErrNoRows) {
return errors.WithStack(err)
}
}
if x := len(migrationFunctions); databaseVersion == x {
log.Info().Msg("migrations up-to-date without any changes")
return nil
} else if databaseVersion > x {
return errors.New("corrupt database: database version too high")
}
for _, f := range migrationFunctions[databaseVersion:] {
if err := f(tx); err != nil {
return errors.WithStack(err)
}
}
log.Info().Msg("committing migrations")
return errors.WithStack(
tx.Commit(),
)
}
//go:embed migrations/0to1.sql
var migrate0to1SQL string
func migrate0to1(trans *sql.Tx) error {
log.Info().Msg("migrating new database to v1")
_, err := trans.Exec(migrate0to1SQL)
group, err := mig.Migrate(ctx)
if err != nil {
return errors.Wrap(err, "failed to migrate database version from v0 to v1")
return errors.WithStack(err)
}
if group.IsZero() {
log.Info().Msg("database up to date")
} else {
log.Info().Msg("migrations applied")
}
return nil

View file

@ -1,9 +0,0 @@
-- Migrate a new database to v1 format.
CREATE TABLE "version"
(
version INT
);
INSERT INTO "version"(version)
VALUES (1);

View file

@ -0,0 +1,37 @@
package migrations
import (
"context"
"github.com/codemicro/go-fiber-sql/application/db/models"
"github.com/pkg/errors"
"github.com/uptrace/bun"
)
func init() {
tps := []any{
(*models.User)(nil),
}
mig.MustRegister(func(ctx context.Context, db *bun.DB) error {
logger.Debug().Msg("1 up")
for _, t := range tps {
if _, err := db.NewCreateTable().Model(t).Exec(ctx); err != nil {
return errors.WithStack(err)
}
}
return nil
},
func(ctx context.Context, db *bun.DB) error {
logger.Debug().Msg("1 down")
for _, t := range tps {
if _, err := db.NewDropTable().Model(t).Exec(ctx); err != nil {
return errors.WithStack(err)
}
}
return nil
})
}

View file

@ -0,0 +1,20 @@
package migrations
import (
"github.com/rs/zerolog/log"
"github.com/uptrace/bun/migrate"
)
// //go:embed *.sql
// var files embed.FS
var mig = migrate.NewMigrations()
var logger = log.Logger.With().Str("location", "migrations").Logger()
func GetMigrations() (*migrate.Migrations, error) {
// if err := mig.Discover(files); err != nil {
// return nil, errors.WithStack(err)
// }
return mig, nil
}

View file

@ -0,0 +1,13 @@
package models
import (
"github.com/google/uuid"
"github.com/uptrace/bun"
)
type User struct {
bun.BaseModel `bun:"table:users"`
ID uuid.UUID `bun:"id,pk,type:varchar"`
EmailAddress string `bun:"email_address,notnull"`
}

View file

@ -1,10 +1,12 @@
package endpoints
import (
"github.com/codemicro/go-fiber-sql/application/config"
"github.com/codemicro/go-fiber-sql/application/db"
"github.com/codemicro/go-fiber-sql/application/urls"
"github.com/codemicro/go-fiber-sql/application/paths"
"github.com/codemicro/go-fiber-sql/application/util"
"github.com/gofiber/fiber/v2"
"time"
)
type Endpoints struct {
@ -19,10 +21,14 @@ func New(dbi *db.DB) *Endpoints {
func (e *Endpoints) SetupApp() *fiber.App {
app := fiber.New(fiber.Config{
ErrorHandler: util.JSONErrorHandler,
ErrorHandler: util.JSONErrorHandler,
DisableStartupMessage: !config.Debug.Enabled,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
})
app.Get(urls.Index, e.Index)
app.Get(paths.Index, e.Index)
return app
}

View file

@ -7,7 +7,10 @@ import (
"github.com/codemicro/go-fiber-sql/application/endpoints"
"github.com/pkg/errors"
"github.com/rs/zerolog/log"
"os"
"os/signal"
"strconv"
"syscall"
)
func run() error {
@ -25,12 +28,23 @@ func run() error {
serveAddr := config.HTTP.Host + ":" + strconv.Itoa(config.HTTP.Port)
go func() {
shutdownNotifier := make(chan os.Signal, 1)
signal.Notify(shutdownNotifier, syscall.SIGINT)
<-shutdownNotifier
if err := app.Shutdown(); err != nil {
log.Error().Err(err).Msg("failed to shutdown server on SIGINT")
log.Fatal().Msg("terminating")
}
}()
log.Info().Msgf("starting server on %s", serveAddr)
if err := app.Listen(serveAddr); err != nil {
return errors.Wrap(err, "fiber server run failed")
}
log.Info().Msg("shutting down...")
return nil
}
@ -38,6 +52,6 @@ func main() {
config.InitLogging()
if err := run(); err != nil {
fmt.Printf("%+v\n", err)
log.Error().Stack().Err(err).Msg("failed to run coordinator")
log.Error().Stack().Err(err).Msg("failed to run")
}
}

View file

@ -0,0 +1,20 @@
package paths
import (
"fmt"
"strings"
)
const (
Index = "/"
)
func Make(path string, replacements ...any) string {
x := strings.Split(path, "/")
for i, p := range x {
if strings.HasPrefix(p, ":") {
x[i] = "%s"
}
}
return fmt.Sprintf(strings.Join(x, "/"), replacements...)
}

View file

@ -1,5 +0,0 @@
package urls
const (
Index = "/"
)

16
go.mod
View file

@ -4,18 +4,28 @@ go 1.18
require (
github.com/gofiber/fiber/v2 v2.35.0
github.com/google/uuid v1.3.0
github.com/mattn/go-sqlite3 v1.14.15
github.com/pkg/errors v0.9.1
github.com/rs/zerolog v1.27.0
github.com/uptrace/bun v1.1.8
github.com/uptrace/bun/dialect/sqlitedialect v1.1.8
github.com/uptrace/bun/extra/bundebug v1.1.8
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/fatih/color v1.13.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/klauspost/compress v1.15.0 // indirect
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mattn/go-isatty v0.0.14 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.38.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect
github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 // indirect
)

42
go.sum
View file

@ -1,37 +1,72 @@
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/coreos/go-systemd/v22 v22.3.3-0.20220203105225-a9a7ef127534/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.35.0 h1:ct+jKw8Qb24WEIZx3VV3zz9VXyBZL7mcEjNaqj3g0h0=
github.com/gofiber/fiber/v2 v2.35.0/go.mod h1:tgCr+lierLwLoVHHO/jn3Niannv34WRkQETU8wiL9fQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
github.com/rs/zerolog v1.27.0 h1:1T7qCieN22GVc8S4Q2yuexzBb1EqjbgjSH9RohbMjKs=
github.com/rs/zerolog v1.27.0/go.mod h1:7frBqO0oezxmnO7GF86FY++uy8I0Tk/If5ni1G9Qc0U=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc h1:9lRDQMhESg+zvGYmW5DyG0UqvY96Bu5QYsTLvCHdrgo=
github.com/tmthrgd/go-hex v0.0.0-20190904060850-447a3041c3bc/go.mod h1:bciPuU6GHm1iF1pBvUfxfsH0Wmnc2VbpgvbI9ZWuIRs=
github.com/uptrace/bun v1.1.8 h1:slxuaP4LYWFbPRUmTtQhfJN+6eX/6ar2HDKYTcI50SA=
github.com/uptrace/bun v1.1.8/go.mod h1:iT89ESdV3uMupD9ixt6Khidht+BK0STabK/LeZE+B84=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.8 h1:IJ6qBLjeON21tpgmZF/V/k/oHdzAql5UrnaqMCksTlY=
github.com/uptrace/bun/dialect/sqlitedialect v1.1.8/go.mod h1:IZF76cHEf8eeGA29OpkYyPYDs4l/iSMTYRyuFRqeXdY=
github.com/uptrace/bun/extra/bundebug v1.1.8 h1:RrZNOYYFb690k14nCN0t/hokfpsgoppT55/Xk/ijvBA=
github.com/uptrace/bun/extra/bundebug v1.1.8/go.mod h1:AXl9cPt1j3Yyu+a681xTlDyWoIBL1iSjTjr2SAU5oUY=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.38.0 h1:yTjSSNjuDi2PPvXY2836bIwLmiTS2T4T9p1coQshpco=
github.com/valyala/fasthttp v1.38.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU=
github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc=
github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g=
github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
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/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -39,5 +74,6 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
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/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=