Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor to use the new flags system in script #70

Merged
merged 1 commit into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ module github.com/cilium/statedb
go 1.23

require (
github.com/cilium/hive v0.0.0-20241025140746-d66ad09f4384
github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3
github.com/cilium/stream v0.0.0-20240209152734-a0792b51812d
github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de
github.com/spf13/cobra v1.8.0
Expand Down
8 changes: 4 additions & 4 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
github.com/cilium/hive v0.0.0-20241011093954-8df06c41a157 h1:8UuDJ7JPPoCaDfZ/WkU/aP3FtNCwdNQe+7fbzP+lZrk=
github.com/cilium/hive v0.0.0-20241011093954-8df06c41a157/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
github.com/cilium/hive v0.0.0-20241025140746-d66ad09f4384 h1:MAkG2lk4v0Z8J2X4+fFnhuCEsIJGPdCCrWzL41S2Z/I=
github.com/cilium/hive v0.0.0-20241025140746-d66ad09f4384/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
github.com/cilium/hive v0.0.0-20241213101835-553aca42f74a h1:KuDVdRWFhuntkXMuXBraKvsJ4o6HuPf3iF2hETefRtE=
github.com/cilium/hive v0.0.0-20241213101835-553aca42f74a/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3 h1:RfmUH1ouzj0LzORYJRhp43e1rlGpx6GNv4NIRUakU2w=
github.com/cilium/hive v0.0.0-20241213121623-605c1412b9b3/go.mod h1:pI2GJ1n3SLKIQVFrKF7W6A6gb6BQkZ+3Hp4PAEo5SuI=
github.com/cilium/stream v0.0.0-20240209152734-a0792b51812d h1:p6MgATaKEB9o7iAsk9rlzXNDMNCeKPAkx4Y8f+Zq8X8=
github.com/cilium/stream v0.0.0-20240209152734-a0792b51812d/go.mod h1:3VLiLgs8wfjirkuYqos4t0IBPQ+sXtf3tFkChLm6ARM=
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
Expand Down
10 changes: 5 additions & 5 deletions reconciler/testdata/batching.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,11 @@ health 'job-reconcile.*level=OK.*message=OK, 0 object'

# Check metrics
expvar
! grep 'reconciliation_count.test: 0$'
grep 'reconciliation_current_errors.test: 0$'
! grep 'reconciliation_total_errors.test: 0$'
! grep 'reconciliation_duration.test/update: 0$'
! grep 'reconciliation_duration.test/delete: 0$'
! stdout 'reconciliation_count.test: 0$'
stdout 'reconciliation_current_errors.test: 0$'
! stdout 'reconciliation_total_errors.test: 0$'
! stdout 'reconciliation_duration.test/update: 0$'
! stdout 'reconciliation_duration.test/delete: 0$'

# ------------

Expand Down
10 changes: 5 additions & 5 deletions reconciler/testdata/incremental.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -48,11 +48,11 @@ health 'job-reconcile.*level=OK.*message=OK, 0 object'

# Check metrics
expvar
! grep 'reconciliation_count.test: 0$'
grep 'reconciliation_current_errors.test: 0$'
! grep 'reconciliation_total_errors.test: 0$'
! grep 'reconciliation_duration.test/update: 0$'
! grep 'reconciliation_duration.test/delete: 0$'
! stdout 'reconciliation_count.test: 0$'
stdout 'reconciliation_current_errors.test: 0$'
! stdout 'reconciliation_total_errors.test: 0$'
! stdout 'reconciliation_duration.test/update: 0$'
! stdout 'reconciliation_duration.test/delete: 0$'

# ------------

Expand Down
24 changes: 12 additions & 12 deletions reconciler/testdata/pruning.txtar
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,23 @@ mark-init
expect-ops prune(n=2)
health 'job-reconcile.*level=OK'
expvar
! grep 'prune_count.test: 0'
! stdout 'prune_count.test: 0'

# Pruning with faulty ops will mark status as degraded
set-faulty true
prune
expect-ops 'prune(n=2) fail'
health 'job-reconcile.*level=Degraded.*message=.*prune fail'
expvar
grep 'prune_current_errors.test: 1'
stdout 'prune_current_errors.test: 1'

# Pruning again with healthy ops fixes the status.
set-faulty false
prune
expect-ops 'prune(n=2)'
health 'job-reconcile.*level=OK'
expvar
grep 'prune_current_errors.test: 0'
stdout 'prune_current_errors.test: 0'

# Delete an object and check pruning happens without it
db/delete test-objects obj1.yaml
Expand All @@ -44,15 +44,15 @@ expect-ops prune(n=0) delete(2) prune(n=1)

# Check metrics
expvar
! grep 'prune_count.test: 0'
grep 'prune_current_errors.test: 0'
grep 'prune_total_errors.test: 1'
! grep 'prune_duration.test: 0$'
! grep 'reconciliation_count.test: 0$'
grep 'reconciliation_current_errors.test: 0$'
grep 'reconciliation_total_errors.test: 0$'
! grep 'reconciliation_duration.test/update: 0$'
! grep 'reconciliation_duration.test/delete: 0$'
! stdout 'prune_count.test: 0'
stdout 'prune_current_errors.test: 0'
stdout 'prune_total_errors.test: 1'
! stdout 'prune_duration.test: 0$'
! stdout 'reconciliation_count.test: 0$'
stdout 'reconciliation_current_errors.test: 0$'
stdout 'reconciliation_total_errors.test: 0$'
! stdout 'reconciliation_duration.test/update: 0$'
! stdout 'reconciliation_duration.test/delete: 0$'

-- obj1.yaml --
id: 1
Expand Down
144 changes: 80 additions & 64 deletions script.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ package statedb
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io"
"iter"
Expand All @@ -19,6 +18,7 @@ import (
"github.com/cilium/hive"
"github.com/cilium/hive/script"
"github.com/liggitt/tabwriter"
"github.com/spf13/pflag"
"golang.org/x/time/rate"
"gopkg.in/yaml.v3"
)
Expand Down Expand Up @@ -90,17 +90,14 @@ func DBCmd(db *DB) script.Cmd {
)
}

