Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Update delete action behavior and JSON format output #1155

Merged
merged 8 commits into from
Apr 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,24 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.

### Deprecations/Changes

* API `delete` actions now result in a `204` status code and no body when
successful. This was not the case previously due to a technical limitation
which has now been solved.
* When using a `delete` command we now either show success or treat the `404`
error the same as any other `404` error, that is, it results in a non-zero
status code and an error message. This makes `delete` actions behave the same
as other commands, all of which pass through errors to the CLI. Given `-format
json` capability, it's relatively easy to perform a check to see whether an
error was `404` or something else from within scripts, in conjunction with
checking that the returned status code matches the API error status code
(`1`).
* When outputting from the CLI in JSON format, the resource information under
`item` or `items` (depending on the action) now exactly matches the JSON sent
across the wire by the controller, as opposed to matching the Go SDK
representation which could result in some extra fields being shown or fields
having Go-specific types. This includes `delete` actions which previously
would show an object indicating existence, but now show no `item` on success
or the API's `404` error.
* Permissions in new scope default roles have been updated to include support
for `list`, `read:self`, and `delete:self` on `auth-token` resources. This
allows a user to list and manage their own authentication tokens. (As is the
Expand All @@ -16,6 +34,10 @@ Canonical reference for changes, improvements, and bugfixes for Boundary.

### New and Improved

* cli: Match JSON format output with the across-the-wire API JSON format
([PR](https://github.com/hashicorp/boundary/pull/1155))
* api: Return `204` instead of an empty object on successful `delete` operations
([PR](https://github.com/hashicorp/boundary/pull/1155))
* actions: The new `no-op` action allows a grant to be given to a principals
without conveying any actionable result. Since resources do not appear in list
results if the principal has no actions granted on that resource, this can be
Expand Down
5 changes: 5 additions & 0 deletions api/accounts/account.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/authmethods/authmethods.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/authtokens/authtokens.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/groups/group.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/hostcatalogs/host_catalog.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/hosts/host.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/hostsets/host_set.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions api/response.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ func (r *Response) Decode(inStruct interface{}) (*Error, error) {
}
defer r.resp.Body.Close()

// Always allocate this buffer. It's okay if the bytes return `nil`.
r.Body = new(bytes.Buffer)

if r.resp.StatusCode == 204 {
// Do nothing.
return nil, nil
Expand Down
5 changes: 5 additions & 0 deletions api/roles/role.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/scopes/scope.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/sessions/session.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/targets/target.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions api/users/user.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions internal/api/genapi/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -569,6 +569,11 @@ type {{ .Name }}DeleteResult struct {
response *api.Response
}

// GetItem will always be nil for {{ .Name }}DeleteResult
func (n {{ .Name }}DeleteResult) GetItem() interface{} {
return nil
}

func (n {{ .Name }}DeleteResult) GetResponse() *api.Response {
return n.response
}
Expand Down
53 changes: 37 additions & 16 deletions internal/cmd/base/format.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"github.com/hashicorp/boundary/api/scopes"
"github.com/mitchellh/cli"
"github.com/mitchellh/go-wordwrap"
"github.com/pkg/errors"
)

// This is adapted from the code in the strings package for TrimSpace
Expand Down Expand Up @@ -229,39 +230,59 @@ func (c *Command) PrintCliError(err error) {
}

// PrintJsonItem prints the given item to the UI in JSON format
func (c *Command) PrintJsonItem(result api.GenericResult, item interface{}) bool {
func (c *Command) PrintJsonItem(result api.GenericResult) bool {
resp := result.GetResponse()
if resp == nil {
c.PrintCliError(errors.New("Error formatting as JSON: no response given to item formatter"))
return false
}
output := struct {
StatusCode int `json:"status_code"`
Item interface{} `json:"item"`
StatusCode int `json:"status_code"`
Item json.RawMessage `json:"item,omitempty"`
}{
Item: item,
}
if result.GetResponse() != nil && result.GetResponse().HttpResponse() != nil {
output.StatusCode = result.GetResponse().HttpResponse().StatusCode
StatusCode: resp.HttpResponse().StatusCode,
Item: resp.Body.Bytes(),
}
b, err := JsonFormatter{}.Format(output)
if err != nil {
c.PrintCliError(err)
c.PrintCliError(fmt.Errorf("Error formatting as JSON: %w", err))
return false
}
c.UI.Output(string(b))
return true
}

// PrintJsonItems prints the given items to the UI in JSON format
func (c *Command) PrintJsonItems(result api.GenericListResult, items []interface{}) bool {
func (c *Command) PrintJsonItems(result api.GenericListResult) bool {
resp := result.GetResponse()
if resp == nil {
c.PrintCliError(errors.New("Error formatting as JSON: no response given to items formatter"))
return false
}
// First we need to grab the items out. The reason is that if we simply
// embed the raw message as with PrintJsonItem above, it will have {"items":
// {"items": []}}. However, we decode into a RawMessage which makes it much
// more efficient on both the decoding and encoding side.
type inMsg struct {
Items json.RawMessage `json:"items"`
}
var input inMsg
if resp.Body.Bytes() != nil {
if err := json.Unmarshal(resp.Body.Bytes(), &input); err != nil {
c.PrintCliError(fmt.Errorf("Error unmarshaling response body at format time: %w", err))
return false
}
}
output := struct {
StatusCode int `json:"status_code"`
Items []interface{} `json:"items"`
StatusCode int `json:"status_code"`
Items json.RawMessage `json:"items"`
}{
Items: items,
}
if result.GetResponse() != nil && result.GetResponse().HttpResponse() != nil {
output.StatusCode = result.GetResponse().HttpResponse().StatusCode
StatusCode: resp.HttpResponse().StatusCode,
Items: input.Items,
}
b, err := JsonFormatter{}.Format(output)
if err != nil {
c.PrintCliError(err)
c.PrintCliError(fmt.Errorf("Error formatting as JSON: %w", err))
return false
}
c.UI.Output(string(b))
Expand Down
43 changes: 10 additions & 33 deletions internal/cmd/commands/accountscmd/accounts.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions internal/cmd/commands/accountscmd/oidc_accounts.gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading