diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cc0a0aaa..e3d633ffc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -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 @@ -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 diff --git a/api/accounts/account.gen.go b/api/accounts/account.gen.go index 41eb13686..47e70bd0b 100644 --- a/api/accounts/account.gen.go +++ b/api/accounts/account.gen.go @@ -50,6 +50,11 @@ type AccountDeleteResult struct { response *api.Response } +// GetItem will always be nil for AccountDeleteResult +func (n AccountDeleteResult) GetItem() interface{} { + return nil +} + func (n AccountDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/authmethods/authmethods.gen.go b/api/authmethods/authmethods.gen.go index 9c57afd74..839bc2c34 100644 --- a/api/authmethods/authmethods.gen.go +++ b/api/authmethods/authmethods.gen.go @@ -52,6 +52,11 @@ type AuthMethodDeleteResult struct { response *api.Response } +// GetItem will always be nil for AuthMethodDeleteResult +func (n AuthMethodDeleteResult) GetItem() interface{} { + return nil +} + func (n AuthMethodDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/authtokens/authtokens.gen.go b/api/authtokens/authtokens.gen.go index 09acb6878..1e178bcbc 100644 --- a/api/authtokens/authtokens.gen.go +++ b/api/authtokens/authtokens.gen.go @@ -50,6 +50,11 @@ type AuthTokenDeleteResult struct { response *api.Response } +// GetItem will always be nil for AuthTokenDeleteResult +func (n AuthTokenDeleteResult) GetItem() interface{} { + return nil +} + func (n AuthTokenDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/groups/group.gen.go b/api/groups/group.gen.go index 6d83396ba..e36662236 100644 --- a/api/groups/group.gen.go +++ b/api/groups/group.gen.go @@ -50,6 +50,11 @@ type GroupDeleteResult struct { response *api.Response } +// GetItem will always be nil for GroupDeleteResult +func (n GroupDeleteResult) GetItem() interface{} { + return nil +} + func (n GroupDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/hostcatalogs/host_catalog.gen.go b/api/hostcatalogs/host_catalog.gen.go index f9238a4e8..f047e62f8 100644 --- a/api/hostcatalogs/host_catalog.gen.go +++ b/api/hostcatalogs/host_catalog.gen.go @@ -51,6 +51,11 @@ type HostCatalogDeleteResult struct { response *api.Response } +// GetItem will always be nil for HostCatalogDeleteResult +func (n HostCatalogDeleteResult) GetItem() interface{} { + return nil +} + func (n HostCatalogDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/hosts/host.gen.go b/api/hosts/host.gen.go index f94233355..d0545890c 100644 --- a/api/hosts/host.gen.go +++ b/api/hosts/host.gen.go @@ -51,6 +51,11 @@ type HostDeleteResult struct { response *api.Response } +// GetItem will always be nil for HostDeleteResult +func (n HostDeleteResult) GetItem() interface{} { + return nil +} + func (n HostDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/hostsets/host_set.gen.go b/api/hostsets/host_set.gen.go index a1278da72..96184941f 100644 --- a/api/hostsets/host_set.gen.go +++ b/api/hostsets/host_set.gen.go @@ -51,6 +51,11 @@ type HostSetDeleteResult struct { response *api.Response } +// GetItem will always be nil for HostSetDeleteResult +func (n HostSetDeleteResult) GetItem() interface{} { + return nil +} + func (n HostSetDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/response.go b/api/response.go index 189343e06..43be56709 100644 --- a/api/response.go +++ b/api/response.go @@ -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 diff --git a/api/roles/role.gen.go b/api/roles/role.gen.go index af6d28856..486e01ac7 100644 --- a/api/roles/role.gen.go +++ b/api/roles/role.gen.go @@ -53,6 +53,11 @@ type RoleDeleteResult struct { response *api.Response } +// GetItem will always be nil for RoleDeleteResult +func (n RoleDeleteResult) GetItem() interface{} { + return nil +} + func (n RoleDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/scopes/scope.gen.go b/api/scopes/scope.gen.go index e87b45d22..1f34be548 100644 --- a/api/scopes/scope.gen.go +++ b/api/scopes/scope.gen.go @@ -50,6 +50,11 @@ type ScopeDeleteResult struct { response *api.Response } +// GetItem will always be nil for ScopeDeleteResult +func (n ScopeDeleteResult) GetItem() interface{} { + return nil +} + func (n ScopeDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/sessions/session.gen.go b/api/sessions/session.gen.go index 2d68a6b95..59e4e7abc 100644 --- a/api/sessions/session.gen.go +++ b/api/sessions/session.gen.go @@ -58,6 +58,11 @@ type SessionDeleteResult struct { response *api.Response } +// GetItem will always be nil for SessionDeleteResult +func (n SessionDeleteResult) GetItem() interface{} { + return nil +} + func (n SessionDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/targets/target.gen.go b/api/targets/target.gen.go index 4f9c528e1..6acf813a7 100644 --- a/api/targets/target.gen.go +++ b/api/targets/target.gen.go @@ -55,6 +55,11 @@ type TargetDeleteResult struct { response *api.Response } +// GetItem will always be nil for TargetDeleteResult +func (n TargetDeleteResult) GetItem() interface{} { + return nil +} + func (n TargetDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/api/users/user.gen.go b/api/users/user.gen.go index 7473b817d..1ab9ace25 100644 --- a/api/users/user.gen.go +++ b/api/users/user.gen.go @@ -54,6 +54,11 @@ type UserDeleteResult struct { response *api.Response } +// GetItem will always be nil for UserDeleteResult +func (n UserDeleteResult) GetItem() interface{} { + return nil +} + func (n UserDeleteResult) GetResponse() *api.Response { return n.response } diff --git a/internal/api/genapi/templates.go b/internal/api/genapi/templates.go index cd743da58..104854728 100644 --- a/internal/api/genapi/templates.go +++ b/internal/api/genapi/templates.go @@ -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 } diff --git a/internal/cmd/base/format.go b/internal/cmd/base/format.go index d520b5a1a..6280fd980 100644 --- a/internal/cmd/base/format.go +++ b/internal/cmd/base/format.go @@ -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 @@ -229,19 +230,22 @@ 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 { - output := struct { - StatusCode int `json:"status_code"` - Item interface{} `json:"item"` - }{ - Item: item, +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 } - if result.GetResponse() != nil && result.GetResponse().HttpResponse() != nil { - output.StatusCode = result.GetResponse().HttpResponse().StatusCode + output := struct { + StatusCode int `json:"status_code"` + Item json.RawMessage `json:"item,omitempty"` + }{ + 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)) @@ -249,19 +253,36 @@ func (c *Command) PrintJsonItem(result api.GenericResult, item interface{}) bool } // PrintJsonItems prints the given items to the UI in JSON format -func (c *Command) PrintJsonItems(result api.GenericListResult, items []interface{}) bool { - output := struct { - StatusCode int `json:"status_code"` - Items []interface{} `json:"items"` - }{ - Items: items, +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 } - if result.GetResponse() != nil && result.GetResponse().HttpResponse() != nil { - output.StatusCode = result.GetResponse().HttpResponse().StatusCode + // 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 json.RawMessage `json:"items"` + }{ + 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)) diff --git a/internal/cmd/commands/accountscmd/accounts.gen.go b/internal/cmd/commands/accountscmd/accounts.gen.go index 4640e84c4..e75f879b0 100644 --- a/internal/cmd/commands/accountscmd/accounts.gen.go +++ b/internal/cmd/commands/accountscmd/accounts.gen.go @@ -4,7 +4,6 @@ package accountscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -206,8 +205,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -218,11 +215,7 @@ func (c *Command) Run(args []string) int { result, err = accountsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = accountsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = accountsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = accountsClient.List(c.Context, c.FlagAuthMethodId, opts...) @@ -254,41 +247,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*accounts.Account) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*accounts.Account) c.UI.Output(c.printListTable(listedItems)) } @@ -296,13 +273,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*accounts.Account) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*accounts.Account) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/accountscmd/oidc_accounts.gen.go b/internal/cmd/commands/accountscmd/oidc_accounts.gen.go index 672c5aa34..aa8724eb2 100644 --- a/internal/cmd/commands/accountscmd/oidc_accounts.gen.go +++ b/internal/cmd/commands/accountscmd/oidc_accounts.gen.go @@ -214,13 +214,13 @@ func (c *OidcCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*accounts.Account) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*accounts.Account) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/accountscmd/password_accounts.gen.go b/internal/cmd/commands/accountscmd/password_accounts.gen.go index 9077f5dff..c5ceb8f09 100644 --- a/internal/cmd/commands/accountscmd/password_accounts.gen.go +++ b/internal/cmd/commands/accountscmd/password_accounts.gen.go @@ -214,13 +214,13 @@ func (c *PasswordCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*accounts.Account) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*accounts.Account) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/authenticate/funcs.go b/internal/cmd/commands/authenticate/funcs.go index ffd3f808a..4dcf15cbd 100644 --- a/internal/cmd/commands/authenticate/funcs.go +++ b/internal/cmd/commands/authenticate/funcs.go @@ -35,7 +35,7 @@ func saveAndOrPrintToken(c *base.Command, result *authmethods.AuthenticateResult if ok := c.PrintJsonItem(&dummyGenericResponse{ item: token, response: result.GetResponse(), - }, token); !ok { + }); !ok { return base.CommandCliError } return base.CommandSuccess diff --git a/internal/cmd/commands/authmethodscmd/authmethods.gen.go b/internal/cmd/commands/authmethodscmd/authmethods.gen.go index 427582169..6ce403e35 100644 --- a/internal/cmd/commands/authmethodscmd/authmethods.gen.go +++ b/internal/cmd/commands/authmethodscmd/authmethods.gen.go @@ -4,7 +4,6 @@ package authmethodscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -173,8 +172,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -185,11 +182,7 @@ func (c *Command) Run(args []string) int { result, err = authmethodsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = authmethodsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = authmethodsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = authmethodsClient.List(c.Context, c.FlagScopeId, opts...) @@ -221,41 +214,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*authmethods.AuthMethod) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*authmethods.AuthMethod) c.UI.Output(c.printListTable(listedItems)) } @@ -263,13 +240,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*authmethods.AuthMethod) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*authmethods.AuthMethod) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/authmethodscmd/oidc_authmethods.gen.go b/internal/cmd/commands/authmethodscmd/oidc_authmethods.gen.go index bf6963daa..1adc3e08f 100644 --- a/internal/cmd/commands/authmethodscmd/oidc_authmethods.gen.go +++ b/internal/cmd/commands/authmethodscmd/oidc_authmethods.gen.go @@ -229,13 +229,13 @@ func (c *OidcCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*authmethods.AuthMethod) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*authmethods.AuthMethod) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/authmethodscmd/password_authmethods.gen.go b/internal/cmd/commands/authmethodscmd/password_authmethods.gen.go index 1e7d448c0..83b2d72ab 100644 --- a/internal/cmd/commands/authmethodscmd/password_authmethods.gen.go +++ b/internal/cmd/commands/authmethodscmd/password_authmethods.gen.go @@ -219,13 +219,13 @@ func (c *PasswordCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*authmethods.AuthMethod) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*authmethods.AuthMethod) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/authtokenscmd/authtokens.gen.go b/internal/cmd/commands/authtokenscmd/authtokens.gen.go index 4e7923207..1f30377f3 100644 --- a/internal/cmd/commands/authtokenscmd/authtokens.gen.go +++ b/internal/cmd/commands/authtokenscmd/authtokens.gen.go @@ -4,7 +4,6 @@ package authtokenscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -164,8 +163,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -176,11 +173,7 @@ func (c *Command) Run(args []string) int { result, err = authtokensClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = authtokensClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = authtokensClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = authtokensClient.List(c.Context, c.FlagScopeId, opts...) @@ -212,41 +205,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*authtokens.AuthToken) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*authtokens.AuthToken) c.UI.Output(c.printListTable(listedItems)) } @@ -254,13 +231,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*authtokens.AuthToken) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*authtokens.AuthToken) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/groupscmd/groups.gen.go b/internal/cmd/commands/groupscmd/groups.gen.go index 0d3b3e110..10e5252ae 100644 --- a/internal/cmd/commands/groupscmd/groups.gen.go +++ b/internal/cmd/commands/groupscmd/groups.gen.go @@ -4,7 +4,6 @@ package groupscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -241,8 +240,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -259,11 +256,7 @@ func (c *Command) Run(args []string) int { result, err = groupsClient.Update(c.Context, c.FlagId, version, opts...) case "delete": - _, err = groupsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = groupsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = groupsClient.List(c.Context, c.FlagScopeId, opts...) @@ -295,41 +288,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*groups.Group) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*groups.Group) c.UI.Output(c.printListTable(listedItems)) } @@ -337,13 +314,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*groups.Group) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*groups.Group) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostcatalogscmd/hostcatalogs.gen.go b/internal/cmd/commands/hostcatalogscmd/hostcatalogs.gen.go index 5ba1cbeb4..96b348c35 100644 --- a/internal/cmd/commands/hostcatalogscmd/hostcatalogs.gen.go +++ b/internal/cmd/commands/hostcatalogscmd/hostcatalogs.gen.go @@ -4,7 +4,6 @@ package hostcatalogscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -173,8 +172,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -185,11 +182,7 @@ func (c *Command) Run(args []string) int { result, err = hostcatalogsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = hostcatalogsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = hostcatalogsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = hostcatalogsClient.List(c.Context, c.FlagScopeId, opts...) @@ -221,41 +214,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*hostcatalogs.HostCatalog) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*hostcatalogs.HostCatalog) c.UI.Output(c.printListTable(listedItems)) } @@ -263,13 +240,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*hostcatalogs.HostCatalog) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hostcatalogs.HostCatalog) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostcatalogscmd/static_hostcatalogs.gen.go b/internal/cmd/commands/hostcatalogscmd/static_hostcatalogs.gen.go index 12faa906f..f5d4edd9c 100644 --- a/internal/cmd/commands/hostcatalogscmd/static_hostcatalogs.gen.go +++ b/internal/cmd/commands/hostcatalogscmd/static_hostcatalogs.gen.go @@ -217,13 +217,13 @@ func (c *StaticCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*hostcatalogs.HostCatalog) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hostcatalogs.HostCatalog) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostscmd/hosts.gen.go b/internal/cmd/commands/hostscmd/hosts.gen.go index 27f8e7c27..ace10fff0 100644 --- a/internal/cmd/commands/hostscmd/hosts.gen.go +++ b/internal/cmd/commands/hostscmd/hosts.gen.go @@ -4,7 +4,6 @@ package hostscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -184,8 +183,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -196,11 +193,7 @@ func (c *Command) Run(args []string) int { result, err = hostsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = hostsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = hostsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = hostsClient.List(c.Context, c.FlagHostCatalogId, opts...) @@ -232,41 +225,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*hosts.Host) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*hosts.Host) c.UI.Output(c.printListTable(listedItems)) } @@ -274,13 +251,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*hosts.Host) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hosts.Host) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostscmd/static_hosts.gen.go b/internal/cmd/commands/hostscmd/static_hosts.gen.go index 0c53acedb..0332c0f58 100644 --- a/internal/cmd/commands/hostscmd/static_hosts.gen.go +++ b/internal/cmd/commands/hostscmd/static_hosts.gen.go @@ -214,13 +214,13 @@ func (c *StaticCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*hosts.Host) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hosts.Host) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostsetscmd/hostsets.gen.go b/internal/cmd/commands/hostsetscmd/hostsets.gen.go index 5a19c07bf..b7c630ecc 100644 --- a/internal/cmd/commands/hostsetscmd/hostsets.gen.go +++ b/internal/cmd/commands/hostsetscmd/hostsets.gen.go @@ -4,7 +4,6 @@ package hostsetscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -214,8 +213,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -226,11 +223,7 @@ func (c *Command) Run(args []string) int { result, err = hostsetsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = hostsetsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = hostsetsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = hostsetsClient.List(c.Context, c.FlagHostCatalogId, opts...) @@ -262,41 +255,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*hostsets.HostSet) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*hostsets.HostSet) c.UI.Output(c.printListTable(listedItems)) } @@ -304,13 +281,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*hostsets.HostSet) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hostsets.HostSet) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/hostsetscmd/static_hostsets.gen.go b/internal/cmd/commands/hostsetscmd/static_hostsets.gen.go index 6a2c382f4..19c5eaed9 100644 --- a/internal/cmd/commands/hostsetscmd/static_hostsets.gen.go +++ b/internal/cmd/commands/hostsetscmd/static_hostsets.gen.go @@ -212,13 +212,13 @@ func (c *StaticCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*hostsets.HostSet) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*hostsets.HostSet) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/rolescmd/roles.gen.go b/internal/cmd/commands/rolescmd/roles.gen.go index 4d240ff9f..4cb779638 100644 --- a/internal/cmd/commands/rolescmd/roles.gen.go +++ b/internal/cmd/commands/rolescmd/roles.gen.go @@ -4,7 +4,6 @@ package rolescmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -265,8 +264,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -283,11 +280,7 @@ func (c *Command) Run(args []string) int { result, err = rolesClient.Update(c.Context, c.FlagId, version, opts...) case "delete": - _, err = rolesClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = rolesClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = rolesClient.List(c.Context, c.FlagScopeId, opts...) @@ -319,41 +312,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*roles.Role) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*roles.Role) c.UI.Output(c.printListTable(listedItems)) } @@ -361,13 +338,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*roles.Role) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*roles.Role) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/scopescmd/scopes.gen.go b/internal/cmd/commands/scopescmd/scopes.gen.go index 0d15fb770..68b832aa5 100644 --- a/internal/cmd/commands/scopescmd/scopes.gen.go +++ b/internal/cmd/commands/scopescmd/scopes.gen.go @@ -4,7 +4,6 @@ package scopescmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -215,8 +214,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -233,11 +230,7 @@ func (c *Command) Run(args []string) int { result, err = scopesClient.Update(c.Context, c.FlagId, version, opts...) case "delete": - _, err = scopesClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = scopesClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = scopesClient.List(c.Context, c.FlagScopeId, opts...) @@ -269,41 +262,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*scopes.Scope) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*scopes.Scope) c.UI.Output(c.printListTable(listedItems)) } @@ -311,13 +288,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*scopes.Scope) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*scopes.Scope) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/sessionscmd/sessions.gen.go b/internal/cmd/commands/sessionscmd/sessions.gen.go index ca6fec876..a0fe32fa6 100644 --- a/internal/cmd/commands/sessionscmd/sessions.gen.go +++ b/internal/cmd/commands/sessionscmd/sessions.gen.go @@ -209,38 +209,27 @@ func (c *Command) Run(args []string) int { switch c.Func { case "list": - listedItems := listResult.GetItems().([]*sessions.Session) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*sessions.Session) c.UI.Output(c.printListTable(listedItems)) } return base.CommandSuccess } - item := result.GetItem().(*sessions.Session) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*sessions.Session) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/targetscmd/funcs.go b/internal/cmd/commands/targetscmd/funcs.go index 34af0aeb6..0813f7a57 100644 --- a/internal/cmd/commands/targetscmd/funcs.go +++ b/internal/cmd/commands/targetscmd/funcs.go @@ -444,7 +444,7 @@ func printCustomActionOutputImpl(c *Command) (bool, error) { return true, nil case "json": - if ok := c.PrintJsonItem(c.sar, item); !ok { + if ok := c.PrintJsonItem(c.sar); !ok { return false, fmt.Errorf("Error formatting as JSON") } return true, nil diff --git a/internal/cmd/commands/targetscmd/targets.gen.go b/internal/cmd/commands/targetscmd/targets.gen.go index 880a35238..f4fc9a1ed 100644 --- a/internal/cmd/commands/targetscmd/targets.gen.go +++ b/internal/cmd/commands/targetscmd/targets.gen.go @@ -4,7 +4,6 @@ package targetscmd import ( "errors" "fmt" - "net/http" "os" "sync" @@ -220,8 +219,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -232,11 +229,7 @@ func (c *Command) Run(args []string) int { result, err = targetsClient.Read(c.Context, c.FlagId, opts...) case "delete": - _, err = targetsClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = targetsClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = targetsClient.List(c.Context, c.FlagScopeId, opts...) @@ -268,41 +261,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*targets.Target) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*targets.Target) c.UI.Output(c.printListTable(listedItems)) } @@ -310,13 +287,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*targets.Target) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*targets.Target) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/targetscmd/tcp_targets.gen.go b/internal/cmd/commands/targetscmd/tcp_targets.gen.go index a8ba7237d..aa0ebf382 100644 --- a/internal/cmd/commands/targetscmd/tcp_targets.gen.go +++ b/internal/cmd/commands/targetscmd/tcp_targets.gen.go @@ -219,13 +219,13 @@ func (c *TcpCommand) Run(args []string) int { switch c.Func { } - item := result.GetItem().(*targets.Target) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*targets.Target) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/commands/userscmd/users.gen.go b/internal/cmd/commands/userscmd/users.gen.go index f0bf6c42c..5b93677d3 100644 --- a/internal/cmd/commands/userscmd/users.gen.go +++ b/internal/cmd/commands/userscmd/users.gen.go @@ -4,7 +4,6 @@ package userscmd import ( "errors" "fmt" - "net/http" "sync" "github.com/hashicorp/boundary/api" @@ -241,8 +240,6 @@ func (c *Command) Run(args []string) int { return base.CommandUserError } - existed := true - var result api.GenericResult var listResult api.GenericListResult @@ -259,11 +256,7 @@ func (c *Command) Run(args []string) int { result, err = usersClient.Update(c.Context, c.FlagId, version, opts...) case "delete": - _, err = usersClient.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = usersClient.Delete(c.Context, c.FlagId, opts...) case "list": listResult, err = usersClient.List(c.Context, c.FlagScopeId, opts...) @@ -295,41 +288,25 @@ func (c *Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess case "list": - listedItems := listResult.GetItems().([]*users.User) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*users.User) c.UI.Output(c.printListTable(listedItems)) } @@ -337,13 +314,13 @@ func (c *Command) Run(args []string) int { } - item := result.GetItem().(*users.User) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*users.User) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/cmd/gencli/templates.go b/internal/cmd/gencli/templates.go index 29df4bf3f..c72e6ac22 100644 --- a/internal/cmd/gencli/templates.go +++ b/internal/cmd/gencli/templates.go @@ -327,9 +327,6 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int { return base.CommandUserError } - {{ if hasAction .StdActions "delete" }} - existed := true - {{ end }} var result api.GenericResult {{ if hasAction .StdActions "list" }} var listResult api.GenericListResult @@ -351,11 +348,7 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int { {{ end }} {{ if eq $action "delete" }} case "delete": - _, err = {{ $input.Pkg}}Client.Delete(c.Context, c.FlagId, opts...) - if apiErr := api.AsServerError(err); apiErr != nil && apiErr.Response().StatusCode() == http.StatusNotFound { - existed = false - err = nil - } + result, err = {{ $input.Pkg }}Client.Delete(c.Context, c.FlagId, opts...) {{ end }} {{ if eq $action "list" }} case "list": @@ -390,42 +383,26 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int { case "delete": switch base.Format(c.UI) { case "json": - c.UI.Output(fmt.Sprintf("{ \"existed\": %t }", existed)) + if ok := c.PrintJsonItem(result); !ok { + return base.CommandCliError + } case "table": - output := "The delete operation completed successfully" - switch existed { - case true: - output += "." - default: - output += ", however the resource did not exist at the time." - } - c.UI.Output(output) + c.UI.Output("The delete operation completed successfully.") } return base.CommandSuccess {{ end }} {{ if eq $action "list" }} case "list": - listedItems := listResult.GetItems().([]*{{ $input.Pkg }}.{{ camelCase $input.ResourceType }}) switch base.Format(c.UI) { case "json": - switch { - - case len(listedItems) == 0: - c.UI.Output("null") - - default: - items := make([]interface{}, len(listedItems)) - for i, v := range listedItems { - items[i] = v - } - if ok := c.PrintJsonItems(listResult, items); !ok { - return base.CommandCliError - } + if ok := c.PrintJsonItems(listResult); !ok { + return base.CommandCliError } case "table": + listedItems := listResult.GetItems().([]*{{ $input.Pkg }}.{{ camelCase $input.ResourceType }}) c.UI.Output(c.printListTable(listedItems)) } @@ -434,13 +411,13 @@ func (c *{{ camelCase .SubActionPrefix }}Command) Run(args []string) int { {{ end }} } - item := result.GetItem().(*{{ .Pkg }}.{{ camelCase .ResourceType }}) switch base.Format(c.UI) { case "table": + item := result.GetItem().(*{{ .Pkg }}.{{ camelCase .ResourceType }}) c.UI.Output(printItemTable(item)) case "json": - if ok := c.PrintJsonItem(result, item); !ok { + if ok := c.PrintJsonItem(result); !ok { return base.CommandCliError } } diff --git a/internal/servers/controller/handlers/accounts/account_service.go b/internal/servers/controller/handlers/accounts/account_service.go index 8f0444e90..2d228faf3 100644 --- a/internal/servers/controller/handlers/accounts/account_service.go +++ b/internal/servers/controller/handlers/accounts/account_service.go @@ -210,7 +210,7 @@ func (s Service) DeleteAccount(ctx context.Context, req *pbs.DeleteAccountReques if err != nil { return nil, err } - return &pbs.DeleteAccountResponse{}, nil + return nil, nil } // ChangePassword implements the interface pbs.AccountServiceServer. diff --git a/internal/servers/controller/handlers/accounts/account_service_test.go b/internal/servers/controller/handlers/accounts/account_service_test.go index 2c1221f3a..444d77808 100644 --- a/internal/servers/controller/handlers/accounts/account_service_test.go +++ b/internal/servers/controller/handlers/accounts/account_service_test.go @@ -517,14 +517,12 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteAccountRequest{ Id: ac.GetPublicId(), }, - res: &pbs.DeleteAccountResponse{}, }, { name: "Delete an existing oidc account", req: &pbs.DeleteAccountRequest{ Id: oidcA.GetPublicId(), }, - res: &pbs.DeleteAccountResponse{}, }, { name: "Delete bad pw account id", diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service.go b/internal/servers/controller/handlers/authmethods/authmethod_service.go index cc17f0ce0..95723aa3c 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service.go @@ -293,7 +293,7 @@ func (s Service) DeleteAuthMethod(ctx context.Context, req *pbs.DeleteAuthMethod if err != nil { return nil, err } - return &pbs.DeleteAuthMethodResponse{}, nil + return nil, nil } // Authenticate implements the interface pbs.AuthenticationServiceServer. diff --git a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go index 076bb625f..0a3465faa 100644 --- a/internal/servers/controller/handlers/authmethods/authmethod_service_test.go +++ b/internal/servers/controller/handlers/authmethods/authmethod_service_test.go @@ -423,14 +423,12 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteAuthMethodRequest{ Id: pwam.GetPublicId(), }, - res: &pbs.DeleteAuthMethodResponse{}, }, { name: "Delete an Existing OIDC AuthMethod", req: &pbs.DeleteAuthMethodRequest{ Id: oidcam.GetPublicId(), }, - res: &pbs.DeleteAuthMethodResponse{}, }, { name: "Delete bad auth_method id", diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service.go b/internal/servers/controller/handlers/authtokens/authtoken_service.go index 556966c4f..8d5386e1f 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service.go @@ -172,7 +172,7 @@ func (s Service) DeleteAuthToken(ctx context.Context, req *pbs.DeleteAuthTokenRe if err != nil { return nil, err } - return &pbs.DeleteAuthTokenResponse{}, nil + return nil, nil } func (s Service) getFromRepo(ctx context.Context, id string) (*pb.AuthToken, error) { diff --git a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go index 0589fc99f..d68cae9ad 100644 --- a/internal/servers/controller/handlers/authtokens/authtoken_service_test.go +++ b/internal/servers/controller/handlers/authtokens/authtoken_service_test.go @@ -522,7 +522,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteAuthTokenRequest{ Id: at.GetPublicId(), }, - res: &pbs.DeleteAuthTokenResponse{}, }, { name: "Delete bad token id", diff --git a/internal/servers/controller/handlers/groups/group_service.go b/internal/servers/controller/handlers/groups/group_service.go index 45153e772..f56c84f72 100644 --- a/internal/servers/controller/handlers/groups/group_service.go +++ b/internal/servers/controller/handlers/groups/group_service.go @@ -191,7 +191,7 @@ func (s Service) DeleteGroup(ctx context.Context, req *pbs.DeleteGroupRequest) ( if err != nil { return nil, err } - return &pbs.DeleteGroupResponse{}, nil + return nil, nil } // AddGroupMembers implements the interface pbs.GroupServiceServer. diff --git a/internal/servers/controller/handlers/groups/group_service_test.go b/internal/servers/controller/handlers/groups/group_service_test.go index 333b4163b..4ad49b887 100644 --- a/internal/servers/controller/handlers/groups/group_service_test.go +++ b/internal/servers/controller/handlers/groups/group_service_test.go @@ -348,7 +348,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteGroupRequest{ Id: og.GetPublicId(), }, - res: &pbs.DeleteGroupResponse{}, }, { name: "Delete bad group id", @@ -372,7 +371,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteGroupRequest{ Id: pg.GetPublicId(), }, - res: &pbs.DeleteGroupResponse{}, }, { name: "Project Scoped Delete bad group id", diff --git a/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go b/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go index e0b176331..e552dedd6 100644 --- a/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go +++ b/internal/servers/controller/handlers/host_catalogs/host_catalog_service.go @@ -243,7 +243,7 @@ func (s Service) DeleteHostCatalog(ctx context.Context, req *pbs.DeleteHostCatal if err != nil { return nil, err } - return &pbs.DeleteHostCatalogResponse{}, nil + return nil, nil } func (s Service) getFromRepo(ctx context.Context, id string) (*pb.HostCatalog, error) { diff --git a/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go b/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go index 54062e8e6..d7b341bda 100644 --- a/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go +++ b/internal/servers/controller/handlers/host_catalogs/host_catalog_service_test.go @@ -289,7 +289,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteHostCatalogRequest{ Id: hc.GetPublicId(), }, - res: &pbs.DeleteHostCatalogResponse{}, }, { name: "Delete bad id HostCatalog", diff --git a/internal/servers/controller/handlers/host_sets/host_set_service.go b/internal/servers/controller/handlers/host_sets/host_set_service.go index f3a32e7ed..816e99cda 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service.go @@ -174,7 +174,7 @@ func (s Service) DeleteHostSet(ctx context.Context, req *pbs.DeleteHostSetReques if err != nil { return nil, err } - return &pbs.DeleteHostSetResponse{}, nil + return nil, nil } // AddHostSetHosts implements the interface pbs.HostSetServiceServer. diff --git a/internal/servers/controller/handlers/host_sets/host_set_service_test.go b/internal/servers/controller/handlers/host_sets/host_set_service_test.go index 6eeaf1a8c..42707ec89 100644 --- a/internal/servers/controller/handlers/host_sets/host_set_service_test.go +++ b/internal/servers/controller/handlers/host_sets/host_set_service_test.go @@ -242,7 +242,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteHostSetRequest{ Id: h.GetPublicId(), }, - res: &pbs.DeleteHostSetResponse{}, }, { name: "Delete bad id Host Set", diff --git a/internal/servers/controller/handlers/hosts/host_service.go b/internal/servers/controller/handlers/hosts/host_service.go index a5521e5ac..cd1400dbb 100644 --- a/internal/servers/controller/handlers/hosts/host_service.go +++ b/internal/servers/controller/handlers/hosts/host_service.go @@ -172,7 +172,7 @@ func (s Service) DeleteHost(ctx context.Context, req *pbs.DeleteHostRequest) (*p if err != nil { return nil, err } - return &pbs.DeleteHostResponse{}, nil + return nil, nil } func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Host, error) { diff --git a/internal/servers/controller/handlers/hosts/host_service_test.go b/internal/servers/controller/handlers/hosts/host_service_test.go index 2a35d4014..15a172489 100644 --- a/internal/servers/controller/handlers/hosts/host_service_test.go +++ b/internal/servers/controller/handlers/hosts/host_service_test.go @@ -237,7 +237,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteHostRequest{ Id: h.GetPublicId(), }, - res: &pbs.DeleteHostResponse{}, }, { name: "Delete bad id Host", diff --git a/internal/servers/controller/handlers/roles/role_service.go b/internal/servers/controller/handlers/roles/role_service.go index a11deffbd..305c3ea62 100644 --- a/internal/servers/controller/handlers/roles/role_service.go +++ b/internal/servers/controller/handlers/roles/role_service.go @@ -195,7 +195,7 @@ func (s Service) DeleteRole(ctx context.Context, req *pbs.DeleteRoleRequest) (*p if err != nil { return nil, err } - return &pbs.DeleteRoleResponse{}, nil + return nil, nil } // AddRolePrincipals implements the interface pbs.RoleServiceServer. diff --git a/internal/servers/controller/handlers/roles/role_service_test.go b/internal/servers/controller/handlers/roles/role_service_test.go index b04f53294..2408a7a96 100644 --- a/internal/servers/controller/handlers/roles/role_service_test.go +++ b/internal/servers/controller/handlers/roles/role_service_test.go @@ -325,7 +325,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteRoleRequest{ Id: or.GetPublicId(), }, - res: &pbs.DeleteRoleResponse{}, }, { name: "Delete bad role id", @@ -349,7 +348,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteRoleRequest{ Id: pr.GetPublicId(), }, - res: &pbs.DeleteRoleResponse{}, }, { name: "Project Scoped Delete bad Role id", diff --git a/internal/servers/controller/handlers/scopes/scope_service.go b/internal/servers/controller/handlers/scopes/scope_service.go index 3e4af8099..c4c6734b6 100644 --- a/internal/servers/controller/handlers/scopes/scope_service.go +++ b/internal/servers/controller/handlers/scopes/scope_service.go @@ -270,7 +270,7 @@ func (s Service) DeleteScope(ctx context.Context, req *pbs.DeleteScopeRequest) ( if err != nil { return nil, err } - return &pbs.DeleteScopeResponse{}, nil + return nil, nil } func (s Service) getFromRepo(ctx context.Context, id string) (*pb.Scope, error) { diff --git a/internal/servers/controller/handlers/scopes/scope_service_test.go b/internal/servers/controller/handlers/scopes/scope_service_test.go index da546bb30..475e44e1d 100644 --- a/internal/servers/controller/handlers/scopes/scope_service_test.go +++ b/internal/servers/controller/handlers/scopes/scope_service_test.go @@ -495,7 +495,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteScopeRequest{ Id: proj.GetPublicId(), }, - res: &pbs.DeleteScopeResponse{}, }, { name: "Delete bad project id Project", @@ -519,7 +518,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteScopeRequest{ Id: org.GetPublicId(), }, - res: &pbs.DeleteScopeResponse{}, }, { name: "Delete bad org id Org", diff --git a/internal/servers/controller/handlers/targets/target_service.go b/internal/servers/controller/handlers/targets/target_service.go index 8407119c7..dc7ce6fcd 100644 --- a/internal/servers/controller/handlers/targets/target_service.go +++ b/internal/servers/controller/handlers/targets/target_service.go @@ -239,7 +239,7 @@ func (s Service) DeleteTarget(ctx context.Context, req *pbs.DeleteTargetRequest) if err != nil { return nil, err } - return &pbs.DeleteTargetResponse{}, nil + return nil, nil } // AddTargetHostSets implements the interface pbs.TargetServiceServer. diff --git a/internal/servers/controller/handlers/targets/target_service_test.go b/internal/servers/controller/handlers/targets/target_service_test.go index 67b79df6f..f45dec070 100644 --- a/internal/servers/controller/handlers/targets/target_service_test.go +++ b/internal/servers/controller/handlers/targets/target_service_test.go @@ -285,7 +285,6 @@ func TestDelete(t *testing.T) { req: &pbs.DeleteTargetRequest{ Id: tar.GetPublicId(), }, - res: &pbs.DeleteTargetResponse{}, }, { name: "Delete Not Existing Target", diff --git a/website/content/docs/api-clients/api.mdx b/website/content/docs/api-clients/api.mdx index 14e918fae..2311ae096 100644 --- a/website/content/docs/api-clients/api.mdx +++ b/website/content/docs/api-clients/api.mdx @@ -17,7 +17,7 @@ Boundary's current API version is 1; all API paths begin with `/v1/`. ## Status Codes -- `2XX`: Boundary returns a code between `200` and `299` on success. Generally this is `200`, but implementations should be prepared to accept any `2XX` status code as indicating success. If a call returns a `2XX` code that is not `200`, it will follow well-understood semantics for those status codes. +- `2XX`: Boundary returns a code between `200` and `299` on success. Generally this is `200`, but implementations should be prepared to accept any `2XX` status code as indicating success. If a call returns a `2XX` code that is not `200`, it will follow well-understood semantics for those status codes. (Starting with Boundary 0.2.1, `delete` actions return `204` on success.) - `400`: Boundary returns `400` when a command cannot be completed due to invalid user input, except for a properly-formatted identifier that does not map to an existing resource, which will return a `404` as discussed below. - `401`: Boundary returns `401` if no authentication token is provided or if the provided token is invalid. A valid token that simply does not have permission for a resource will return a `403` instead. A token that is invalid or missing, but where the anonymous user (`u_anon`) is able to successfully perform the action, will not return a `401` but instead will return the result of the action. - `403`: Boundary returns `403` if a provided token was valid but does not have the grants required to perform the requested action.