From a0f9d1354924bc04ca1c1b0062dd26bd9f47d9cf Mon Sep 17 00:00:00 2001 From: Roberto Hidalgo Date: Sun, 26 Nov 2023 20:57:42 +0000 Subject: [PATCH] Bump deps, get `op item edit` with json stdin, finally (#1) Co-authored-by: Roberto Hidalgo Reviewed-on: https://git.rob.mx/nidito/joao/pulls/1 --- .golangci.yml | 4 +- .milpa/commands/joao/release/build.sh | 7 +- .milpa/commands/joao/test/unit.sh | 1 + .tool-versions | 2 +- cmd/fetch.go | 4 +- cmd/fetch_test.go | 35 +- cmd/get_test.go | 311 +++--------------- cmd/set.go | 4 +- cmd/set_test.go | 42 ++- go.mod | 74 +++-- go.sum | 202 ++++++++---- internal/op-client/checksum.go | 10 +- internal/op-client/cli.go | 118 ++++--- internal/op-client/cli_test.go | 159 +++++++++ internal/op-client/op.go | 3 + .../testdata/bad-test.yaml | 0 .../testdata/deeply-nested.test.yaml | 0 internal/testdata/fixtures.go | 251 ++++++++++++++ .../mock => testdata/opconnect}/opconnect.go | 2 +- test.yaml => internal/testdata/test.yaml | 0 internal/vault/backend.go | 4 +- internal/vault/backend_test.go | 10 +- internal/vault/config_test.go | 4 +- internal/vault/helper_test.go | 6 +- internal/vault/tree_test.go | 12 +- pkg/config/config.go | 3 +- 26 files changed, 784 insertions(+), 484 deletions(-) create mode 100644 internal/op-client/cli_test.go rename bad-test.yaml => internal/testdata/bad-test.yaml (100%) rename deeply-nested.test.yaml => internal/testdata/deeply-nested.test.yaml (100%) create mode 100644 internal/testdata/fixtures.go rename internal/{op-client/mock => testdata/opconnect}/opconnect.go (99%) rename test.yaml => internal/testdata/test.yaml (100%) diff --git a/.golangci.yml b/.golangci.yml index fa3240e..ed71c96 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -21,7 +21,6 @@ linters: - gosec - gosimple - govet - - ifshort - ineffassign - misspell - nakedret @@ -29,12 +28,11 @@ linters: - prealloc - revive - staticcheck - - structcheck + # - structcheck - stylecheck - tagliatelle - typecheck - unconvert - unparam - unused - - varcheck - whitespace diff --git a/.milpa/commands/joao/release/build.sh b/.milpa/commands/joao/release/build.sh index 33e030d..38a8505 100644 --- a/.milpa/commands/joao/release/build.sh +++ b/.milpa/commands/joao/release/build.sh @@ -12,7 +12,7 @@ platforms=( darwin/amd64 ) root=$(dirname "$MILPA_COMMAND_REPO") -cd "$root" || @milpa.fail "could not cd into $MILPA_REPO_ROOT" +cd "$root" || @milpa.fail "could not cd into $root" @milpa.log info "Starting build for version $MILPA_ARG_VERSION" @@ -27,11 +27,14 @@ for platform in "${platforms[@]}"; do package="$root/dist/joao-$os-$arch.tgz" @milpa.log info "archiving to $package" - (cd "$base" && tar -czf "$MILPA_REPO_ROOT$package" joao) || @milpa.fail "Could not archive $package" + (cd "$base" && tar -czf "$package" joao) || @milpa.fail "Could not archive $package" + openssl dgst -sha256 "$package" | awk '{print $2}' > "$package.shasum" rm -rf "$base" @milpa.log success "archived $package" done +echo -n "$MILPA_ARG_VERSION" > "$root/dist/latest-version" + @milpa.log info "uploading to cdn" rclone sync --s3-acl=public-read \ "$root/dist/" \ diff --git a/.milpa/commands/joao/test/unit.sh b/.milpa/commands/joao/test/unit.sh index 813de1e..ac6ffc3 100644 --- a/.milpa/commands/joao/test/unit.sh +++ b/.milpa/commands/joao/test/unit.sh @@ -16,4 +16,5 @@ gotestsum --format testname -- "$MILPA_ARG_SPEC" "${args[@]}" || exit 2 [[ ! "${MILPA_OPT_COVERAGE}" ]] && exit @milpa.log info "Building coverage report" go tool cover -html=coverage.out -o coverage.html || @milpa.fail "could not build reports" +go tool cover -func=coverage.out | tail -n 1 @milpa.log complete "Coverage report ready at coverage.html" diff --git a/.tool-versions b/.tool-versions index b77e706..e4ab54c 100644 --- a/.tool-versions +++ b/.tool-versions @@ -1 +1 @@ -golang 1.20.2 +golang 1.21.1 diff --git a/cmd/fetch.go b/cmd/fetch.go index b00c9ba..ea8a776 100644 --- a/cmd/fetch.go +++ b/cmd/fetch.go @@ -39,7 +39,9 @@ var Fetch = &command.Command{ if dryRun := cmd.Options["dry-run"].ToValue().(bool); dryRun { logrus.Warnf("dry-run: comparing %s to %s", local.OPURL(), path) - if err := local.DiffRemote(path, false, true, cmd.Cobra.OutOrStdout(), cmd.Cobra.OutOrStderr()); err != nil { + stdout := cmd.Cobra.OutOrStdout() + stderr := cmd.Cobra.OutOrStderr() + if err := local.DiffRemote(path, false, true, stdout, stderr); err != nil { return err } logrus.Warnf("dry-run: did not update %s", path) diff --git a/cmd/fetch_test.go b/cmd/fetch_test.go index 753f1df..93b87d2 100644 --- a/cmd/fetch_test.go +++ b/cmd/fetch_test.go @@ -8,23 +8,22 @@ import ( "testing" . "git.rob.mx/nidito/joao/cmd" - "git.rob.mx/nidito/joao/internal/op-client/mock" + "git.rob.mx/nidito/joao/internal/testdata" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "github.com/1Password/connect-sdk-go/onepassword" - "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) func TestFetch(t *testing.T) { - mockOPConnect(t) - f := testConfig.Fields - s := testConfig.Sections - defer func() { testConfig.Fields = f; testConfig.Sections = s }() - - testConfig.Sections = append(testConfig.Sections, + testdata.EnableDebugLogging() + testdata.MockOPConnect(t) + root := testdata.FromProjectRoot() + cfg := testdata.NewTestConfig("some:test") + cfg.Sections = append(cfg.Sections, &onepassword.ItemSection{ID: "o", Label: "o"}, &onepassword.ItemSection{ID: "e-fez-tambem", Label: "e-fez-tambem"}, ) - testConfig.Fields = append(testConfig.Fields, + cfg.Fields = append(cfg.Fields, &onepassword.ItemField{ ID: "o.ganso.gosto", Section: &onepassword.ItemSection{ID: "o", Label: "o"}, @@ -53,23 +52,23 @@ func TestFetch(t *testing.T) { Label: "2", Value: "quém!", }) - mock.Update(testConfig) - root := fromProjectRoot() - out := bytes.Buffer{} - Fetch.SetBindings() + + opconnect.Add(cfg) + out := &bytes.Buffer{} cmd := &cobra.Command{} cmd.Flags().Bool("dry-run", true, "") - cmd.SetOut(&out) - cmd.SetErr(&out) + cmd.SetOut(out) + cmd.SetErr(out) + + Fetch.SetBindings() Fetch.Cobra = cmd - logrus.SetLevel(logrus.DebugLevel) - err := Fetch.Run(cmd, []string{root + "/test.yaml"}) + err := Fetch.Run(cmd, []string{testdata.YAML("test")}) if err != nil { t.Fatalf("could not get: %s", err) } - expected := `--- /Users/roberto/src/joao/test.yaml + expected := `--- ` + root + `/testdata/test.yaml +++ op://example/some:test @@ -1,4 +1,8 @@ bool: false diff --git a/cmd/get_test.go b/cmd/get_test.go index a2e5d11..f572f42 100644 --- a/cmd/get_test.go +++ b/cmd/get_test.go @@ -6,247 +6,24 @@ import ( "bytes" "encoding/json" "os" - "path" - "runtime" "strings" "testing" . "git.rob.mx/nidito/joao/cmd" - opclient "git.rob.mx/nidito/joao/internal/op-client" - "git.rob.mx/nidito/joao/internal/op-client/mock" - "github.com/1Password/connect-sdk-go/connect" - "github.com/1Password/connect-sdk-go/onepassword" + "git.rob.mx/nidito/joao/internal/testdata" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) -var testConfig = &onepassword.Item{ - Title: "some:test", - Vault: onepassword.ItemVault{ID: "example"}, - Category: "PASSWORD", - Sections: []*onepassword.ItemSection{ - {ID: "~annotations", Label: "~annotations"}, - {ID: "nested", Label: "nested"}, - {ID: "list", Label: "list"}, - }, - Fields: []*onepassword.ItemField{ - { - ID: "password", - Type: "CONCEALED", - Purpose: "PASSWORD", - Label: "password", - Value: "8b23de7705b79b73d9f75b120651bc162859e45a732b764362feaefc882eab5d", - }, - { - ID: "notesPlain", - Type: "STRING", - Purpose: "NOTES", - Label: "notesPlain", - Value: "flushed by joao", - }, - { - ID: "~annotations.int", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "int", - Value: "int", - }, - { - ID: "int", - Type: "STRING", - Label: "int", - Value: "1", - }, - { - ID: "string", - Type: "STRING", - Label: "string", - Value: "pato", - }, - { - ID: "~annotations.bool", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "bool", - Value: "bool", - }, - { - ID: "bool", - Type: "STRING", - Label: "bool", - Value: "false", - }, - { - ID: "~annotations.secret", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "secret", - Value: "secret", - }, - { - ID: "secret", - Type: "CONCEALED", - Label: "secret", - Value: "very secret", - }, - { - ID: "~annotations.nested.int", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.int", - Value: "int", - }, - { - ID: "nested.int", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "int", - Value: "1", - }, - { - ID: "~annotations.nested.bool", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.bool", - Value: "bool", - }, - { - ID: "nested.bool", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "bool", - Value: "true", - }, - { - ID: "~annotations.nested.list.0", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.list.0", - Value: "int", - }, - { - ID: "nested.list.0", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "list.0", - Value: "1", - }, - { - ID: "~annotations.nested.list.1", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.list.1", - Value: "int", - }, - { - ID: "nested.list.1", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "list.1", - Value: "2", - }, - { - ID: "~annotations.nested.list.2", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.list.2", - Value: "int", - }, - { - ID: "nested.list.2", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "list.2", - Value: "3", - }, - { - ID: "~annotations.nested.secret", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.secret", - Value: "secret", - }, - { - ID: "nested.secret", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "CONCEALED", - Label: "secret", - Value: "very secret", - }, - { - ID: "~annotations.nested.second_secret", - Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, - Type: "STRING", - Label: "nested.second_secret", - Value: "secret", - }, - { - ID: "nested.second_secret", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "CONCEALED", - Label: "second_secret", - Value: "very secret", - }, - { - ID: "nested.string", - Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, - Type: "STRING", - Label: "string", - Value: "quem", - }, - { - ID: "list.0", - Section: &onepassword.ItemSection{ID: "list", Label: "list"}, - Type: "STRING", - Label: "0", - Value: "one", - }, - { - ID: "list.1", - Section: &onepassword.ItemSection{ID: "list", Label: "list"}, - Type: "STRING", - Label: "1", - Value: "two", - }, - { - ID: "list.2", - Section: &onepassword.ItemSection{ID: "list", Label: "list"}, - Type: "STRING", - Label: "2", - Value: "three", - }, - }, -} - -func mockOPConnect(t *testing.T) { - t.Helper() - opclient.ConnectClientFactory = func(host, token, userAgent string) connect.Client { - return &mock.Client{} - } - client := opclient.NewConnect("", "") - opclient.Use(client) - mock.Add(testConfig) -} - -func fromProjectRoot() string { - _, filename, _, _ := runtime.Caller(0) - dir := path.Join(path.Dir(filename), "../") - if err := os.Chdir(dir); err != nil { - panic(err) - } - wd, _ := os.Getwd() - return wd -} - func TestGetBadYAML(t *testing.T) { - root := fromProjectRoot() Get.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - err := Get.Run(cmd, []string{root + "/bad-test.yaml", "."}) + err := Get.Run(cmd, []string{testdata.YAML("bad-test"), "."}) if err == nil { t.Fatalf("Did not throw on bad path: %s", out.String()) } @@ -258,7 +35,7 @@ func TestGetBadYAML(t *testing.T) { } func TestGetBadPath(t *testing.T) { - root := fromProjectRoot() + root := testdata.FromProjectRoot() Get.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -278,7 +55,6 @@ func TestGetBadPath(t *testing.T) { } func TestGetNormal(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -286,13 +62,13 @@ func TestGetNormal(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) } - expected, err := os.ReadFile(root + "/test.yaml") + expected, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file: %s", err) } @@ -303,7 +79,6 @@ func TestGetNormal(t *testing.T) { } func TestGetRedacted(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -311,14 +86,14 @@ func TestGetRedacted(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", ".", "--redacted"} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + os.Args = []string{testdata.YAML("test"), ".", "--redacted"} + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) } - expected, err := os.ReadFile(root + "/test.yaml") + expected, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file: %s", err) } @@ -329,7 +104,6 @@ func TestGetRedacted(t *testing.T) { } func TestGetPath(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -338,7 +112,7 @@ func TestGetPath(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", "nested.secret"} + os.Args = []string{testdata.YAML("test"), "nested.secret"} err := Get.Run(cmd, os.Args) if err != nil { @@ -353,8 +127,8 @@ func TestGetPath(t *testing.T) { out = bytes.Buffer{} cmd.SetOut(&out) cmd.SetErr(&out) - os.Args = []string{root + "/test.yaml", "nested", "--output", "diff-yaml"} - err = Get.Run(cmd, []string{root + "/test.yaml", "nested"}) + os.Args = []string{testdata.YAML("test"), "nested", "--output", "diff-yaml"} + err = Get.Run(cmd, []string{testdata.YAML("test"), "nested"}) if err != nil { t.Fatalf("could not get: %s", err) @@ -376,7 +150,6 @@ string: quem` } func TestGetPathCollection(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -385,8 +158,8 @@ func TestGetPathCollection(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", "nested", "--output", "yaml"} - err := Get.Run(cmd, []string{root + "/test.yaml", "nested"}) + os.Args = []string{testdata.YAML("test"), "nested", "--output", "yaml"} + err := Get.Run(cmd, []string{testdata.YAML("test"), "nested"}) if err != nil { t.Fatalf("could not get: %s", err) @@ -408,7 +181,6 @@ string: quem` } func TestGetDiff(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -417,8 +189,8 @@ func TestGetDiff(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", ".", "--output", "diff-yaml"} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + os.Args = []string{testdata.YAML("test"), ".", "--output", "diff-yaml"} + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) @@ -452,7 +224,6 @@ string: pato` } func TestGetJSON(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -461,8 +232,8 @@ func TestGetJSON(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", ".", "--output", "json"} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + os.Args = []string{testdata.YAML("test"), ".", "--output", "json"} + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) @@ -476,7 +247,6 @@ func TestGetJSON(t *testing.T) { } func TestGetDeepJSON(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -485,8 +255,9 @@ func TestGetDeepJSON(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/deeply-nested.test.yaml", ".", "--output", "json"} - err := Get.Run(cmd, []string{root + "/deeply-nested.test.yaml", "."}) + file := testdata.YAML("deeply-nested.test") + os.Args = []string{file, ".", "--output", "json"} + err := Get.Run(cmd, []string{file, "."}) if err != nil { t.Fatalf("could not get: %s", err) @@ -500,7 +271,6 @@ func TestGetDeepJSON(t *testing.T) { } func TestGetJSONPathScalar(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -509,8 +279,9 @@ func TestGetJSONPathScalar(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", "nested.secret", "--output", "json"} - err := Get.Run(cmd, []string{root + "/test.yaml", "nested.secret"}) + file := testdata.YAML("test") + os.Args = []string{file, "nested.secret", "--output", "json"} + err := Get.Run(cmd, []string{file, "nested.secret"}) if err != nil { t.Fatalf("could not get: %s", err) @@ -524,7 +295,6 @@ func TestGetJSONPathScalar(t *testing.T) { } func TestGetJSONPathCollection(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -533,8 +303,9 @@ func TestGetJSONPathCollection(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", "nested", "--output", "json"} - err := Get.Run(cmd, []string{root + "/test.yaml", "nested"}) + file := testdata.YAML("test") + os.Args = []string{file, "nested", "--output", "json"} + err := Get.Run(cmd, []string{file, "nested"}) if err != nil { t.Fatalf("could not get: %s", err) @@ -548,7 +319,6 @@ func TestGetJSONPathCollection(t *testing.T) { } func TestGetJSONRedacted(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -557,8 +327,9 @@ func TestGetJSONRedacted(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", ".", "--output", "json", "--redacted"} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + file := testdata.YAML("test") + os.Args = []string{file, ".", "--output", "json", "--redacted"} + err := Get.Run(cmd, []string{file, "."}) if err != nil { t.Fatalf("could not get: %s", err) @@ -572,7 +343,6 @@ func TestGetJSONRedacted(t *testing.T) { } func TestGetJSONOP(t *testing.T) { - root := fromProjectRoot() out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -580,17 +350,18 @@ func TestGetJSONOP(t *testing.T) { cmd.SetOut(&out) cmd.SetErr(&out) Get.Cobra = cmd - os.Args = []string{root + "/test.yaml", ".", "--output", "op"} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + os.Args = []string{testdata.YAML("test"), ".", "--output", "op"} + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) } - id := testConfig.ID - testConfig.ID = "" - defer func() { testConfig.ID = id }() - expected, err := json.Marshal(testConfig) + cfg := testdata.NewTestConfig("some:test") + id := cfg.ID + cfg.ID = "" + defer func() { cfg.ID = id }() + expected, err := json.Marshal(cfg) if err != nil { t.Fatal(err) } @@ -601,8 +372,8 @@ func TestGetJSONOP(t *testing.T) { } func TestGetRemote(t *testing.T) { - mockOPConnect(t) - root := fromProjectRoot() + testdata.MockOPConnect(t) + opconnect.Add(testdata.NewTestConfig("some:test")) out := bytes.Buffer{} Get.SetBindings() cmd := &cobra.Command{} @@ -613,8 +384,8 @@ func TestGetRemote(t *testing.T) { cmd.SetErr(&out) Get.Cobra = cmd logrus.SetLevel(logrus.DebugLevel) - os.Args = []string{root + "/test.yaml", "."} - err := Get.Run(cmd, []string{root + "/test.yaml", "."}) + os.Args = []string{testdata.YAML("test"), "."} + err := Get.Run(cmd, []string{testdata.YAML("test"), "."}) if err != nil { t.Fatalf("could not get: %s", err) diff --git a/cmd/set.go b/cmd/set.go index b925d69..41cb03c 100644 --- a/cmd/set.go +++ b/cmd/set.go @@ -4,7 +4,7 @@ package cmd import ( "fmt" - "io/ioutil" + "io" "os" "strings" @@ -106,7 +106,7 @@ Will read values from stdin (or ﹅--from﹅ a file) and store it at the ﹅PATH } else { var valueBytes []byte if input == "/dev/stdin" { - valueBytes, err = ioutil.ReadAll(cmd.Cobra.InOrStdin()) + valueBytes, err = io.ReadAll(cmd.Cobra.InOrStdin()) } else { valueBytes, err = os.ReadFile(input) } diff --git a/cmd/set_test.go b/cmd/set_test.go index 010ea3c..5fad5fe 100644 --- a/cmd/set_test.go +++ b/cmd/set_test.go @@ -11,7 +11,7 @@ import ( "testing" . "git.rob.mx/nidito/joao/cmd" - "github.com/sirupsen/logrus" + "git.rob.mx/nidito/joao/internal/testdata" "github.com/spf13/cobra" ) @@ -24,7 +24,7 @@ func tempTestYaml(root, name string, data []byte) (string, func(), error) { } func TestSet(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -38,9 +38,9 @@ func TestSet(t *testing.T) { cmd.Flags().Bool("delete", false, "") cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { - t.Fatalf("could not read file") + t.Fatalf("could not read test file") } path, cleanup, err := tempTestYaml(root, "set-plain", original) @@ -73,7 +73,7 @@ string: |- } func TestSetSecret(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-secret") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -87,7 +87,7 @@ func TestSetSecret(t *testing.T) { cmd.Flags().Bool("delete", false, "") cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -119,7 +119,7 @@ func TestSetSecret(t *testing.T) { } func TestSetFromFile(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-from-file") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -130,7 +130,7 @@ func TestSetFromFile(t *testing.T) { cmd.Flags().Bool("delete", false, "") cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -168,7 +168,7 @@ func TestSetFromFile(t *testing.T) { } func TestSetNew(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-new") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -183,7 +183,7 @@ func TestSetNew(t *testing.T) { cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -219,7 +219,7 @@ quarteto: |- } func TestSetNested(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-nested") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -234,7 +234,7 @@ func TestSetNested(t *testing.T) { cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -267,7 +267,7 @@ func TestSetNested(t *testing.T) { } func TestSetJSON(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-json") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -282,7 +282,7 @@ func TestSetJSON(t *testing.T) { cmd.Flags().Bool("json", true, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -317,9 +317,7 @@ na-beira-da-lagoa: } func TestSetList(t *testing.T) { - logrus.SetLevel(logrus.DebugLevel) - - root := fromProjectRoot() + root := testdata.TempDir(t, "test-set-list") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -334,7 +332,7 @@ func TestSetList(t *testing.T) { cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -368,7 +366,7 @@ asdf: } func TestDelete(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-delete") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -380,7 +378,7 @@ func TestDelete(t *testing.T) { cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } @@ -414,7 +412,7 @@ string: pato } func TestDeleteNested(t *testing.T) { - root := fromProjectRoot() + root := testdata.TempDir(t, "test-delete-nested") Set.SetBindings() out := bytes.Buffer{} cmd := &cobra.Command{} @@ -426,7 +424,7 @@ func TestDeleteNested(t *testing.T) { cmd.Flags().Bool("json", false, "") cmd.Flags().Bool("flush", false, "") cmd.Flags().StringP("input", "i", "/dev/stdin", "") - original, err := os.ReadFile(root + "/test.yaml") + original, err := os.ReadFile(testdata.YAML("test")) if err != nil { t.Fatalf("could not read file") } diff --git a/go.mod b/go.mod index bce0e81..78bde25 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,24 @@ module git.rob.mx/nidito/joao -go 1.20 +go 1.21 require ( - git.rob.mx/nidito/chinampa v0.1.1 + git.rob.mx/nidito/chinampa v0.1.4 github.com/1Password/connect-sdk-go v1.5.3 github.com/alessio/shellescape v1.4.2 github.com/hashicorp/go-hclog v1.5.0 - github.com/hashicorp/vault/api v1.9.2 - github.com/hashicorp/vault/sdk v0.9.2 + github.com/hashicorp/go-version v1.6.0 + github.com/hashicorp/vault/api v1.10.0 + github.com/hashicorp/vault/sdk v0.10.2 github.com/jellydator/ttlcache/v3 v3.1.0 github.com/sirupsen/logrus v1.9.3 - github.com/spf13/cobra v1.7.0 - golang.org/x/crypto v0.13.0 + github.com/spf13/cobra v1.8.0 + golang.org/x/crypto v0.15.0 gopkg.in/yaml.v3 v3.0.1 ) require ( + github.com/Microsoft/go-winio v0.6.1 // indirect github.com/alecthomas/chroma v0.10.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect github.com/armon/go-radix v1.0.0 // indirect @@ -24,42 +26,50 @@ require ( github.com/aymerick/douceur v0.2.0 // indirect github.com/cenkalti/backoff/v3 v3.2.2 // indirect github.com/charmbracelet/glamour v0.6.0 // indirect + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect + github.com/distribution/reference v0.5.0 // indirect github.com/dlclark/regexp2 v1.10.0 // indirect - github.com/evanphx/json-patch/v5 v5.6.0 // indirect - github.com/fatih/color v1.15.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.2 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/docker/distribution v2.8.3+incompatible // indirect + github.com/docker/docker v24.0.7+incompatible // indirect + github.com/docker/go-connections v0.4.0 // indirect + github.com/docker/go-units v0.5.0 // indirect + github.com/evanphx/json-patch/v5 v5.7.0 // indirect + github.com/fatih/color v1.16.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.3 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.15.3 // indirect + github.com/go-playground/validator/v10 v10.16.0 // indirect + github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/golang/snappy v0.0.4 // indirect - github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0 // indirect - github.com/hashicorp/go-kms-wrapping/v2 v2.0.12 // indirect + github.com/hashicorp/go-kms-wrapping/v2 v2.0.15 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-plugin v1.5.0 // indirect - github.com/hashicorp/go-retryablehttp v0.7.4 // indirect + github.com/hashicorp/go-plugin v1.6.0 // indirect + github.com/hashicorp/go-retryablehttp v0.7.5 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/mlock v0.1.3 // indirect - github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 // indirect + github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 // indirect + github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect - github.com/hashicorp/go-sockaddr v1.0.4 // indirect + github.com/hashicorp/go-sockaddr v1.0.6 // indirect github.com/hashicorp/go-uuid v1.0.3 // indirect - github.com/hashicorp/go-version v1.6.0 // indirect github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/hcl v1.0.1-vault-5 // indirect github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-runewidth v0.0.15 // indirect - github.com/microcosm-cc/bluemonday v1.0.25 // indirect + github.com/microcosm-cc/bluemonday v1.0.26 // indirect github.com/mitchellh/copystructure v1.2.0 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect @@ -69,24 +79,30 @@ require ( github.com/muesli/termenv v0.15.2 // indirect github.com/oklog/run v1.1.0 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect + github.com/opencontainers/go-digest v1.0.0 // indirect + github.com/opencontainers/image-spec v1.1.0-rc5 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect github.com/pierrec/lz4 v2.6.1+incompatible // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/rivo/uniseg v0.4.4 // indirect github.com/ryanuber/go-glob v1.0.0 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/stretchr/testify v1.8.4 // indirect github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect github.com/uber/jaeger-lib v2.4.1+incompatible // indirect - github.com/yuin/goldmark v1.5.6 // indirect + github.com/yuin/goldmark v1.6.0 // indirect github.com/yuin/goldmark-emoji v1.0.2 // indirect go.uber.org/atomic v1.11.0 // indirect - golang.org/x/net v0.14.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/sys v0.12.0 // indirect - golang.org/x/term v0.12.0 // indirect - golang.org/x/text v0.13.0 // indirect - golang.org/x/time v0.3.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d // indirect - google.golang.org/grpc v1.57.0 // indirect + golang.org/x/mod v0.14.0 // indirect + golang.org/x/net v0.18.0 // indirect + golang.org/x/sync v0.5.0 // indirect + golang.org/x/sys v0.14.0 // indirect + golang.org/x/term v0.14.0 // indirect + golang.org/x/text v0.14.0 // indirect + golang.org/x/time v0.4.0 // indirect + golang.org/x/tools v0.15.0 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f // indirect + google.golang.org/grpc v1.59.0 // indirect google.golang.org/protobuf v1.31.0 // indirect ) diff --git a/go.sum b/go.sum index 7d39faa..d445c8e 100644 --- a/go.sum +++ b/go.sum @@ -1,9 +1,14 @@ -git.rob.mx/nidito/chinampa v0.1.1 h1:2O2dCZPhOoYOjcf2a3ehqy+xACMUFTIK5cMvk8oBi1g= -git.rob.mx/nidito/chinampa v0.1.1/go.mod h1:isI138ZQ3GN/ZcuRrNPJ48fYnPC+U642gUe5bonhwUo= +git.rob.mx/nidito/chinampa v0.1.4 h1:rXmtuwYNtBmpLgWnNK7b5Z/styyuFfCP3RqL+qOzlok= +git.rob.mx/nidito/chinampa v0.1.4/go.mod h1:isI138ZQ3GN/ZcuRrNPJ48fYnPC+U642gUe5bonhwUo= github.com/1Password/connect-sdk-go v1.5.3 h1:KyjJ+kCKj6BwB2Y8tPM1Ixg5uIS6HsB0uWA8U38p/Uk= github.com/1Password/connect-sdk-go v1.5.3/go.mod h1:5rSymY4oIYtS4G3t0oMkGAXBeoYiukV3vkqlnEjIDJs= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= +github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= github.com/HdrHistogram/hdrhistogram-go v1.1.2 h1:5IcZpTvzydCQeHzK4Ef/D5rrSqwxob0t8PQPMybUNFM= +github.com/HdrHistogram/hdrhistogram-go v1.1.2/go.mod h1:yDgFjdqOqDEKOvasDdhWNXYg9BVp4O+o5f6V/ehm6Oo= +github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= +github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -14,7 +19,6 @@ github.com/alessio/shellescape v1.4.2 h1:MHPfaU+ddJ0/bYWpgIeUnQUqKrlJ1S7BfEYPM4u github.com/alessio/shellescape v1.4.2/go.mod h1:PZAiSCk0LJaZkiCSkPv8qIobYglO3FPpyFjDCtHLS30= github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA= github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4= -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/aymanbagabas/go-osc52 v1.0.3/go.mod h1:zT8H+Rk4VSabYN90pWyugflM3ZhpTZNC7cASDfUCdT4= @@ -25,8 +29,8 @@ github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd3 github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bufbuild/protocompile v0.4.0 h1:LbFKd2XowZvQ/kajzguUp2DC9UEIQhIq77fZZlaQsNA= +github.com/bufbuild/protocompile v0.4.0/go.mod h1:3v93+mbWn/v3xzN+31nwkJfrEpAUwp+BagBSZWx+TP8= github.com/cenkalti/backoff/v3 v3.2.2 h1:cfUAAO3yvKMYKPrvhDuHSwQnhZNk/RMHKdZqKTxfm6M= github.com/cenkalti/backoff/v3 v3.2.2/go.mod h1:cIeZDE3IrqwwJl6VUwCN6trj1oXrTS4rc0ij+ULvLYs= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -34,39 +38,55 @@ github.com/charmbracelet/glamour v0.6.0 h1:wi8fse3Y7nfcabbbDuwolqTqMQPMnVPeZhDM2 github.com/charmbracelet/glamour v0.6.0/go.mod h1:taqWV4swIMMbWALc0m7AfE9JkPSU8om2538k9ITBxOc= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= +github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= +github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.10.0 h1:+/GIL799phkJqYW+3YbOd8LCcbHzT0Pbo8zl70MHsq0= github.com/dlclark/regexp2 v1.10.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/evanphx/json-patch/v5 v5.6.0 h1:b91NhWfaz02IuVxO9faSllyAtNXHMPkC5J8sJCLunww= -github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2VvlbKOFpnXhI9Bw4= -github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= +github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= +github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig1seQen0cKYlM= +github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= +github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= +github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= +github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= +github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= +github.com/evanphx/json-patch/v5 v5.7.0 h1:nJqP7uwL84RJInrohHfW0Fx3awjbm8qZeFv0nW9SYGc= +github.com/evanphx/json-patch/v5 v5.7.0/go.mod h1:VNkHZ/282BpEyt/tObQO8s5CMPmYYq14uClGH4abBuQ= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= -github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs= -github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw= +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/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= +github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/frankban/quicktest v1.11.3 h1:8sXhOn0uLys67V8EsXLc6eszDs8VXWxL3iRvebPhedY= -github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= -github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= +github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0= +github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= 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-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.15.3 h1:S+sSpunYjNPDuXkWbK+x+bA7iXiW296KG4dL3X7xUZo= -github.com/go-playground/validator/v10 v10.15.3/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= +github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE= +github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= +github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= 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= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= @@ -80,10 +100,13 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= 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= @@ -98,28 +121,27 @@ github.com/hashicorp/go-immutable-radix v1.3.1 h1:DKHmCUm2hRBK510BaiZlwvpD40f8bJ github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0 h1:pSjQfW3vPtrOTcasTUKgCTQT7OGPPTTMVRrOfU6FJD8= github.com/hashicorp/go-kms-wrapping/entropy/v2 v2.0.0/go.mod h1:xvb32K2keAc+R8DSFG2IwDcydK9DBQE+fGA5fsw6hSk= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.12 h1:zunij049cre7QOfXVAPGUMItPPKVHuvahC7s4p8IB8o= -github.com/hashicorp/go-kms-wrapping/v2 v2.0.12/go.mod h1:NtMaPhqSlfQ72XWDD2g80o8HI8RKkowIB8/WZHMyPY4= -github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.15 h1:f3+/VbanXOmVAaDBKwRiVmeL7EX340a4YmaTItMF4Xs= +github.com/hashicorp/go-kms-wrapping/v2 v2.0.15/go.mod h1:0dWtzl2ilqKpavgM3id/kFK9L3tjo6fS4OhbVPSYpnQ= 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/go-plugin v1.5.0 h1:g6Lj3USwF5LaB8HlvCxPjN2X4nFE08ko2BJNVpl7TIE= -github.com/hashicorp/go-plugin v1.5.0/go.mod h1:w1sAEES3g3PuV/RzUrgow20W2uErMly84hhD3um1WL4= +github.com/hashicorp/go-plugin v1.6.0 h1:wgd4KxHJTVGGqWBq4QPB1i5BZNEx9BR8+OFmHDmTk8A= +github.com/hashicorp/go-plugin v1.6.0/go.mod h1:lBS5MtSSBZk0SHc66KACcjjlU6WzEVP/8pwz68aMkCI= github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs= -github.com/hashicorp/go-retryablehttp v0.7.4 h1:ZQgVdpTdAL7WpMIwLzCfbalOcSUdkDZnpUv3/+BxzFA= -github.com/hashicorp/go-retryablehttp v0.7.4/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= +github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M= +github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8= github.com/hashicorp/go-rootcerts v1.0.2 h1:jzhAVGtqPKbwpyCPELlgNWhE1znq+qwJtW5Oi2viEzc= github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8= github.com/hashicorp/go-secure-stdlib/mlock v0.1.3 h1:kH3Rhiht36xhAfhuHyWJDgdXXEx9IIZhDGRk24CDhzg= github.com/hashicorp/go-secure-stdlib/mlock v0.1.3/go.mod h1:ov1Q0oEDjC3+A4BwsG2YdKltrmEw8sf9Pau4V9JQ4Vo= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7 h1:UpiO20jno/eV1eVZcxqWnUohyKRe1g8FPV/xH1s/2qs= -github.com/hashicorp/go-secure-stdlib/parseutil v0.1.7/go.mod h1:QmrqtbKuxxSWTN3ETMPuB+VtEiBJ/A9XhoYGv8E1uD8= -github.com/hashicorp/go-secure-stdlib/strutil v0.1.1/go.mod h1:gKOamz3EwoIoJq7mlMIRBpVTAUn8qPCrEclOKKWhD3U= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8 h1:iBt4Ew4XEGLfh6/bPk4rSYmuZJGizr6/x/AEizP0CQc= +github.com/hashicorp/go-secure-stdlib/parseutil v0.1.8/go.mod h1:aiJI+PIApBRQG7FZTEBx5GiiX+HbOHilUdNxUZi4eV0= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0 h1:KMWpBsC65ZBXDpoxJ0n2/zVfZaZIW73k2d8cy5Dv/Kk= +github.com/hashicorp/go-secure-stdlib/plugincontainer v0.3.0/go.mod h1:qKYwSZ2EOpppko5ud+Sh9TrUgiTAZSaQCr8XWIYXsbM= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9CdjCtrXrXGuOpxEA7Ts= github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= -github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A= -github.com/hashicorp/go-sockaddr v1.0.4 h1:NJY/hSAoWy0EhQQdDxxoBlwyJex/xC2qNWXD0up6D48= -github.com/hashicorp/go-sockaddr v1.0.4/go.mod h1:LPGW7TbF+cTE2o/bBlBWD4XG8rgRJeIurURxH5kEHr8= +github.com/hashicorp/go-sockaddr v1.0.6 h1:RSG8rKU28VTUTvEKghe5gIhIQpv8evvNpnDEyqO4u9I= +github.com/hashicorp/go-sockaddr v1.0.6/go.mod h1:uoUUmtwU7n9Dv3O4SNLeFvg0SxQ3lyjsj6+CCykpaxI= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8= github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= @@ -130,43 +152,49 @@ github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iP github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= -github.com/hashicorp/vault/api v1.9.2 h1:YjkZLJ7K3inKgMZ0wzCU9OHqc+UqMQyXsPXnf3Cl2as= -github.com/hashicorp/vault/api v1.9.2/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= -github.com/hashicorp/vault/sdk v0.9.2 h1:H1kitfl1rG2SHbeGEyvhEqmIjVKE3E6c2q3ViKOs6HA= -github.com/hashicorp/vault/sdk v0.9.2/go.mod h1:gG0lA7P++KefplzvcD3vrfCmgxVAM7Z/SqX5NeOL/98= +github.com/hashicorp/vault/api v1.10.0 h1:/US7sIjWN6Imp4o/Rj1Ce2Nr5bki/AXi9vAW3p2tOJQ= +github.com/hashicorp/vault/api v1.10.0/go.mod h1:jo5Y/ET+hNyz+JnKDt8XLAdKs+AM0G5W0Vp1IrFI8N8= +github.com/hashicorp/vault/sdk v0.10.2 h1:0UEOLhFyoEMpb/r8H5qyOu58A/j35pncqiS/d+ORKYk= +github.com/hashicorp/vault/sdk v0.10.2/go.mod h1:VxJIQgftEX7FCDM3i6TTLjrZszAeLhqPicNbCVNRg4I= github.com/hashicorp/yamux v0.1.1 h1:yrQxtgseBDrq9Y652vSRDvsKCJKOUD+GzTS4Y0Y8pvE= github.com/hashicorp/yamux v0.1.1/go.mod h1:CtWFDAQgb7dxtzFs4tWbplKIe2jSi3+5vKbgIO0SLnQ= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jellydator/ttlcache/v3 v3.1.0 h1:0gPFG0IHHP6xyUyXq+JaD8fwkDCqgqwohXNJBcYE71g= github.com/jellydator/ttlcache/v3 v3.1.0/go.mod h1:hi7MGFdMAwZna5n2tuvh63DvFLzVKySzCVW6+0gA2n4= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c= +github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo= +github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531 h1:hgVxRoDDPtQE68PT4LFvNlPz2nBKd3OMlGKIQ69OmR4= +github.com/joshlf/go-acl v0.0.0-20200411065538-eae00ae38531/go.mod h1:fqTUQpVYBvhCNIsMXGl2GE9q6z94DIP6NtFKXCSTVbg= +github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d h1:J8tJzRyiddAFF65YVgxli+TyWBi0f79Sld6rJP6CBcY= +github.com/joshlf/testutil v0.0.0-20170608050642-b5d8aa79d93d/go.mod h1:b+Q3v8Yrg5o15d71PSUraUzYb+jWl6wQMSBXSGS/hv0= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= +github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= +github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= 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-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.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/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= +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-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -174,25 +202,26 @@ github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZ github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM= -github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= -github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= -github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58= +github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs= 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/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= github.com/mitchellh/go-testing-interface v1.14.1/go.mod h1:gfgS7OtZj6MA4U1UrDRp04twqAjfvlZyCfX3sDjEym8= -github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= -github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= 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.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= +github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= +github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= 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= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= +github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= @@ -200,10 +229,15 @@ github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA= github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU= 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/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= +github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= +github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= +github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0MwY= @@ -216,7 +250,7 @@ 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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= -github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= @@ -233,16 +267,16 @@ github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= -github.com/spf13/cobra v1.7.0/go.mod h1:uLxZILRyS/50WlhOIKD7W6V5bgeIt+4sICxh6uRMrb0= +github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= +github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= @@ -258,41 +292,54 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= +github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/uber/jaeger-client-go v2.30.0+incompatible h1:D6wyKGCecFaSRUpo8lCVbaOOb6ThwMmTEbhRwtKR97o= github.com/uber/jaeger-client-go v2.30.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v2.4.1+incompatible h1:td4jdvLcExb4cBISKIpHuGoVXh+dVKhn2Um6rjCsSsg= github.com/uber/jaeger-lib v2.4.1+incompatible/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= +github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.7/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.5.6 h1:COmQAWTCcGetChm3Ig7G/t8AFAN00t+o8Mt4cf7JpwA= -github.com/yuin/goldmark v1.5.6/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.6.0 h1:boZcn2GTjpsynOsC0iJHnBWa4Bi0qzfJjthwauItG68= +github.com/yuin/goldmark v1.6.0/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= github.com/yuin/goldmark-emoji v1.0.2 h1:c/RgTShNgHTtc6xdz2KKI74jJr6rWi7FPgnP9GAsO5s= github.com/yuin/goldmark-emoji v1.0.2/go.mod h1:RhP/RWpexdp+KHs7ghKnifRoIs/Bq4nDS7tRbCkOwKY= go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= 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-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.13.0 h1:mvySKfSWJ+UKUii46M40LOvyWfN0s2U+46/jDd0e6Ck= -golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA= +golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g= +golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= +golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= -golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14= -golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= +golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg= +golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= -golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE= +golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -301,6 +348,7 @@ golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/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= @@ -310,23 +358,32 @@ golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= +golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU= -golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= +golang.org/x/term v0.14.0 h1:LGK9IlZ8T9jvdy6cTdfKUCltatMFOehAQo9SRC46UQ8= +golang.org/x/term v0.14.0/go.mod h1:TySc+nGkYR6qt8km8wUhuFRTVSMIX3XPR58y2lC8vww= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= -golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= -golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/time v0.4.0 h1:Z81tqI5ddIoXDPvVQ7/7CC9TnLM7ubaFG2qXYd5BbYY= +golang.org/x/time v0.4.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= +golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.15.0 h1:zdAyfUGbYmuVokhzVmghFl2ZJh5QhcfebBgmVPFYA+8= +golang.org/x/tools v0.15.0/go.mod h1:hpksKq4dtpQWS1uQ61JkdqWM3LscIS6Slf+VVkm+wQk= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= -google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= -google.golang.org/grpc v1.57.0 h1:kfzNeI/klCGD2YPMUlaGNT3pxvYfga7smW3Vth8Zsiw= -google.golang.org/grpc v1.57.0/go.mod h1:Sd+9RMTACXwmub0zcNY2c4arhtrbBYD1AUHI/dt16Mo= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f h1:ultW7fxlIvee4HYrtnaRPon9HpEgFk5zYpmfMgtKB5I= +google.golang.org/genproto/googleapis/rpc v0.0.0-20231120223509-83a465c0220f/go.mod h1:L9KNLi232K1/xB6f7AlSX692koaRnKaWSR0stBki0Yc= +google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= +google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -335,6 +392,7 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -342,3 +400,5 @@ gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 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= +gotest.tools/v3 v3.5.0 h1:Ljk6PdHdOhAb5aDMWXjDLMMhph+BpztA4v1QdqEW2eY= +gotest.tools/v3 v3.5.0/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= diff --git a/internal/op-client/checksum.go b/internal/op-client/checksum.go index e03e76a..7ff9a40 100644 --- a/internal/op-client/checksum.go +++ b/internal/op-client/checksum.go @@ -20,8 +20,14 @@ func Checksum(fields []*op.ItemField) string { continue } label := field.Label - if field.Section != nil && field.Section.ID != "" { - label = field.Section.ID + "." + label + if field.Section != nil { + sectionID := field.Section.Label + if sectionID == "" { + sectionID = field.Section.ID + } + if sectionID != "" { + label = sectionID + "." + label + } } df = append(df, label+field.Value) } diff --git a/internal/op-client/cli.go b/internal/op-client/cli.go index 5f1e71f..46ae25a 100644 --- a/internal/op-client/cli.go +++ b/internal/op-client/cli.go @@ -12,37 +12,26 @@ import ( op "github.com/1Password/connect-sdk-go/onepassword" "github.com/alessio/shellescape" + "github.com/hashicorp/go-version" "github.com/sirupsen/logrus" ) -type CLI struct { - DryRun bool // Won't write to 1Password -} +// Path points to the op binary. +var Path = "op" +var probedVersionModern = false +var versionConstraint = version.MustConstraints(version.NewConstraint(">= 2.23")) +var Exec ExecFunc = DefaultExec -func invoke(vault string, args ...string) (bytes.Buffer, error) { - if vault != "" { - args = append([]string{"--vault", shellescape.Quote(vault)}, args...) - } +type ExecFunc func(program string, args []string, stdin *bytes.Buffer) (bytes.Buffer, error) - argString := "" - for _, arg := range args { - parts := strings.Split(arg, "]=") - if strings.HasSuffix(parts[0], "[password") { - parts[1] = "*****" - argString += fmt.Sprintf("%s]=%v", parts[0], parts[1]) - } else { - argString += " " + arg - } - } - logrus.Debugf("invoking op with args: %s", argString) - cmd := exec.Command("op", args...) +func DefaultExec(program string, args []string, stdin *bytes.Buffer) (stdout bytes.Buffer, err error) { + cmd := exec.Command(Path, args...) cmd.Env = os.Environ() - var stdout bytes.Buffer cmd.Stdout = &stdout var stderr bytes.Buffer cmd.Stderr = &stderr - if err := cmd.Run(); err != nil { + if err = cmd.Run(); err != nil { return stderr, fmt.Errorf("op exited with %s:\n%s", err, stderr.Bytes()) } if cmd.ProcessState.ExitCode() > 0 { @@ -52,8 +41,28 @@ func invoke(vault string, args ...string) (bytes.Buffer, error) { return stdout, nil } +type CLI struct { + DryRun bool // Won't write to 1Password +} + +func invoke(dryRun bool, vault string, stdin *bytes.Buffer, args ...string) (bytes.Buffer, error) { + if vault != "" { + args = append([]string{"--vault", shellescape.Quote(vault)}, args...) + } + + argString := strings.Join(args, " ") + if dryRun { + logrus.Warnf("dry-run: Would have invoked `op %s`", argString) + logrus.Warnf("dry-run: stdin `%s`", stdin) + return bytes.Buffer{}, nil + } + + logrus.Debugf("running `%s %s`", Path, argString) + return Exec(Path, args, stdin) +} + func (b *CLI) Get(vault, name string) (*op.Item, error) { - stdout, err := invoke(vault, "item", "--format", "json", "get", name) + stdout, err := invoke(false, vault, nil, "item", "--format", "json", "get", name) if err != nil { return nil, err } @@ -68,39 +77,64 @@ func (b *CLI) Get(vault, name string) (*op.Item, error) { func (b *CLI) Create(item *op.Item) error { logrus.Infof("Creating new item: %s/%s", item.Vault.ID, item.Title) - cmd := exec.Command("op", "--vault", shellescape.Quote(item.Vault.ID), "item", "create") // nolint: gosec itemJSON, err := json.Marshal(item) if err != nil { return fmt.Errorf("could not serialize op item into json: %w", err) } - cmd.Stdin = bytes.NewBuffer(itemJSON) - cmd.Env = os.Environ() - var stdout bytes.Buffer - cmd.Stdout = &stdout - var stderr bytes.Buffer - cmd.Stderr = &stderr - if b.DryRun { - logrus.Warnf("dry-run: Would have invoked %v", cmd.Args) - return nil - } - if err := cmd.Run(); err != nil { + stdin := bytes.NewBuffer(itemJSON) + + _, err = invoke(b.DryRun, item.Vault.ID, stdin, "item", "create") + if err != nil { return fmt.Errorf("could not create item: %w", err) } - if cmd.ProcessState.ExitCode() > 0 { - return fmt.Errorf("op exited with %d: %s", cmd.ProcessState.ExitCode(), stderr.Bytes()) - } logrus.Infof("Item %s/%s created", item.Vault.ID, item.Title) return nil } func (b *CLI) Update(item *op.Item, remote *op.Item) error { - args := []string{"item", "edit", item.Title, "--"} + res, err := invoke(false, "", nil, "--version") + if err == nil { + v := strings.TrimSpace(res.String()) + current, err := version.NewVersion(v) + if err == nil { + probedVersionModern = versionConstraint.Check(current) + } else { + logrus.Debugf("Failed parsing version <%s>: %s", v, err) + } + } + + if probedVersionModern { + return b.UpdateModern(item, remote) + } + + return b.DeprecatedUpdate(item, remote) +} + +func (b *CLI) UpdateModern(updated *op.Item, original *op.Item) error { + itemJSON, err := json.Marshal(updated) + if err != nil { + return fmt.Errorf("could not serialize op item into json: %w", err) + } + + stdin := bytes.NewBuffer(itemJSON) + _, err = invoke(b.DryRun, updated.Vault.ID, stdin, "item", "edit", original.Title) + if err != nil { + return fmt.Errorf("could not create item: %w", err) + } + + logrus.Infof("Item %s/%s updated", updated.Vault.ID, updated.Title) + return nil +} + +func (b *CLI) DeprecatedUpdate(updated *op.Item, original *op.Item) error { + logrus.Warnf("Using op-cli < 2.23 means using a hack for updating items, please upgrade ASAP!") + args := []string{"item", "edit", updated.Title, "--"} localKeys := map[string]int{} - for _, field := range item.Fields { + for _, field := range updated.Fields { kind := "" if field.Type == "CONCEALED" { kind = "password" @@ -113,7 +147,7 @@ func (b *CLI) Update(item *op.Item, remote *op.Item) error { localKeys[keyName] = 1 } - for _, field := range remote.Fields { + for _, field := range original.Fields { key := keyForField(field) if _, exists := localKeys[key]; !exists { logrus.Debugf("Deleting remote key %s", key) @@ -125,12 +159,12 @@ func (b *CLI) Update(item *op.Item, remote *op.Item) error { logrus.Warnf("dry-run: Would have invoked op %v", args) return nil } - stdout, err := invoke(item.Vault.ID, args...) + stdout, err := invoke(b.DryRun, updated.Vault.ID, nil, args...) if err != nil { logrus.Errorf("op stderr: %s", stdout.String()) return err } - logrus.Infof("Item %s/%s updated", item.Vault.ID, item.Title) + logrus.Infof("Item %s/%s updated", updated.Vault.ID, updated.Title) return nil } diff --git a/internal/op-client/cli_test.go b/internal/op-client/cli_test.go new file mode 100644 index 0000000..39b4046 --- /dev/null +++ b/internal/op-client/cli_test.go @@ -0,0 +1,159 @@ +package opclient_test + +import ( + "bytes" + "encoding/json" + "os" + "strings" + "testing" + + opclient "git.rob.mx/nidito/joao/internal/op-client" + "git.rob.mx/nidito/joao/internal/testdata" + "github.com/1Password/connect-sdk-go/onepassword" + "github.com/sirupsen/logrus" +) + +func TestMain(m *testing.M) { + code := m.Run() + opclient.Exec = opclient.DefaultExec + os.Exit(code) +} + +func fieldify(item *onepassword.Item) *onepassword.Item { + item.Fields = []*onepassword.ItemField{ + { + ID: "password", + Type: "CONCEALED", + Purpose: "PASSWORD", + Label: "password", + Value: "checksum", + }, + { + ID: "~annotations.int", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "int", + Value: "int", + }, + { + ID: "int", + Type: "STRING", + Label: "int", + Value: "1", + }, + { + ID: "~annotations.nested.int", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.int", + Value: "int", + }, + { + ID: "nested.int", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "int", + Value: "1", + }, + } + + return item +} + +func TestDeprecatedUpdate(t *testing.T) { + client := &opclient.CLI{} + queriedVersion := false + var calledArgs []string + var calledStdin *bytes.Buffer + opclient.Exec = func(program string, args []string, stdin *bytes.Buffer) (bytes.Buffer, error) { + if strings.Contains(strings.Join(args, " "), "--version") { + queriedVersion = true + return *bytes.NewBufferString("1.0"), nil + } + + calledArgs = args + calledStdin = stdin + return *bytes.NewBufferString("updated"), nil + } + + original := fieldify(testdata.NewTestConfig("some:test")) + + updated := fieldify(testdata.NewTestConfig(original.Title)) + updated.Fields[2].Value = "42" + updated.Fields[4].Value = "42" + + err := client.Update(updated, original) + if err != nil { + t.Fatalf("Failed in test update: %s", err) + } + + if !queriedVersion { + t.Fatalf("client did not query for version") + } + + gotArgs := strings.Join(calledArgs, " ") + wantedArgs := "--vault example item edit some:test -- password[password]=checksum ~annotations.int[text]=int int[text]=42 ~annotations.nested\\.int[text]=int nested.int[text]=42" + if gotArgs != wantedArgs { + t.Fatalf("client called unexpected arguments.\nwant: %s\n got: %s", wantedArgs, gotArgs) + } + + var wantedStdin *bytes.Buffer + if wantedStdin.String() != calledStdin.String() { + t.Fatalf("client called unexpected stdin.\nwant: %s\n got: %s", wantedStdin, calledStdin) + } +} + +func TestUpdate(t *testing.T) { + testdata.EnableDebugLogging() + client := &opclient.CLI{} + queriedVersion := false + var calledArgs []string + var calledStdin *bytes.Buffer + execCalled := false + opclient.Exec = func(program string, args []string, stdin *bytes.Buffer) (bytes.Buffer, error) { + logrus.Debugf("Called exec with %+v", args) + execCalled = true + if strings.Contains(strings.Join(args, " "), "--version") { + queriedVersion = true + return *bytes.NewBufferString("2.30"), nil + } + + calledArgs = args + calledStdin = stdin + return *bytes.NewBufferString("updated"), nil + } + + original := fieldify(testdata.NewTestConfig("some:test")) + + updated := fieldify(testdata.NewTestConfig(original.Title)) + updated.Fields[2].Value = "42" + updated.Fields[4].Value = "42" + + err := client.Update(updated, original) + if err != nil { + t.Fatalf("Failed in test update: %s", err) + } + + if !execCalled { + t.Fatalf("client did not query for version") + } + + if !queriedVersion { + t.Fatalf("client did not query for version") + } + + gotArgs := strings.Join(calledArgs, " ") + wantedArgs := "--vault example item edit some:test" + if gotArgs != wantedArgs { + t.Fatalf("client called unexpected arguments.\nwant: %s\n got: %s", wantedArgs, gotArgs) + } + + updatedJSON, err := json.Marshal(updated) + if err != nil { + t.Fatalf("Could not encode json: %s", err) + } + wantedStdin := bytes.NewBuffer(updatedJSON) + if wantedStdin.String() != calledStdin.String() { + t.Fatalf("client called unexpected stdin.\nwant: %s\n got: %s", wantedStdin, calledStdin) + } +} diff --git a/internal/op-client/op.go b/internal/op-client/op.go index 062ee36..7ba9281 100644 --- a/internal/op-client/op.go +++ b/internal/op-client/op.go @@ -42,6 +42,9 @@ func Update(vault, name string, item *op.Item) error { } remoteCS := Checksum(remote.Fields) + // we're checking the checksum we just calculated matches the stored on remote + // and that remoteCS matching the current item's stored password + // nolint:gocritic if remoteCS == item.GetValue("password") && remoteCS == remote.GetValue("password") { logrus.Debugf("remote %s\nlocal %s", remoteCS, item.GetValue("password")) logrus.Warnf("item %s/%s is already up to date", item.Vault.ID, item.Title) diff --git a/bad-test.yaml b/internal/testdata/bad-test.yaml similarity index 100% rename from bad-test.yaml rename to internal/testdata/bad-test.yaml diff --git a/deeply-nested.test.yaml b/internal/testdata/deeply-nested.test.yaml similarity index 100% rename from deeply-nested.test.yaml rename to internal/testdata/deeply-nested.test.yaml diff --git a/internal/testdata/fixtures.go b/internal/testdata/fixtures.go new file mode 100644 index 0000000..e5f29a9 --- /dev/null +++ b/internal/testdata/fixtures.go @@ -0,0 +1,251 @@ +package testdata + +import ( + "fmt" + "os" + "path" + "runtime" + "testing" + + opclient "git.rob.mx/nidito/joao/internal/op-client" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" + "github.com/1Password/connect-sdk-go/connect" + "github.com/1Password/connect-sdk-go/onepassword" + "github.com/sirupsen/logrus" +) + +func MockOPConnect(t *testing.T) { + t.Helper() + opclient.ConnectClientFactory = func(host, token, userAgent string) connect.Client { + return &opconnect.Client{} + } + client := opclient.NewConnect("", "") + opclient.Use(client) + opconnect.Clear() +} + +func FromProjectRoot() string { + _, filename, _, _ := runtime.Caller(0) + dir := path.Join(path.Dir(filename), "../") + if err := os.Chdir(dir); err != nil { + panic(err) + } + wd, _ := os.Getwd() + return wd +} + +func TempDir(t *testing.T, name string) string { + newDir, err := os.MkdirTemp("", name+"-*") + if err != nil { + t.Fatalf("could not create tempdir") + } + return newDir +} + +func YAML(name string) string { + return path.Join(FromProjectRoot(), "testdata", fmt.Sprintf("%s.yaml", name)) +} + +func EnableDebugLogging() { + logrus.SetLevel(logrus.DebugLevel) +} + +func NewTestConfig(title string) *onepassword.Item { + return &onepassword.Item{ + Title: title, + Vault: onepassword.ItemVault{ID: "example"}, + Category: "PASSWORD", + Sections: []*onepassword.ItemSection{ + {ID: "~annotations", Label: "~annotations"}, + {ID: "nested", Label: "nested"}, + {ID: "list", Label: "list"}, + }, + Fields: []*onepassword.ItemField{ + { + ID: "password", + Type: "CONCEALED", + Purpose: "PASSWORD", + Label: "password", + Value: "8b23de7705b79b73d9f75b120651bc162859e45a732b764362feaefc882eab5d", + }, + { + ID: "notesPlain", + Type: "STRING", + Purpose: "NOTES", + Label: "notesPlain", + Value: "flushed by joao", + }, + { + ID: "~annotations.int", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "int", + Value: "int", + }, + { + ID: "int", + Type: "STRING", + Label: "int", + Value: "1", + }, + { + ID: "string", + Type: "STRING", + Label: "string", + Value: "pato", + }, + { + ID: "~annotations.bool", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "bool", + Value: "bool", + }, + { + ID: "bool", + Type: "STRING", + Label: "bool", + Value: "false", + }, + { + ID: "~annotations.secret", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "secret", + Value: "secret", + }, + { + ID: "secret", + Type: "CONCEALED", + Label: "secret", + Value: "very secret", + }, + { + ID: "~annotations.nested.int", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.int", + Value: "int", + }, + { + ID: "nested.int", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "int", + Value: "1", + }, + { + ID: "~annotations.nested.bool", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.bool", + Value: "bool", + }, + { + ID: "nested.bool", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "bool", + Value: "true", + }, + { + ID: "~annotations.nested.list.0", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.list.0", + Value: "int", + }, + { + ID: "nested.list.0", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "list.0", + Value: "1", + }, + { + ID: "~annotations.nested.list.1", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.list.1", + Value: "int", + }, + { + ID: "nested.list.1", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "list.1", + Value: "2", + }, + { + ID: "~annotations.nested.list.2", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.list.2", + Value: "int", + }, + { + ID: "nested.list.2", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "list.2", + Value: "3", + }, + { + ID: "~annotations.nested.secret", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.secret", + Value: "secret", + }, + { + ID: "nested.secret", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "CONCEALED", + Label: "secret", + Value: "very secret", + }, + { + ID: "~annotations.nested.second_secret", + Section: &onepassword.ItemSection{ID: "~annotations", Label: "~annotations"}, + Type: "STRING", + Label: "nested.second_secret", + Value: "secret", + }, + { + ID: "nested.second_secret", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "CONCEALED", + Label: "second_secret", + Value: "very secret", + }, + { + ID: "nested.string", + Section: &onepassword.ItemSection{ID: "nested", Label: "nested"}, + Type: "STRING", + Label: "string", + Value: "quem", + }, + { + ID: "list.0", + Section: &onepassword.ItemSection{ID: "list", Label: "list"}, + Type: "STRING", + Label: "0", + Value: "one", + }, + { + ID: "list.1", + Section: &onepassword.ItemSection{ID: "list", Label: "list"}, + Type: "STRING", + Label: "1", + Value: "two", + }, + { + ID: "list.2", + Section: &onepassword.ItemSection{ID: "list", Label: "list"}, + Type: "STRING", + Label: "2", + Value: "three", + }, + }, + } +} diff --git a/internal/op-client/mock/opconnect.go b/internal/testdata/opconnect/opconnect.go similarity index 99% rename from internal/op-client/mock/opconnect.go rename to internal/testdata/opconnect/opconnect.go index 4e025f8..986bf40 100644 --- a/internal/op-client/mock/opconnect.go +++ b/internal/testdata/opconnect/opconnect.go @@ -1,6 +1,6 @@ // Copyright © 2022 Roberto Hidalgo // SPDX-License-Identifier: Apache-2.0 -package mock +package opconnect import ( "fmt" diff --git a/test.yaml b/internal/testdata/test.yaml similarity index 100% rename from test.yaml rename to internal/testdata/test.yaml diff --git a/internal/vault/backend.go b/internal/vault/backend.go index 5108547..c76a860 100644 --- a/internal/vault/backend.go +++ b/internal/vault/backend.go @@ -30,7 +30,7 @@ var ConnectClientFactory func(s logical.Storage) (connect.Client, error) = onePa // Factory returns a new backend as logical.Backend. func Factory(ctx context.Context, conf *logical.BackendConfig) (logical.Backend, error) { - b := Backend() + b := newBackend() if err := b.Setup(ctx, conf); err != nil { return nil, err } @@ -58,7 +58,7 @@ func optionalVaultPattern(suffix string) string { return fmt.Sprintf("(?P([\\w:]+)%s)?", suffix) } -func Backend() *backend { +func newBackend() *backend { var b = &backend{ configCache: ttlcache.New( ttlcache.WithTTL[string, string](5 * time.Minute), diff --git a/internal/vault/backend_test.go b/internal/vault/backend_test.go index 2b7e117..b277a27 100644 --- a/internal/vault/backend_test.go +++ b/internal/vault/backend_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "git.rob.mx/nidito/joao/internal/op-client/mock" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "git.rob.mx/nidito/joao/internal/vault" "git.rob.mx/nidito/joao/internal/vault/middleware" "github.com/1Password/connect-sdk-go/connect" @@ -15,7 +15,7 @@ import ( func init() { vault.ConnectClientFactory = func(s logical.Storage) (connect.Client, error) { - return &mock.Client{}, nil + return &opconnect.Client{}, nil } } @@ -32,15 +32,15 @@ func TestConfiguredBackend(t *testing.T) { t.Fatalf("Unexpected error with config set: %s => %v", err, resp) } - if resp.Data["token"] != mock.Token { + if resp.Data["token"] != opconnect.Token { t.Errorf("Found unknown token: %s", resp.Data["token"]) } - if resp.Data["host"] != mock.Host { + if resp.Data["host"] != opconnect.Host { t.Errorf("Found unknown host: %s", resp.Data["host"]) } - if resp.Data["vault"] != mock.Vaults[0].ID { + if resp.Data["vault"] != opconnect.Vaults[0].ID { t.Errorf("Found unknown vault: %s", resp.Data["vault"]) } } diff --git a/internal/vault/config_test.go b/internal/vault/config_test.go index 4a0c02e..41259cd 100644 --- a/internal/vault/config_test.go +++ b/internal/vault/config_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "git.rob.mx/nidito/joao/internal/op-client/mock" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "github.com/hashicorp/vault/sdk/logical" ) @@ -49,7 +49,7 @@ func TestConfigDefault(t *testing.T) { t.Fatal("got no response, expected something!") } - mapsEqual(t, resp.Data, map[string]any{"host": mock.Host, "token": mock.Token, "vault": mock.Vaults[0].ID}) + mapsEqual(t, resp.Data, map[string]any{"host": opconnect.Host, "token": opconnect.Token, "vault": opconnect.Vaults[0].ID}) } func TestConfigUpdate(t *testing.T) { diff --git a/internal/vault/helper_test.go b/internal/vault/helper_test.go index 2b4c99c..4f9af70 100644 --- a/internal/vault/helper_test.go +++ b/internal/vault/helper_test.go @@ -8,7 +8,7 @@ import ( "testing" "time" - "git.rob.mx/nidito/joao/internal/op-client/mock" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "git.rob.mx/nidito/joao/internal/vault" "git.rob.mx/nidito/joao/internal/vault/middleware" "github.com/1Password/connect-sdk-go/connect" @@ -44,7 +44,7 @@ func getBackend(tb testing.TB) (logical.Backend, logical.Storage) { cfg := testConfig() ctx := context.Background() - data, err := json.Marshal(map[string]string{"host": mock.Host, "token": mock.Token, "vault": mock.Vaults[0].ID}) + data, err := json.Marshal(map[string]string{"host": opconnect.Host, "token": opconnect.Token, "vault": opconnect.Vaults[0].ID}) if err != nil { tb.Fatalf("Could not serialize config for client: %s", err) } @@ -77,6 +77,6 @@ func getUnconfiguredBackend(tb testing.TB) (logical.Backend, logical.Storage) { func setOnePassswordConnectMocks() { vault.ConnectClientFactory = func(s logical.Storage) (connect.Client, error) { - return &mock.Client{}, nil + return &opconnect.Client{}, nil } } diff --git a/internal/vault/tree_test.go b/internal/vault/tree_test.go index ce925d0..5fd7bb5 100644 --- a/internal/vault/tree_test.go +++ b/internal/vault/tree_test.go @@ -8,7 +8,7 @@ import ( "fmt" "testing" - "git.rob.mx/nidito/joao/internal/op-client/mock" + "git.rob.mx/nidito/joao/internal/testdata/opconnect" "github.com/1Password/connect-sdk-go/onepassword" "github.com/hashicorp/vault/sdk/logical" ) @@ -20,8 +20,8 @@ func getTestBackendWithConfig(t *testing.T) (logical.Backend, logical.Storage) { func TestReadEntry(t *testing.T) { b, reqStorage := getTestBackendWithConfig(t) - mock.Clear() - item := mock.Add(generateConfigItem("service:test")) + opconnect.Clear() + item := opconnect.Add(generateConfigItem("service:test")) expected := map[string]any{ "boolean": false, "integer": 42, @@ -89,8 +89,8 @@ func TestReadEntry(t *testing.T) { func TestListEntries(t *testing.T) { b, reqStorage := getTestBackendWithConfig(t) - mock.Clear() - item := mock.Add(generateConfigItem("service:test")) + opconnect.Clear() + item := opconnect.Add(generateConfigItem("service:test")) expected := map[string]any{ "keys": []string{ @@ -174,7 +174,7 @@ func generateConfigItem(title string) *onepassword.Item { Category: "password", Title: title, Vault: onepassword.ItemVault{ - ID: mock.Vaults[0].ID, + ID: opconnect.Vaults[0].ID, }, Fields: []*onepassword.ItemField{ { diff --git a/pkg/config/config.go b/pkg/config/config.go index 64506ff..051950a 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -5,7 +5,6 @@ package config import ( "fmt" "io" - "io/ioutil" "os" "os/exec" "strings" @@ -236,7 +235,7 @@ func (cfg *Config) DiffRemote(path string, redacted, asFetch bool, stdout, stder } func tempfile(data []byte) (string, func(), error) { - f, err := ioutil.TempFile("", "joao-diff") + f, err := os.CreateTemp("", "joao-diff") if err != nil { return "", nil, err }