Skip to content

Commit

Permalink
backport of commit c5d0528 (#19615)
Browse files Browse the repository at this point in the history
Co-authored-by: akshya96 <[email protected]>
  • Loading branch information
1 parent 835123a commit 0efb741
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 1 deletion.
46 changes: 45 additions & 1 deletion api/secret.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ package api

import (
"bytes"
"encoding/json"
"fmt"
"io"
"reflect"
"strings"
"time"

"github.com/hashicorp/errwrap"
Expand Down Expand Up @@ -302,7 +305,15 @@ func ParseSecret(r io.Reader) (*Secret, error) {
// First read the data into a buffer. Not super efficient but we want to
// know if we actually have a body or not.
var buf bytes.Buffer
_, err := buf.ReadFrom(r)

// io.Reader is treated like a stream and cannot be read
// multiple times. Duplicating this stream using TeeReader
// to use this data in case there is no top-level data from
// api response
var teebuf bytes.Buffer
tee := io.TeeReader(r, &teebuf)

_, err := buf.ReadFrom(tee)
if err != nil {
return nil, err
}
Expand All @@ -316,5 +327,38 @@ func ParseSecret(r io.Reader) (*Secret, error) {
return nil, err
}

// If the secret is null, add raw data to secret data if present
if reflect.DeepEqual(secret, Secret{}) {
data := make(map[string]interface{})
if err := jsonutil.DecodeJSONFromReader(&teebuf, &data); err != nil {
return nil, err
}
errRaw, errPresent := data["errors"]

// if only errors are present in the resp.Body return nil
// to return value not found as it does not have any raw data
if len(data) == 1 && errPresent {
return nil, nil
}

// if errors are present along with raw data return the error
if errPresent {
var errStrArray []string
errBytes, err := json.Marshal(errRaw)
if err != nil {
return nil, err
}
if err := json.Unmarshal(errBytes, &errStrArray); err != nil {
return nil, err
}
return nil, fmt.Errorf(strings.Join(errStrArray, " "))
}

// if any raw data is present in resp.Body, add it to secret
if len(data) > 0 {
secret.Data = data
}
}

return &secret, nil
}
3 changes: 3 additions & 0 deletions changelog/17913.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:bug
cli: Fix vault read handling to return raw data as secret.Data when there is no top-level data object from api response.
```
27 changes: 27 additions & 0 deletions command/read_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,33 @@ func TestReadCommand_Run(t *testing.T) {
}
})

t.Run("no_data_object_from_api_response", func(t *testing.T) {
t.Parallel()

client, closer := testVaultServer(t)
defer closer()

ui, cmd := testReadCommand(t)
cmd.client = client

code := cmd.Run([]string{
"sys/health",
})
if exp := 0; code != exp {
t.Errorf("expected %d to be %d", code, exp)
}
combined := ui.OutputWriter.String() + ui.ErrorWriter.String()
expected := []string{
"cluster_id", "cluster_name", "initialized", "performance_standby", "replication_dr_mode", "replication_performance_mode", "sealed",
"server_time_utc", "standby", "version",
}
for _, expectedField := range expected {
if !strings.Contains(combined, expectedField) {
t.Errorf("expected %q to contain %q", combined, expected)
}
}
})

t.Run("no_tabs", func(t *testing.T) {
t.Parallel()

Expand Down

0 comments on commit 0efb741

Please sign in to comment.