func newCmdFlagSet(w io.Writer) *flag.FlagSet {
fs := flag.NewFlagSet("", flag.ContinueOnError)
fs.SetOutput(w)
return fs
}

func InitializedCmd(db *DB) script.Cmd {
return script.Command(
script.CmdUsage{
Summary: "Wait until all or specific tables have been initialized",
Args: "[-timeout=<duration>] table...",
Args: "table...",
Flags: func(fs *pflag.FlagSet) {
fs.Duration("timeout", 5*time.Second, "Maximum amount of time to wait for the table contents to match")
},
Detail: []string{
"Waits until all or specific tables have been marked",
"initialized. The default timeout is 5 seconds.",
Expand All @@ -111,15 +108,13 @@ func InitializedCmd(db *DB) script.Cmd {
},
},
func(s *script.State, args ...string) (script.WaitFunc, error) {
flags := newCmdFlagSet(s.LogWriter())
timeout := flags.Duration("timeout", 5*time.Second, "Maximum amount of time to wait for the table contents to match")
if err := flags.Parse(args); err != nil {
return nil, fmt.Errorf("%w: %w", script.ErrUsage, err)
timeout, err := s.Flags.GetDuration("timeout")
if err != nil {
return nil, err
}
args = flags.Args()

txn := db.ReadTxn()
timeoutChan := time.After(*timeout)
timeoutChan := time.After(timeout)
allTbls := db.GetTables(txn)
tbls := allTbls

Expand Down Expand Up @@ -166,7 +161,12 @@ func ShowCmd(db *DB) script.Cmd {
return script.Command(
script.CmdUsage{
Summary: "Show the contents of a table",
Args: "[-o=<file>] [-columns=col1,...] [-format={table,yaml,json}] table",
Args: "table",
Flags: func(fs *pflag.FlagSet) {
fs.StringP("out", "o", "", "File to write to instead of stdout")
fs.StringSlice("columns", nil, "Columns to write")
fs.StringP("format", "f", "table", "Format to write in (table, yaml or json)")
},
Detail: []string{
"Show the contents of a table.",
"",
Expand All @@ -182,33 +182,32 @@ func ShowCmd(db *DB) script.Cmd {
},
},
func(s *script.State, args ...string) (script.WaitFunc, error) {
flags := newCmdFlagSet(s.LogWriter())
file := flags.String("o", "", "File to write to instead of stdout")
columns := flags.String("columns", "", "Comma-separated list of columns to write")
format := flags.String("format", "table", "Format to write in (table, yaml, json)")
if err := flags.Parse(args); err != nil {
return nil, fmt.Errorf("%w: %w", script.ErrUsage, err)
file, err := s.Flags.GetString("out")
if err != nil {
return nil, err
}

var cols []string
if len(*columns) > 0 {
cols = strings.Split(*columns, ",")
columns, err := s.Flags.GetStringSlice("columns")
if err != nil {
return nil, err
}
format, err := s.Flags.GetString("format")
if err != nil {
return nil, err
}

args = flags.Args()
if len(args) < 1 {
return nil, fmt.Errorf("missing table name")
}
tableName := args[0]
return func(*script.State) (stdout, stderr string, err error) {
var buf strings.Builder
var w io.Writer
if *file == "" {
if file == "" {
w = &buf
} else {
f, err := os.OpenFile(s.Path(*file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
f, err := os.OpenFile(s.Path(file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return "", "", fmt.Errorf("OpenFile(%s): %w", *file, err)
return "", "", fmt.Errorf("OpenFile(%s): %w", file, err)
}
defer f.Close()
w = f
Expand All @@ -217,7 +216,7 @@ func ShowCmd(db *DB) script.Cmd {
if err != nil {
return "", "", err
}
err = writeObjects(tbl, tbl.All(txn), w, cols, *format)
err = writeObjects(tbl, tbl.All(txn), w, columns, format)
return buf.String(), "", err
}, nil
})
Expand All @@ -227,7 +226,11 @@ func CompareCmd(db *DB) script.Cmd {
return script.Command(
script.CmdUsage{
Summary: "Compare table",
Args: "[-timeout=<dur>] [-grep=<pattern>] table file",
Args: "table file",
Flags: func(fs *pflag.FlagSet) {
fs.Duration("timeout", 5*time.Second, "Maximum amount of time to wait for the table contents to match")
fs.String("grep", "", "Grep the result rows and only compare matching ones")
},
Detail: []string{
"Compare the contents of a table against a file.",
"The comparison is retried until a timeout (1s default).",
Expand All @@ -243,21 +246,22 @@ func CompareCmd(db *DB) script.Cmd {
},
},
func(s *script.State, args ...string) (script.WaitFunc, error) {
flags := newCmdFlagSet(s.LogWriter())
timeout := flags.Duration("timeout", time.Second, "Maximum amount of time to wait for the table contents to match")
grep := flags.String("grep", "", "Grep the result rows and only compare matching ones")
err := flags.Parse(args)
timeout, err := s.Flags.GetDuration("timeout")
if err != nil {
return nil, err
}
grep, err := s.Flags.GetString("grep")
if err != nil {
return nil, fmt.Errorf("%w: %w", script.ErrUsage, err)
return nil, err
}
args = flags.Args()

if len(args) != 2 {
return nil, fmt.Errorf("expected table and filename")
}

var grepRe *regexp.Regexp
if *grep != "" {
grepRe, err = regexp.Compile(*grep)
if grep != "" {
grepRe, err = regexp.Compile(grep)
if err != nil {
return nil, fmt.Errorf("bad grep: %w", err)
}
Expand Down Expand Up @@ -292,7 +296,7 @@ func CompareCmd(db *DB) script.Cmd {
}
lines = lines[1:]
origLines := lines
timeoutChan := time.After(*timeout)
timeoutChan := time.After(timeout)

for {
lines = origLines
Expand Down Expand Up @@ -485,8 +489,15 @@ func queryCmd(db *DB, query int, summary string, detail []string) script.Cmd {
return script.Command(
script.CmdUsage{
Summary: summary,
Args: "[-o=<file>] [-columns=col1,...] [-format={table*,yaml,json}] [-index=<index>] table key",
Detail: detail,
Args: "table key",
Flags: func(fs *pflag.FlagSet) {
fs.StringP("out", "o", "", "File to write to instead of stdout")
fs.StringSlice("columns", nil, "Columns to write")
fs.StringP("format", "f", "table", "Format to write in (table, yaml or json)")
fs.StringP("index", "i", "", "Index to query")
fs.Bool("delete", false, "Delete all matching objects")
},
Detail: detail,
},
func(s *script.State, args ...string) (script.WaitFunc, error) {
return runQueryCmd(query, db, s, args)
Expand All @@ -495,22 +506,27 @@ func queryCmd(db *DB, query int, summary string, detail []string) script.Cmd {
}

func runQueryCmd(query int, db *DB, s *script.State, args []string) (script.WaitFunc, error) {
flags := newCmdFlagSet(s.LogWriter())
file := flags.String("o", "", "File to write results to instead of stdout")
index := flags.String("index", "", "Index to query")
format := flags.String("format", "table", "Format to write in (table, yaml, json)")
columns := flags.String("columns", "", "Comma-separated list of columns to write")
delete := flags.Bool("delete", false, "Delete all matching objects")
if err := flags.Parse(args); err != nil {
return nil, fmt.Errorf("%w: %w", script.ErrUsage, err)
file, err := s.Flags.GetString("out")
if err != nil {
return nil, err
}

var cols []string
if len(*columns) > 0 {
cols = strings.Split(*columns, ",")
columns, err := s.Flags.GetStringSlice("columns")
if err != nil {
return nil, err
}
format, err := s.Flags.GetString("format")
if err != nil {
return nil, err
}
index, err := s.Flags.GetString("index")
if err != nil {
return nil, err
}
delete, err := s.Flags.GetBool("delete")
if err != nil {
return nil, err
}

args = flags.Args()
if len(args) < 2 {
return nil, fmt.Errorf("expected table and key")
}
Expand All @@ -523,12 +539,12 @@ func runQueryCmd(query int, db *DB, s *script.State, args []string) (script.Wait

var buf strings.Builder
var w io.Writer
if *file == "" {
if file == "" {
w = &buf
} else {
f, err := os.OpenFile(s.Path(*file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
f, err := os.OpenFile(s.Path(file), os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return "", "", fmt.Errorf("OpenFile(%s): %s", *file, err)
return "", "", fmt.Errorf("OpenFile(%s): %s", file, err)
}
defer f.Close()
w = f
Expand All @@ -537,13 +553,13 @@ func runQueryCmd(query int, db *DB, s *script.State, args []string) (script.Wait
var it iter.Seq2[any, uint64]
switch query {
case queryCmdList:
it, err = tbl.List(txn, *index, args[1])
it, err = tbl.List(txn, index, args[1])
case queryCmdLowerBound:
it, err = tbl.LowerBound(txn, *index, args[1])
it, err = tbl.LowerBound(txn, index, args[1])
case queryCmdPrefix:
it, err = tbl.Prefix(txn, *index, args[1])
it, err = tbl.Prefix(txn, index, args[1])
case queryCmdGet:
it, err = tbl.List(txn, *index, args[1])
it, err = tbl.List(txn, index, args[1])
if err == nil {
it = firstOfSeq2(it)
}
Expand All @@ -554,12 +570,12 @@ func runQueryCmd(query int, db *DB, s *script.State, args []string) (script.Wait
return "", "", fmt.Errorf("query: %w", err)
}

err = writeObjects(tbl, it, w, cols, *format)
err = writeObjects(tbl, it, w, columns, format)
if err != nil {
return "", "", err
}

if *delete {
if delete {
wtxn := db.WriteTxn(tbl.Meta)
count := 0
for obj := range it {
Expand Down
Loading
Loading