joao/cmd/get_test.go

540 lines
16 KiB
Go
Raw Normal View History

2023-01-10 07:02:10 +00:00
// Copyright © 2022 Roberto Hidalgo <joao@un.rob.mx>
// SPDX-License-Identifier: Apache-2.0
package cmd_test
import (
"bytes"
"os"
"path"
"runtime"
"strings"
"testing"
. "git.rob.mx/nidito/joao/cmd"
2023-01-11 04:50:06 +00:00
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"
"github.com/sirupsen/logrus"
2023-01-10 07:02:10 +00:00
"github.com/spf13/cobra"
)
2023-01-11 04:50:06 +00:00
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: "56615e9be5f0ce5f97d5b446faaa1d39f95a13a1ea8326ae933c3d29eb29735c",
},
{
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: "nested.string",
Section: &onepassword.ItemSection{ID: "nested", Label: "nested"},
Type: "STRING",
Label: "string",
Value: "quem",
},
{
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.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.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: "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)
}
2023-01-10 07:02:10 +00:00
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
}
2023-01-11 04:50:06 +00:00
func TestGetBadYAML(t *testing.T) {
2023-01-10 07:02:10 +00:00
root := fromProjectRoot()
2023-01-11 04:50:06 +00:00
Get.SetBindings()
2023-01-10 07:02:10 +00:00
out := bytes.Buffer{}
2023-01-11 04:50:06 +00:00
cmd := &cobra.Command{}
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/bad-test.yaml", "."})
if err == nil {
t.Fatalf("Did not throw on bad path: %s", out.String())
}
wantedPrefix := "could not parse file"
wantedSuffix := "/bad-test.yaml as yaml: line 4: mapping values are not allowed in this context"
if got := err.Error(); !(strings.HasPrefix(got, wantedPrefix) && strings.HasSuffix(got, wantedSuffix)) {
t.Fatalf("Failed with bad error, wanted %s /some-path%s, got %s", wantedPrefix, wantedSuffix, got)
}
}
func TestGetBadPath(t *testing.T) {
root := fromProjectRoot()
2023-01-10 07:02:10 +00:00
Get.SetBindings()
2023-01-11 04:50:06 +00:00
out := bytes.Buffer{}
2023-01-10 07:02:10 +00:00
cmd := &cobra.Command{}
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
2023-01-11 04:50:06 +00:00
err := Get.Run(cmd, []string{root + "/does-not-exist.yaml", "."})
if err == nil {
t.Fatalf("Did not throw on bad path: %s", out.String())
}
wantedPrefix := "could not read file"
wantedSuffix := "/does-not-exist.yaml"
if got := err.Error(); !(strings.HasPrefix(got, wantedPrefix) && strings.HasSuffix(got, wantedSuffix)) {
t.Fatalf("Failed with bad error, wanted %s /some-path%s, got %s", wantedPrefix, wantedSuffix, got)
}
}
func TestGetNormal(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", "."})
2023-01-10 07:02:10 +00:00
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected, err := os.ReadFile(root + "/test.yaml")
if err != nil {
t.Fatalf("could not read file: %s", err)
}
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != strings.TrimSpace(string(expected)) {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
2023-01-11 04:50:06 +00:00
func TestGetRedacted(t *testing.T) {
2023-01-10 07:02:10 +00:00
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
2023-01-11 04:50:06 +00:00
cmd.Flags().Bool("redacted", true, "")
2023-01-10 07:02:10 +00:00
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
2023-01-11 04:50:06 +00:00
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--redacted"})
2023-01-10 07:02:10 +00:00
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected, err := os.ReadFile(root + "/test.yaml")
if err != nil {
t.Fatalf("could not read file: %s", err)
}
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != strings.ReplaceAll(strings.TrimSpace(string(expected)), " very secret", "") {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetPath(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
2023-01-11 04:50:06 +00:00
cmd.Flags().StringP("output", "o", "yaml", "")
2023-01-10 07:02:10 +00:00
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", "nested.secret"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected := "very secret"
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != strings.TrimSpace(expected) {
t.Fatalf("did not get expected scalar output:\nwanted: %s\ngot: %s", expected, got)
}
out = bytes.Buffer{}
cmd.SetOut(&out)
cmd.SetErr(&out)
err = Get.Run(cmd, []string{root + "/test.yaml", "nested", "--output", "diff-yaml"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected = `bool: true
int: 1
list:
- 1
- 2
- 3
secret: very secret
string: quem`
if got := out.String(); strings.TrimSpace(got) != strings.TrimSpace(expected) {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetPathCollection(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().StringP("output", "o", "yaml", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", "nested", "--output", "yaml"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected := `bool: true
int: 1
2023-01-11 04:50:06 +00:00
list:
- 1
- 2
- 3
2023-01-10 07:02:10 +00:00
secret: very secret
string: quem`
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetDiff(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().StringP("output", "o", "diff-yaml", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--output", "diff-yaml"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected := `_config: !!joao
name: some:test
vault: example
bool: false
int: 1
list:
- one
- two
- three
nested:
bool: true
int: 1
2023-01-11 04:50:06 +00:00
list:
- 1
- 2
- 3
2023-01-10 07:02:10 +00:00
secret: !!secret very secret
string: quem
secret: !!secret very secret
2023-01-11 04:50:06 +00:00
string: pato`
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetJSON(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().StringP("output", "o", "json", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--output", "json"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
2023-01-11 04:50:06 +00:00
expected := `{"bool":false,"int":1,"list":["one","two","three"],"nested":{"bool":true,"int":1,"list":[1,2,3],"secret":"very secret","string":"quem"},"secret":"very secret","string":"pato"}`
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetJSONPathScalar(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().StringP("output", "o", "json", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", "nested.secret", "--output", "json"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
2023-01-11 04:50:06 +00:00
expected := `very secret` // nolint: ifshort
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetJSONPathCollection(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().StringP("output", "o", "json", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", "nested", "--output", "json"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
2023-01-11 04:50:06 +00:00
expected := `{"bool":true,"int":1,"list":[1,2,3],"secret":"very secret","string":"quem"}`
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetJSONRedacted(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", true, "")
cmd.Flags().StringP("output", "o", "json", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--output", "json", "--redacted"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
2023-01-11 04:50:06 +00:00
expected := `{"bool":false,"int":1,"list":["one","two","three"],"nested":{"bool":true,"int":1,"list":[1,2,3],"secret":"","string":"quem"},"secret":"","string":"pato"}`
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetJSONOP(t *testing.T) {
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().StringP("output", "o", "op", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--output", "op"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
2023-01-11 04:50:06 +00:00
expected := `{"id":"","title":"some:test","vault":{"id":"example"},"category":"PASSWORD","sections":[{"id":"~annotations","label":"~annotations"},{"id":"nested","label":"nested"},{"id":"list","label":"list"}],"fields":[{"id":"password","type":"CONCEALED","purpose":"PASSWORD","label":"password","value":"cedbdf86fb15cf1237569e9b3188372d623aea9d6a707401aca656645590227c"},{"id":"notesPlain","type":"STRING","purpose":"NOTES","label":"notesPlain","value":"flushed by joao"},{"id":"~annotations.int","section":{"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":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"bool","value":"bool"},{"id":"bool","type":"STRING","label":"bool","value":"false"},{"id":"~annotations.secret","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"secret","value":"secret"},{"id":"secret","type":"CONCEALED","label":"secret","value":"very secret"},{"id":"nested.string","section":{"id":"nested"},"type":"STRING","label":"string","value":"quem"},{"id":"~annotations.nested.int","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.int","value":"int"},{"id":"nested.int","section":{"id":"nested"},"type":"STRING","label":"int","value":"1"},{"id":"~annotations.nested.secret","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.secret","value":"secret"},{"id":"nested.secret","section":{"id":"nested"},"type":"CONCEALED","label":"secret","value":"very secret"},{"id":"~annotations.nested.bool","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.bool","value":"bool"},{"id":"nested.bool","section":{"id":"nested"},"type":"STRING","label":"bool","value":"true"},{"id":"~annotations.nested.list.0","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.list.0","value":"int"},{"id":"nested.list.0","section":{"id":"nested"},"type":"STRING","label":"list.0","value":"1"},{"id":"~annotations.nested.list.1","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.list.1","value":"int"},{"id":"nested.list.1","section":{"id":"nested"},"type":"STRING","label":"list.1","value":"2"},{"id":"~annotations.nested.list.2","section":{"id":"~annotations","label":"~annotations"},"type":"STRING","label":"nested.list.2","value":"int"},{"id":"nested.list.2","section":{"id":"nested"},"type":"STRING","label":"list.2","value":"3"},{"id":"list.0","section":{"id":"list"},"type":"STRING","label":"0","value":"one"},{"id":"list.1","section":{"id":"list"},"type":"STRING","label":"1","value":"two"},{"id":"list.2","section":{"id":"list"},"type":"STRING","label":"2","value":"three"}],"createdAt":"0001-01-01T00:00:00Z","updatedAt":"0001-01-01T00:00:00Z"}`
if got := out.String(); strings.TrimSpace(got) != expected {
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}
func TestGetRemote(t *testing.T) {
mockOPConnect(t)
root := fromProjectRoot()
out := bytes.Buffer{}
Get.SetBindings()
cmd := &cobra.Command{}
cmd.Flags().Bool("redacted", false, "")
cmd.Flags().Bool("remote", true, "")
cmd.Flags().StringP("output", "o", "diff-yaml", "")
cmd.SetOut(&out)
cmd.SetErr(&out)
Get.Cobra = cmd
logrus.SetLevel(logrus.DebugLevel)
err := Get.Run(cmd, []string{root + "/test.yaml", ".", "--output", "diff-yaml", "--remote"})
if err != nil {
t.Fatalf("could not get: %s", err)
}
expected := `bool: false
int: 1
list:
- one
- two
- three
nested:
bool: true
int: 1
secret: !!secret very secret
string: quem
secret: !!secret very secret
string: pato`
2023-01-10 07:02:10 +00:00
2023-01-11 04:50:06 +00:00
if got := out.String(); strings.TrimSpace(got) != expected {
2023-01-10 07:02:10 +00:00
t.Fatalf("did not get expected output:\nwanted: %s\ngot: %s", expected, got)
}
}