Vault 9800 Fix vault read handling for endpoints with no top-level data object (#17913)
* fix vault read * changing json unmarshal * adding changelog * removing line * removing format=raw * add test * fix tests * add fix for resp.Errors * adding comments
This commit is contained in:
parent
59cec0a96c
commit
22029c696b
|
@ -2,8 +2,11 @@ package api
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
```
|
|
@ -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()
|
||||
|
||||
|
|
Loading…
Reference in New Issue