Generate new version of SDK resources and Add Tests (#331)
This commit is contained in:
1 parent
96e4b1cdba
commit
c3ecea172d
93 files changed
+3414
-2826
No files matched your search
+27
-25
@@ -27,27 +27,42 @@ type Account struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, authMethodId string, opt ...Option) (*Account, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s/accounts", authMethodId), opts.postMap, apiOpts...)
|
||||
opts.postMap["auth_method_id"] = authMethodId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "accounts", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -72,22 +87,17 @@ func (c *Client) Create(ctx context.Context, authMethodId string, opt ...Option)
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, authMethodId string, accountId string, opt ...Option) (*Account, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into Read request")
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, accountId string, opt ...Option) (*Account, *api.Error, error) {
|
||||
if accountId == "" {
|
||||
return nil, nil, fmt.Errorf("empty accountId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty accountId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("auth-methods/%s/accounts/%s", authMethodId, accountId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("accounts/%s", accountId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Read request: %w", err)
|
||||
}
|
||||
@@ -116,10 +126,7 @@ func (c *Client) Read(ctx context.Context, authMethodId string, accountId string
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Update(ctx context.Context, authMethodId string, accountId string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into Update request")
|
||||
}
|
||||
func (c *Client) Update(ctx context.Context, accountId string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if accountId == "" {
|
||||
return nil, nil, fmt.Errorf("empty accountId value passed into Update request")
|
||||
}
|
||||
@@ -133,7 +140,7 @@ func (c *Client) Update(ctx context.Context, authMethodId string, accountId stri
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, authMethodId, accountId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, accountId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -148,7 +155,7 @@ func (c *Client) Update(ctx context.Context, authMethodId string, accountId stri
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("auth-methods/%s/accounts/%s", authMethodId, accountId), opts.postMap, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("accounts/%s", accountId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Update request: %w", err)
|
||||
}
|
||||
@@ -177,22 +184,17 @@ func (c *Client) Update(ctx context.Context, authMethodId string, accountId stri
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, authMethodId string, accountId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return false, nil, fmt.Errorf("empty authMethodId value passed into Delete request")
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, accountId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if accountId == "" {
|
||||
return false, nil, fmt.Errorf("empty accountId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("auth-methods/%s/accounts/%s", authMethodId, accountId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("accounts/%s", accountId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error creating Delete request: %w", err)
|
||||
}
|
||||
@@ -228,14 +230,14 @@ func (c *Client) List(ctx context.Context, authMethodId string, opt ...Option) (
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into List request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["auth_method_id"] = authMethodId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("auth-methods/%s/accounts", authMethodId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "GET", "accounts", nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package accounts_test
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
@@ -15,18 +16,21 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAccounts_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
os.Setenv("BOUNDARY_LOG_URLS", "1")
|
||||
os.Setenv("BOUNDARY_DEV_SKIP_AUTHZ", "1")
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
require.NotNil(client)
|
||||
token := tc.Token()
|
||||
require.NotNil(token)
|
||||
client.SetToken(token.Token)
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
amClient := authmethods.NewClient(client)
|
||||
am, apiErr, err := amClient.Create(tc.Context(), "password")
|
||||
am, apiErr, err := amClient.Create(tc.Context(), "password", org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(am)
|
||||
@@ -77,21 +81,15 @@ func comparableSlice(in []*accounts.Account) []accounts.Account {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestAccount_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
amId := token.AuthMethodId
|
||||
accountClient := accounts.NewClient(client)
|
||||
|
||||
checkAccount := func(step string, u *accounts.Account, apiErr *api.Error, err error, wantedName string, wantedVersion uint32) {
|
||||
@@ -111,35 +109,30 @@ func TestAccount_Crud(t *testing.T) {
|
||||
u, apiErr, err := accountClient.Create(tc.Context(), amId, accounts.WithName("foo"), accounts.WithPasswordAccountLoginName("loginname"))
|
||||
checkAccount("create", u, apiErr, err, "foo", 1)
|
||||
|
||||
u, apiErr, err = accountClient.Read(tc.Context(), amId, u.Id)
|
||||
u, apiErr, err = accountClient.Read(tc.Context(), u.Id)
|
||||
checkAccount("read", u, apiErr, err, "foo", 1)
|
||||
|
||||
u, apiErr, err = accountClient.Update(tc.Context(), amId, u.Id, u.Version, accounts.WithName("bar"))
|
||||
u, apiErr, err = accountClient.Update(tc.Context(), u.Id, u.Version, accounts.WithName("bar"))
|
||||
checkAccount("update", u, apiErr, err, "bar", 2)
|
||||
|
||||
u, apiErr, err = accountClient.Update(tc.Context(), amId, u.Id, u.Version, accounts.DefaultName())
|
||||
u, apiErr, err = accountClient.Update(tc.Context(), u.Id, u.Version, accounts.DefaultName())
|
||||
checkAccount("update", u, apiErr, err, "", 3)
|
||||
|
||||
existed, _, err := accountClient.Delete(tc.Context(), amId, u.Id)
|
||||
existed, _, err := accountClient.Delete(tc.Context(), u.Id)
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.True(existed, "Expected existing account when deleted, but it wasn't.")
|
||||
}
|
||||
|
||||
func TestAccount_CustomMethods(t *testing.T) {
|
||||
func TestCustomMethods(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
amId := token.AuthMethodId
|
||||
|
||||
accountClient := accounts.NewClient(client)
|
||||
|
||||
@@ -150,34 +143,28 @@ func TestAccount_CustomMethods(t *testing.T) {
|
||||
|
||||
acct := al[0]
|
||||
|
||||
setAcct, apiErr, err := accountClient.SetPassword(tc.Context(), amId, acct.Id, "setpassword", acct.Version)
|
||||
setAcct, apiErr, err := accountClient.SetPassword(tc.Context(), acct.Id, "setpassword", acct.Version)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(setAcct)
|
||||
assert.Equal(acct.Version+1, setAcct.Version)
|
||||
|
||||
changeAcct, apiErr, err := accountClient.ChangePassword(tc.Context(), amId, acct.Id, "setpassword", "changepassword", setAcct.Version)
|
||||
changeAcct, apiErr, err := accountClient.ChangePassword(tc.Context(), acct.Id, "setpassword", "changepassword", setAcct.Version)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(changeAcct)
|
||||
assert.Equal(setAcct.Version+1, changeAcct.Version)
|
||||
}
|
||||
|
||||
func TestAccount_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
amId := token.AuthMethodId
|
||||
accountClient := accounts.NewClient(client)
|
||||
|
||||
u, apiErr, err := accountClient.Create(tc.Context(), amId, accounts.WithPasswordAccountLoginName("first"))
|
||||
@@ -190,17 +177,17 @@ func TestAccount_Errors(t *testing.T) {
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
_, apiErr, err = accountClient.Read(tc.Context(), amId, password.AccountPrefix+"_doesntexis")
|
||||
_, apiErr, err = accountClient.Read(tc.Context(), password.AccountPrefix+"_doesntexis")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
|
||||
_, apiErr, err = accountClient.Read(tc.Context(), amId, "invalid id")
|
||||
_, apiErr, err = accountClient.Read(tc.Context(), "invalid id")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
|
||||
|
||||
_, apiErr, err = accountClient.Update(tc.Context(), amId, u.Id, u.Version)
|
||||
_, apiErr, err = accountClient.Update(tc.Context(), u.Id, u.Version)
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
|
||||
|
||||
@@ -9,10 +9,7 @@ import (
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func (c *Client) ChangePassword(ctx context.Context, authMethodId, accountId, oldPassword, newPassword string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into ChangePassword request")
|
||||
}
|
||||
func (c *Client) ChangePassword(ctx context.Context, accountId, currentPassword, newPassword string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if accountId == "" {
|
||||
return nil, nil, fmt.Errorf("empty accountId value passed into ChangePassword request")
|
||||
}
|
||||
@@ -26,7 +23,7 @@ func (c *Client) ChangePassword(ctx context.Context, authMethodId, accountId, ol
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, authMethodId, accountId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, accountId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -40,12 +37,12 @@ func (c *Client) ChangePassword(ctx context.Context, authMethodId, accountId, ol
|
||||
}
|
||||
|
||||
reqBody := map[string]interface{}{
|
||||
"version": version,
|
||||
"old_password": oldPassword,
|
||||
"new_password": newPassword,
|
||||
"version": version,
|
||||
"current_password": currentPassword,
|
||||
"new_password": newPassword,
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s/accounts/%s:change-password", authMethodId, accountId), reqBody, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("accounts/%s:change-password", accountId), reqBody, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating ChangePassword request: %w", err)
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,10 +9,7 @@ import (
|
||||
"github.com/kr/pretty"
|
||||
)
|
||||
|
||||
func (c *Client) SetPassword(ctx context.Context, authMethodId, accountId, password string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into SetPassword request")
|
||||
}
|
||||
func (c *Client) SetPassword(ctx context.Context, accountId, password string, version uint32, opt ...Option) (*Account, *api.Error, error) {
|
||||
if accountId == "" {
|
||||
return nil, nil, fmt.Errorf("empty accountId value passed into SetPassword request")
|
||||
}
|
||||
@@ -26,7 +23,7 @@ func (c *Client) SetPassword(ctx context.Context, authMethodId, accountId, passw
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, authMethodId, accountId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, accountId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -44,7 +41,7 @@ func (c *Client) SetPassword(ctx context.Context, authMethodId, accountId, passw
|
||||
"password": password,
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s/accounts/%s:set-password", authMethodId, accountId), reqBody, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("accounts/%s:set-password", accountId), reqBody, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating SetPassword request: %w", err)
|
||||
}
|
||||
|
||||
@@ -8,9 +8,7 @@ import (
|
||||
"github.com/hashicorp/boundary/api/authtokens"
|
||||
)
|
||||
|
||||
// TODO: This will need to be changed when we add Auth Method API to boundary. We'll also need a better
|
||||
// way to handle different auth method types.
|
||||
func (c *Client) Authenticate(ctx context.Context, authMethodId, loginName, password string, opt ...Option) (*authtokens.AuthToken, *api.Error, error) {
|
||||
func (c *Client) Authenticate(ctx context.Context, authMethodId string, credentials map[string]interface{}, opt ...Option) (*authtokens.AuthToken, *api.Error, error) {
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client in Authenticate request")
|
||||
}
|
||||
@@ -18,10 +16,7 @@ func (c *Client) Authenticate(ctx context.Context, authMethodId, loginName, pass
|
||||
_, apiOpts := getOpts(opt...)
|
||||
|
||||
reqBody := map[string]interface{}{
|
||||
"credentials": map[string]string{
|
||||
"login_name": loginName,
|
||||
"password": password,
|
||||
},
|
||||
"credentials": credentials,
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("auth-methods/%s:authenticate", authMethodId), reqBody, apiOpts...)
|
||||
|
||||
@@ -15,22 +15,21 @@ func TestAuthenticate(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
methods := authmethods.NewClient(client)
|
||||
|
||||
tok, apiErr, err := methods.Authenticate(tc.Context(), amId, "user", "passpass")
|
||||
tok, apiErr, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr, pretty.Sprint(apiErr))
|
||||
assert.NotNil(tok)
|
||||
|
||||
_, apiErr, err = methods.Authenticate(tc.Context(), amId, "user", "wrong")
|
||||
_, apiErr, err = methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "wrong"})
|
||||
require.NoError(err)
|
||||
require.NotNil(t, apiErr)
|
||||
assert.EqualValuesf(http.StatusUnauthorized, apiErr.Status, "Expected unauthenticated, got %q", apiErr.Message)
|
||||
|
||||
@@ -27,16 +27,31 @@ type AuthMethod struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option) (*AuthMethod, *api.Error, error) {
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, scopeId string, opt ...Option) (*AuthMethod, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -46,10 +61,13 @@ func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option)
|
||||
opts.postMap["type"] = resourceType
|
||||
}
|
||||
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "auth-methods", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -76,9 +94,8 @@ func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option)
|
||||
|
||||
func (c *Client) Read(ctx context.Context, authMethodId string, opt ...Option) (*AuthMethod, *api.Error, error) {
|
||||
if authMethodId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty authMethodId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -176,7 +193,6 @@ func (c *Client) Delete(ctx context.Context, authMethodId string, opt ...Option)
|
||||
if authMethodId == "" {
|
||||
return false, nil, fmt.Errorf("empty authMethodId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -215,12 +231,16 @@ func (c *Client) Delete(ctx context.Context, authMethodId string, opt ...Option)
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*AuthMethod, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*AuthMethod, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "auth-methods", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/hashicorp/boundary/api/accounts"
|
||||
"github.com/hashicorp/boundary/api/authmethods"
|
||||
"github.com/hashicorp/boundary/api/authtokens"
|
||||
"github.com/hashicorp/boundary/api/roles"
|
||||
"github.com/hashicorp/boundary/internal/authtoken"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller"
|
||||
@@ -15,21 +16,41 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestAuthTokens_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
defer tc.Shutdown()
|
||||
|
||||
token := tc.Token()
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
client.SetToken(token.Token)
|
||||
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
amClient := authmethods.NewClient(client)
|
||||
am, apiErr, err := amClient.Create(tc.Context(), "password")
|
||||
am, apiErr, err := amClient.Create(tc.Context(), "password", org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(am)
|
||||
amId := am.Id
|
||||
amId = am.Id
|
||||
|
||||
rolesClient := roles.NewClient(client)
|
||||
role, apiErr, err := rolesClient.Create(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(role)
|
||||
role, apiErr, err = rolesClient.AddPrincipals(tc.Context(), role.Id, 0, []string{"u_anon"}, roles.WithAutomaticVersioning(true))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(role)
|
||||
role, apiErr, err = rolesClient.AddGrants(tc.Context(), role.Id, 0, []string{"type=auth-method;actions=authenticate"}, roles.WithAutomaticVersioning(true))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(role)
|
||||
|
||||
acctClient := accounts.NewClient(client)
|
||||
acct, apiErr, err := acctClient.Create(tc.Context(), amId, accounts.WithPasswordAccountLoginName("user"), accounts.WithPasswordAccountPassword("passpass"))
|
||||
@@ -38,32 +59,32 @@ func TestAuthTokens_List(t *testing.T) {
|
||||
require.NotNil(acct)
|
||||
|
||||
tokens := authtokens.NewClient(client)
|
||||
methods := authmethods.NewClient(client)
|
||||
|
||||
atl, apiErr, err := tokens.List(tc.Context())
|
||||
atl, apiErr, err := tokens.List(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.Empty(atl)
|
||||
|
||||
var expected []*authtokens.AuthToken
|
||||
methods := authmethods.NewClient(client)
|
||||
|
||||
at, apiErr, err := methods.Authenticate(tc.Context(), amId, "user", "passpass")
|
||||
at, apiErr, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
expected = append(expected, at)
|
||||
|
||||
atl, apiErr, err = tokens.List(tc.Context())
|
||||
atl, apiErr, err = tokens.List(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected), comparableSlice(atl))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
at, apiErr, err = methods.Authenticate(tc.Context(), amId, "user", "passpass")
|
||||
at, apiErr, err = methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
expected = append(expected, at)
|
||||
}
|
||||
atl, apiErr, err = tokens.List(tc.Context())
|
||||
atl, apiErr, err = tokens.List(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected), comparableSlice(atl))
|
||||
@@ -92,22 +113,23 @@ func comparableSlice(in []*authtokens.AuthToken) []authtokens.AuthToken {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestAuthToken_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
tokens := authtokens.NewClient(client)
|
||||
methods := authmethods.NewClient(client)
|
||||
|
||||
want, apiErr, err := methods.Authenticate(tc.Context(), amId, "user", "passpass")
|
||||
want, apiErr, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
|
||||
require.NoError(err)
|
||||
assert.Empty(apiErr)
|
||||
|
||||
@@ -122,18 +144,14 @@ func TestAuthToken_Crud(t *testing.T) {
|
||||
assert.True(existed, "Expected existing token when deleted, but it wasn't.")
|
||||
}
|
||||
|
||||
func TestAuthToken_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
tokens := authtokens.NewClient(client)
|
||||
|
||||
_, apiErr, err := tokens.Read(tc.Context(), authtoken.AuthTokenPrefix+"_doesntexis")
|
||||
|
||||
@@ -24,19 +24,28 @@ type AuthToken struct {
|
||||
ExpirationTime time.Time `json:"expiration_time,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, authTokenId string, opt ...Option) (*AuthToken, *api.Error, error) {
|
||||
if authTokenId == "" {
|
||||
return nil, nil, fmt.Errorf("empty authTokenId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty authTokenId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -76,7 +85,6 @@ func (c *Client) Delete(ctx context.Context, authTokenId string, opt ...Option)
|
||||
if authTokenId == "" {
|
||||
return false, nil, fmt.Errorf("empty authTokenId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -115,12 +123,16 @@ func (c *Client) Delete(ctx context.Context, authTokenId string, opt ...Option)
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*AuthToken, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*AuthToken, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "auth-tokens", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,24 +32,15 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
+8
-69
@@ -38,7 +38,6 @@ const EnvBoundaryMaxRetries = "BOUNDARY_MAX_RETRIES"
|
||||
const EnvBoundaryToken = "BOUNDARY_TOKEN"
|
||||
const EnvBoundaryRateLimit = "BOUNDARY_RATE_LIMIT"
|
||||
const EnvBoundarySRVLookup = "BOUNDARY_SRV_LOOKUP"
|
||||
const EnvBoundaryScopeId = "BOUNDARY_SCOPE_ID"
|
||||
|
||||
// Config is used to configure the creation of the client
|
||||
type Config struct {
|
||||
@@ -97,9 +96,6 @@ type Config struct {
|
||||
|
||||
// SRVLookup enables the client to lookup the host through DNS SRV lookup
|
||||
SRVLookup bool
|
||||
|
||||
// ScopeId is the ID of the scope to use if not overridden per-call
|
||||
ScopeId string
|
||||
}
|
||||
|
||||
// TLSConfig contains the parameters needed to configure TLS on the HTTP client
|
||||
@@ -140,7 +136,6 @@ func DefaultConfig() (*Config, error) {
|
||||
HttpClient: cleanhttp.DefaultPooledClient(),
|
||||
Timeout: time.Second * 60,
|
||||
TLSConfig: &TLSConfig{},
|
||||
ScopeId: "global",
|
||||
}
|
||||
|
||||
// We read the environment now; after DefaultClient returns we can override
|
||||
@@ -215,10 +210,9 @@ func (c *Config) ConfigureTLS() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// setAddr parses a given string and looks for scope info, setting the
|
||||
// actual address to the base. Note that if a very malformed URL is passed in,
|
||||
// this may not return what one expects. For now this is on purpose to avoid
|
||||
// requiring error handling.
|
||||
// setAddr parses a given string, setting the actual address to the base. Note
|
||||
// that if a very malformed URL is passed in, this may not return what one
|
||||
// expects. For now this is on purpose to avoid requiring error handling.
|
||||
//
|
||||
// This also removes any trailing "/v1"; we'll use that in our commands so we
|
||||
// don't require it from users.
|
||||
@@ -229,11 +223,12 @@ func (c *Config) setAddr(addr string) error {
|
||||
}
|
||||
c.Addr = fmt.Sprintf("%s://%s", u.Scheme, u.Host)
|
||||
|
||||
// If there is a scopes segment, elide everything after it. Do this only for
|
||||
// the last "scopes" segment in case it's part of the base path.
|
||||
if lastIndex := strings.LastIndex(u.Path, "scopes"); lastIndex != -1 {
|
||||
// If there is a v1 segment, elide everything after it. Do this only for
|
||||
// the last v1 segment in case it's part of the base path.
|
||||
if lastIndex := strings.LastIndex(u.Path, "v1"); lastIndex != -1 {
|
||||
u.Path = u.Path[:lastIndex]
|
||||
}
|
||||
|
||||
// Remove trailing or leading slashes
|
||||
path := strings.Trim(u.Path, "/")
|
||||
// Remove v1 in front or back (e.g. they could have
|
||||
@@ -270,10 +265,6 @@ func (c *Config) ReadEnvironment() error {
|
||||
c.Token = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundaryScopeId); v != "" {
|
||||
c.ScopeId = v
|
||||
}
|
||||
|
||||
if v := os.Getenv(EnvBoundaryMaxRetries); v != "" {
|
||||
maxRetries, err := strconv.ParseUint(v, 10, 32)
|
||||
if err != nil {
|
||||
@@ -439,23 +430,6 @@ func (c *Client) SetAddr(addr string) error {
|
||||
return c.config.setAddr(addr)
|
||||
}
|
||||
|
||||
// ScopeId fetches the scope ID the client will use by default
|
||||
func (c *Client) ScopeId() string {
|
||||
c.modifyLock.RLock()
|
||||
defer c.modifyLock.RUnlock()
|
||||
|
||||
return c.config.ScopeId
|
||||
}
|
||||
|
||||
// Sets the scope ID to use when making calls. This will apply to all calls with
|
||||
// this client unless overridden per request via WithScopeId.
|
||||
func (c *Client) SetScopeId(scopeId string) {
|
||||
c.modifyLock.Lock()
|
||||
defer c.modifyLock.Unlock()
|
||||
|
||||
c.config.ScopeId = scopeId
|
||||
}
|
||||
|
||||
// SetTLSConfig sets the TLS parameters to use and calls ConfigureTLS
|
||||
func (c *Client) SetTLSConfig(conf *TLSConfig) error {
|
||||
c.modifyLock.Lock()
|
||||
@@ -564,7 +538,6 @@ func (c *Client) Clone() *Client {
|
||||
CheckRetry: config.CheckRetry,
|
||||
Limiter: config.Limiter,
|
||||
SRVLookup: config.SRVLookup,
|
||||
ScopeId: config.ScopeId,
|
||||
}
|
||||
if config.TLSConfig != nil {
|
||||
newConfig.TLSConfig = new(TLSConfig)
|
||||
@@ -632,7 +605,6 @@ func (c *Client) NewRequest(ctx context.Context, method, requestPath string, bod
|
||||
|
||||
c.modifyLock.RLock()
|
||||
addr := c.config.Addr
|
||||
scopeId := c.config.ScopeId
|
||||
srvLookup := c.config.SRVLookup
|
||||
token := c.config.Token
|
||||
httpClient := c.config.HttpClient
|
||||
@@ -677,46 +649,13 @@ func (c *Client) NewRequest(ctx context.Context, method, requestPath string, bod
|
||||
}
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
if opts.withScopeId != "" {
|
||||
scopeId = opts.withScopeId
|
||||
}
|
||||
if scopeId == "" {
|
||||
scopeId = "global"
|
||||
}
|
||||
|
||||
var finalPath string
|
||||
switch opts.withNewStyle {
|
||||
case true:
|
||||
// Do nothing. Eventually, remove the notion of a scoped client; calls
|
||||
// to specific resources won't need it, and calls to collections can
|
||||
// take care of it in the functions themselves as part of the api
|
||||
// parameters.
|
||||
finalPath = path.Join(u.Path, "/v1/", requestPath)
|
||||
default:
|
||||
scopedPath := strings.TrimPrefix(requestPath, "/")
|
||||
switch requestPath {
|
||||
case "scopes":
|
||||
// This is a special case for creating or listing scopes; don't do
|
||||
// anything
|
||||
|
||||
default:
|
||||
// If their path already has 'scopes/' in it, use the given request path
|
||||
// instead of building it from the client's scope information
|
||||
if !strings.HasPrefix(scopedPath, "scopes/") {
|
||||
scopedPath = path.Join("scopes", scopeId, scopedPath)
|
||||
}
|
||||
}
|
||||
finalPath = path.Join(u.Path, "/v1", scopedPath)
|
||||
}
|
||||
|
||||
req := &http.Request{
|
||||
Method: method,
|
||||
URL: &url.URL{
|
||||
User: u.User,
|
||||
Scheme: u.Scheme,
|
||||
Host: host,
|
||||
Path: finalPath,
|
||||
Path: path.Join(u.Path, "/v1/", requestPath),
|
||||
},
|
||||
Host: u.Host,
|
||||
}
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ func TestConfigSetAddress(t *testing.T) {
|
||||
},
|
||||
{
|
||||
"longer path project",
|
||||
"http://127.0.0.1:9200/v1/scopes/orgid/auth-methods",
|
||||
"http://127.0.0.1:9200/v1/auth-methods",
|
||||
"http://127.0.0.1:9200",
|
||||
"",
|
||||
},
|
||||
|
||||
+26
-6
@@ -27,24 +27,42 @@ type Group struct {
|
||||
Members []*Member `json:"members,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, opt ...Option) (*Group, *api.Error, error) {
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Group, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "groups", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -71,9 +89,8 @@ func (c *Client) Create(ctx context.Context, opt ...Option) (*Group, *api.Error,
|
||||
|
||||
func (c *Client) Read(ctx context.Context, groupId string, opt ...Option) (*Group, *api.Error, error) {
|
||||
if groupId == "" {
|
||||
return nil, nil, fmt.Errorf("empty groupId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty groupId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -171,7 +188,6 @@ func (c *Client) Delete(ctx context.Context, groupId string, opt ...Option) (boo
|
||||
if groupId == "" {
|
||||
return false, nil, fmt.Errorf("empty groupId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -210,12 +226,16 @@ func (c *Client) Delete(ctx context.Context, groupId string, opt ...Option) (boo
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*Group, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*Group, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "groups", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
+44
-65
@@ -14,52 +14,45 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestGroup_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
grps := groups.NewClient(tt.scopeClient)
|
||||
pl, apiErr, err := grps.List(tc.Context())
|
||||
grps := groups.NewClient(client)
|
||||
pl, apiErr, err := grps.List(tc.Context(), tt.scopeId)
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.Empty(pl)
|
||||
|
||||
expected := make([]*groups.Group, 10)
|
||||
for i := 0; i < 10; i++ {
|
||||
expected[i], apiErr, err = grps.Create(tc.Context(), groups.WithName(fmt.Sprint(i)))
|
||||
expected[i], apiErr, err = grps.Create(tc.Context(), tt.scopeId, groups.WithName(fmt.Sprint(i)))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
}
|
||||
pl, apiErr, err = grps.List(tc.Context())
|
||||
pl, apiErr, err = grps.List(tc.Context(), tt.scopeId)
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
require.NotNil(pl)
|
||||
@@ -84,22 +77,15 @@ func comparableSlice(in []*groups.Group) []groups.Group {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestGroup_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
checkGroup := func(step string, g *groups.Group, apiErr *api.Error, err error, wantedName string, wantedVersion uint32, expectedUserIds []string) {
|
||||
require.NoError(err, step)
|
||||
@@ -120,31 +106,31 @@ func TestGroup_Crud(t *testing.T) {
|
||||
}
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
user1, apiErr, err := users.NewClient(client).Create(tc.Context())
|
||||
user1, apiErr, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
user2, apiErr, err := users.NewClient(client).Create(tc.Context())
|
||||
user2, apiErr, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
groupsClient := groups.NewClient(tt.scopeClient)
|
||||
g, apiErr, err := groupsClient.Create(tc.Context(), groups.WithName("foo"))
|
||||
groupsClient := groups.NewClient(client)
|
||||
g, apiErr, err := groupsClient.Create(tc.Context(), tt.scopeId, groups.WithName("foo"))
|
||||
checkGroup("create", g, apiErr, err, "foo", 1, nil)
|
||||
|
||||
g, apiErr, err = groupsClient.Read(tc.Context(), g.Id)
|
||||
@@ -177,48 +163,41 @@ func TestGroup_Crud(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestGroup_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
groupClient := groups.NewClient(tt.scopeClient)
|
||||
groupClient := groups.NewClient(client)
|
||||
|
||||
g, apiErr, err := groupClient.Create(tc.Context(), groups.WithName("first"))
|
||||
g, apiErr, err := groupClient.Create(tc.Context(), tt.scopeId, groups.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.NotNil(g)
|
||||
|
||||
// Create another resource with the same name.
|
||||
_, apiErr, err = groupClient.Create(tc.Context(), groups.WithName("first"))
|
||||
_, apiErr, err = groupClient.Create(tc.Context(), tt.scopeId, groups.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,16 +27,31 @@ type HostCatalog struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option) (*HostCatalog, *api.Error, error) {
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, scopeId string, opt ...Option) (*HostCatalog, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -46,10 +61,13 @@ func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option)
|
||||
opts.postMap["type"] = resourceType
|
||||
}
|
||||
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "host-catalogs", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -76,9 +94,8 @@ func (c *Client) Create(ctx context.Context, resourceType string, opt ...Option)
|
||||
|
||||
func (c *Client) Read(ctx context.Context, hostCatalogId string, opt ...Option) (*HostCatalog, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -176,7 +193,6 @@ func (c *Client) Delete(ctx context.Context, hostCatalogId string, opt ...Option
|
||||
if hostCatalogId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostCatalogId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -215,12 +231,16 @@ func (c *Client) Delete(ctx context.Context, hostCatalogId string, opt ...Option
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*HostCatalog, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*HostCatalog, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "host-catalogs", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
@@ -14,23 +14,18 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestCatalog_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
catalogClient := hostcatalogs.NewClient(client)
|
||||
|
||||
ul, apiErr, err := catalogClient.List(tc.Context())
|
||||
ul, apiErr, err := catalogClient.List(tc.Context(), proj.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.Empty(ul)
|
||||
@@ -40,21 +35,21 @@ func TestCatalog_List(t *testing.T) {
|
||||
expected = append(expected, &hostcatalogs.HostCatalog{Name: fmt.Sprint(i)})
|
||||
}
|
||||
|
||||
expected[0], apiErr, err = catalogClient.Create(tc.Context(), "static", hostcatalogs.WithName(expected[0].Name))
|
||||
expected[0], apiErr, err = catalogClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName(expected[0].Name))
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
|
||||
ul, apiErr, err = catalogClient.List(tc.Context())
|
||||
ul, apiErr, err = catalogClient.List(tc.Context(), proj.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableCatalogSlice(expected[:1]), comparableCatalogSlice(ul))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
expected[i], apiErr, err = catalogClient.Create(tc.Context(), "static", hostcatalogs.WithName(expected[i].Name))
|
||||
expected[i], apiErr, err = catalogClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName(expected[i].Name))
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
}
|
||||
ul, apiErr, err = catalogClient.List(tc.Context())
|
||||
ul, apiErr, err = catalogClient.List(tc.Context(), proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableCatalogSlice(expected), comparableCatalogSlice(ul))
|
||||
@@ -75,22 +70,15 @@ func comparableCatalogSlice(in []*hostcatalogs.HostCatalog) []hostcatalogs.HostC
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestCatalogs_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
checkCatalog := func(step string, hc *hostcatalogs.HostCatalog, apiErr *api.Error, err error, wantedName string, wantVersion uint32) {
|
||||
require.NoError(err, step)
|
||||
@@ -106,9 +94,9 @@ func TestCatalogs_Crud(t *testing.T) {
|
||||
assert.Equal(wantVersion, hc.Version)
|
||||
}
|
||||
|
||||
hcClient := hostcatalogs.NewClient(projClient)
|
||||
hcClient := hostcatalogs.NewClient(client)
|
||||
|
||||
hc, apiErr, err := hcClient.Create(tc.Context(), "static", hostcatalogs.WithName("foo"))
|
||||
hc, apiErr, err := hcClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
|
||||
checkCatalog("create", hc, apiErr, err, "foo", 1)
|
||||
|
||||
hc, apiErr, err = hcClient.Read(tc.Context(), hc.Id)
|
||||
@@ -131,28 +119,23 @@ func TestCatalogs_Crud(t *testing.T) {
|
||||
}
|
||||
|
||||
// TODO: Get better coverage for expected errors and error formats.
|
||||
func TestCatalogs_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
pc := hostcatalogs.NewClient(client)
|
||||
|
||||
hc, apiErr, err := pc.Create(tc.Context(), "static", hostcatalogs.WithName("foo"))
|
||||
hc, apiErr, err := pc.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.NotNil(hc)
|
||||
|
||||
_, apiErr, err = pc.Create(tc.Context(), "static", hostcatalogs.WithName("foo"))
|
||||
_, apiErr, err = pc.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+27
-25
@@ -28,27 +28,42 @@ type Host struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, hostCatalogId string, opt ...Option) (*Host, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("host-catalogs/%s/hosts", hostCatalogId), opts.postMap, apiOpts...)
|
||||
opts.postMap["host_catalog_id"] = hostCatalogId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "hosts", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -73,22 +88,17 @@ func (c *Client) Create(ctx context.Context, hostCatalogId string, opt ...Option
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, hostCatalogId string, hostId string, opt ...Option) (*Host, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Read request")
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, hostId string, opt ...Option) (*Host, *api.Error, error) {
|
||||
if hostId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty hostId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("host-catalogs/%s/hosts/%s", hostCatalogId, hostId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("hosts/%s", hostId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Read request: %w", err)
|
||||
}
|
||||
@@ -117,10 +127,7 @@ func (c *Client) Read(ctx context.Context, hostCatalogId string, hostId string,
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Update(ctx context.Context, hostCatalogId string, hostId string, version uint32, opt ...Option) (*Host, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Update request")
|
||||
}
|
||||
func (c *Client) Update(ctx context.Context, hostId string, version uint32, opt ...Option) (*Host, *api.Error, error) {
|
||||
if hostId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostId value passed into Update request")
|
||||
}
|
||||
@@ -134,7 +141,7 @@ func (c *Client) Update(ctx context.Context, hostCatalogId string, hostId string
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostCatalogId, hostId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -149,7 +156,7 @@ func (c *Client) Update(ctx context.Context, hostCatalogId string, hostId string
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("host-catalogs/%s/hosts/%s", hostCatalogId, hostId), opts.postMap, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("hosts/%s", hostId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Update request: %w", err)
|
||||
}
|
||||
@@ -178,22 +185,17 @@ func (c *Client) Update(ctx context.Context, hostCatalogId string, hostId string
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, hostCatalogId string, hostId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostCatalogId value passed into Delete request")
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, hostId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if hostId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("host-catalogs/%s/hosts/%s", hostCatalogId, hostId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("hosts/%s", hostId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error creating Delete request: %w", err)
|
||||
}
|
||||
@@ -229,14 +231,14 @@ func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into List request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["host_catalog_id"] = hostCatalogId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("host-catalogs/%s/hosts", hostCatalogId), nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "GET", "hosts", nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
|
||||
+26
-43
@@ -15,22 +15,17 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHost_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
@@ -82,24 +77,17 @@ func comparableHostSlice(in []*hosts.Host) []hosts.Host {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestHost_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(projClient).Create(tc.Context(), "static")
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
@@ -118,47 +106,42 @@ func TestHost_Crud(t *testing.T) {
|
||||
assert.Equal(wantVersion, h.Version)
|
||||
}
|
||||
|
||||
hClient := hosts.NewClient(projClient)
|
||||
hClient := hosts.NewClient(client)
|
||||
|
||||
h, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithName("foo"), hosts.WithStaticHostAddress("someaddress"))
|
||||
checkHost("create", h, apiErr, err, "foo", 1)
|
||||
|
||||
h, apiErr, err = hClient.Read(tc.Context(), hc.Id, h.Id)
|
||||
h, apiErr, err = hClient.Read(tc.Context(), h.Id)
|
||||
checkHost("read", h, apiErr, err, "foo", 1)
|
||||
|
||||
h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hosts.WithName("bar"))
|
||||
h, apiErr, err = hClient.Update(tc.Context(), h.Id, h.Version, hosts.WithName("bar"))
|
||||
checkHost("update", h, apiErr, err, "bar", 2)
|
||||
|
||||
h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hosts.DefaultName())
|
||||
h, apiErr, err = hClient.Update(tc.Context(), h.Id, h.Version, hosts.DefaultName())
|
||||
checkHost("update", h, apiErr, err, "", 3)
|
||||
|
||||
existed, apiErr, err := hClient.Delete(tc.Context(), hc.Id, h.Id)
|
||||
existed, apiErr, err := hClient.Delete(tc.Context(), h.Id)
|
||||
assert.NoError(err)
|
||||
assert.True(existed, "Expected existing catalog when deleted, but it wasn't.")
|
||||
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id)
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), h.Id)
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
}
|
||||
|
||||
// TODO: Get better coverage for expected errors and error formats.
|
||||
func TestHost_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
@@ -174,12 +157,12 @@ func TestHost_Errors(t *testing.T) {
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, static.HostPrefix+"_doesntexis")
|
||||
_, apiErr, err = hClient.Read(tc.Context(), static.HostPrefix+"_doesntexis")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(apiErr.Status, http.StatusForbidden)
|
||||
|
||||
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, "invalid id")
|
||||
_, apiErr, err = hClient.Read(tc.Context(), "invalid id")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
|
||||
|
||||
+2
-12
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+22
-448
@@ -28,252 +28,31 @@ type HostSet struct {
|
||||
Attributes map[string]interface{} `json:"attributes,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, hostCatalogId string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Create request")
|
||||
}
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("host-catalogs/%s/host-sets", hostCatalogId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Create call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Create response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read(ctx context.Context, hostCatalogId string, hostSetId string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Read request")
|
||||
}
|
||||
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("host-catalogs/%s/host-sets/%s", hostCatalogId, hostSetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Read request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Read call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Read response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Update(ctx context.Context, hostCatalogId string, hostSetId string, version uint32, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Update request")
|
||||
}
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into Update request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostCatalogId, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", fmt.Sprintf("host-catalogs/%s/host-sets/%s", hostCatalogId, hostSetId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Update request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Update call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Update response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete(ctx context.Context, hostCatalogId string, hostSetId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostCatalogId value passed into Delete request")
|
||||
}
|
||||
|
||||
if hostSetId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostSetId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("host-catalogs/%s/host-sets/%s", hostCatalogId, hostSetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error creating Delete request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error performing client request during Delete call: %w", err)
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Existed bool
|
||||
}
|
||||
target := &deleteResponse{}
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error decoding Delete response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return false, apiErr, nil
|
||||
}
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option) ([]*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into List request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("host-catalogs/%s/host-sets", hostCatalogId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during List call: %w", err)
|
||||
}
|
||||
|
||||
type listResponse struct {
|
||||
Items []*HostSet
|
||||
}
|
||||
target := &listResponse{}
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding List response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target.Items, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Create2(ctx context.Context, hostCatalogId string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into Create request")
|
||||
}
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -309,7 +88,7 @@ func (c *Client) Create2(ctx context.Context, hostCatalogId string, opt ...Optio
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Read2(ctx context.Context, hostSetId string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
func (c *Client) Read(ctx context.Context, hostSetId string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into Read request")
|
||||
}
|
||||
@@ -318,7 +97,6 @@ func (c *Client) Read2(ctx context.Context, hostSetId string, opt ...Option) (*H
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("host-sets/%s", hostSetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -349,7 +127,7 @@ func (c *Client) Read2(ctx context.Context, hostSetId string, opt ...Option) (*H
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Update2(ctx context.Context, hostSetId string, version uint32, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
func (c *Client) Update(ctx context.Context, hostSetId string, version uint32, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into Update request")
|
||||
}
|
||||
@@ -358,13 +136,12 @@ func (c *Client) Update2(ctx context.Context, hostSetId string, version uint32,
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read2(ctx, hostSetId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -408,7 +185,7 @@ func (c *Client) Update2(ctx context.Context, hostSetId string, version uint32,
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) Delete2(ctx context.Context, hostSetId string, opt ...Option) (bool, *api.Error, error) {
|
||||
func (c *Client) Delete(ctx context.Context, hostSetId string, opt ...Option) (bool, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return false, nil, fmt.Errorf("empty hostSetId value passed into Delete request")
|
||||
}
|
||||
@@ -417,7 +194,6 @@ func (c *Client) Delete2(ctx context.Context, hostSetId string, opt ...Option) (
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("host-sets/%s", hostSetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -451,7 +227,7 @@ func (c *Client) Delete2(ctx context.Context, hostSetId string, opt ...Option) (
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List2(ctx context.Context, hostCatalogId string, opt ...Option) ([]*HostSet, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, hostCatalogId string, opt ...Option) ([]*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into List request")
|
||||
}
|
||||
@@ -460,7 +236,6 @@ func (c *Client) List2(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
opts.queryMap["host_catalog_id"] = hostCatalogId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "host-sets", nil, apiOpts...)
|
||||
@@ -495,10 +270,7 @@ func (c *Client) List2(ctx context.Context, hostCatalogId string, opt ...Option)
|
||||
return target.Items, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) AddHosts(ctx context.Context, hostCatalogId string, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into AddHosts request")
|
||||
}
|
||||
func (c *Client) AddHosts(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into AddHosts request")
|
||||
}
|
||||
@@ -512,203 +284,7 @@ func (c *Client) AddHosts(ctx context.Context, hostCatalogId string, hostSetId s
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into AddHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostCatalogId, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
if len(hostIds) > 0 {
|
||||
opts.postMap["host_ids"] = hostIds
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("host-catalogs/%s/host-sets/%s:add-hosts", hostCatalogId, hostSetId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating AddHosts request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during AddHosts call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding AddHosts response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetHosts(ctx context.Context, hostCatalogId string, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into SetHosts request")
|
||||
}
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into SetHosts request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into SetHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostCatalogId, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
if len(hostIds) > 0 {
|
||||
opts.postMap["host_ids"] = hostIds
|
||||
} else if hostIds != nil {
|
||||
// In this function, a non-nil but empty list means clear out
|
||||
opts.postMap["host_ids"] = nil
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("host-catalogs/%s/host-sets/%s:set-hosts", hostCatalogId, hostSetId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating SetHosts request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during SetHosts call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding SetHosts response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) RemoveHosts(ctx context.Context, hostCatalogId string, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostCatalogId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostCatalogId value passed into RemoveHosts request")
|
||||
}
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into RemoveHosts request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into RemoveHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostCatalogId, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
if len(hostIds) > 0 {
|
||||
opts.postMap["host_ids"] = hostIds
|
||||
}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", fmt.Sprintf("host-catalogs/%s/host-sets/%s:remove-hosts", hostCatalogId, hostSetId), opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating RemoveHosts request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during RemoveHosts call: %w", err)
|
||||
}
|
||||
|
||||
target := new(HostSet)
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding RemoveHosts response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) AddHosts2(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into AddHosts request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into AddHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read2(ctx, hostSetId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -756,7 +332,7 @@ func (c *Client) AddHosts2(ctx context.Context, hostSetId string, version uint32
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) SetHosts2(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
func (c *Client) SetHosts(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into SetHosts request")
|
||||
}
|
||||
@@ -765,13 +341,12 @@ func (c *Client) SetHosts2(ctx context.Context, hostSetId string, version uint32
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into SetHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read2(ctx, hostSetId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -822,7 +397,7 @@ func (c *Client) SetHosts2(ctx context.Context, hostSetId string, version uint32
|
||||
return target, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) RemoveHosts2(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
func (c *Client) RemoveHosts(ctx context.Context, hostSetId string, version uint32, hostIds []string, opt ...Option) (*HostSet, *api.Error, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, nil, fmt.Errorf("empty hostSetId value passed into RemoveHosts request")
|
||||
}
|
||||
@@ -831,13 +406,12 @@ func (c *Client) RemoveHosts2(ctx context.Context, hostSetId string, version uin
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into RemoveHosts request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read2(ctx, hostSetId, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, hostSetId, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
|
||||
+153
-236
@@ -18,129 +18,95 @@ import (
|
||||
)
|
||||
|
||||
func TestCustom(t *testing.T) {
|
||||
for _, newStyle := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("custom_%t", newStyle), func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
token := tc.Token()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client := tc.Client().Clone()
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
hClient := hosts.NewClient(client)
|
||||
h1, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithStaticHostAddress("someaddress"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
h2, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithStaticHostAddress("someaddress"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
hClient := hosts.NewClient(client)
|
||||
h1, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithStaticHostAddress("someaddress"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
h2, apiErr, err := hClient.Create(tc.Context(), hc.Id, hosts.WithStaticHostAddress("someaddress"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
hSetClient := hostsets.NewClient(client)
|
||||
var hSet *hostsets.HostSet
|
||||
if newStyle {
|
||||
hSet, apiErr, err = hSetClient.Create2(tc.Context(), hc.Id)
|
||||
} else {
|
||||
hSet, apiErr, err = hSetClient.Create(tc.Context(), hc.Id)
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
hSetClient := hostsets.NewClient(client)
|
||||
var hSet *hostsets.HostSet
|
||||
hSet, apiErr, err = hSetClient.Create(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
if newStyle {
|
||||
hSet, apiErr, err = hSetClient.AddHosts2(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id, h2.Id})
|
||||
} else {
|
||||
hSet, apiErr, err = hSetClient.AddHosts(tc.Context(), hc.Id, hSet.Id, hSet.Version, []string{h1.Id, h2.Id})
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Contains(hSet.HostIds, h1.Id, h2.Id)
|
||||
hSet, apiErr, err = hSetClient.AddHosts(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id, h2.Id})
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Contains(hSet.HostIds, h1.Id, h2.Id)
|
||||
|
||||
if newStyle {
|
||||
hSet, apiErr, err = hSetClient.SetHosts2(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id})
|
||||
} else {
|
||||
hSet, apiErr, err = hSetClient.SetHosts(tc.Context(), hc.Id, hSet.Id, hSet.Version, []string{h1.Id})
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr, pretty.Sprint(apiErr))
|
||||
assert.ElementsMatch([]string{h1.Id}, hSet.HostIds)
|
||||
hSet, apiErr, err = hSetClient.SetHosts(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id})
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr, pretty.Sprint(apiErr))
|
||||
assert.ElementsMatch([]string{h1.Id}, hSet.HostIds)
|
||||
|
||||
if newStyle {
|
||||
hSet, apiErr, err = hSetClient.RemoveHosts2(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id})
|
||||
} else {
|
||||
hSet, apiErr, err = hSetClient.RemoveHosts(tc.Context(), hc.Id, hSet.Id, hSet.Version, []string{h1.Id})
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Empty(hSet.HostIds)
|
||||
})
|
||||
}
|
||||
hSet, apiErr, err = hSetClient.RemoveHosts(tc.Context(), hSet.Id, hSet.Version, []string{h1.Id})
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Empty(hSet.HostIds)
|
||||
}
|
||||
|
||||
func TestSet_List(t *testing.T) {
|
||||
for _, newStyle := range []bool{false, true} {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
|
||||
hClient := hostsets.NewClient(client)
|
||||
var ul []*hostsets.HostSet
|
||||
hClient := hostsets.NewClient(client)
|
||||
var ul []*hostsets.HostSet
|
||||
|
||||
if newStyle {
|
||||
ul, apiErr, err = hClient.List2(tc.Context(), hc.Id)
|
||||
} else {
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Empty(ul)
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.Empty(ul)
|
||||
|
||||
var expected []*hostsets.HostSet
|
||||
for i := 0; i < 10; i++ {
|
||||
expected = append(expected, &hostsets.HostSet{Name: fmt.Sprint(i)})
|
||||
}
|
||||
|
||||
expected[0], apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName(expected[0].Name))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
if newStyle {
|
||||
ul, apiErr, err = hClient.List2(tc.Context(), hc.Id)
|
||||
} else {
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSetSlice(expected[:1]), comparableSetSlice(ul))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
expected[i], apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName(expected[i].Name))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
}
|
||||
if newStyle {
|
||||
ul, apiErr, err = hClient.List2(tc.Context(), hc.Id)
|
||||
} else {
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSetSlice(expected), comparableSetSlice(ul))
|
||||
var expected []*hostsets.HostSet
|
||||
for i := 0; i < 10; i++ {
|
||||
expected = append(expected, &hostsets.HostSet{Name: fmt.Sprint(i)})
|
||||
}
|
||||
|
||||
expected[0], apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName(expected[0].Name))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSetSlice(expected[:1]), comparableSetSlice(ul))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
expected[i], apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName(expected[i].Name))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
}
|
||||
ul, apiErr, err = hClient.List(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSetSlice(expected), comparableSetSlice(ul))
|
||||
}
|
||||
|
||||
func comparableSetSlice(in []*hostsets.HostSet) []hostsets.HostSet {
|
||||
@@ -158,146 +124,97 @@ func comparableSetSlice(in []*hostsets.HostSet) []hostsets.HostSet {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestSet_Crud(t *testing.T) {
|
||||
for _, newStyle := range []bool{false, true} {
|
||||
t.Run(fmt.Sprintf("crud_%t", newStyle), func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(projClient).Create(tc.Context(), "static")
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
|
||||
checkHost := func(t *testing.T, step string, h *hostsets.HostSet, apiErr *api.Error, err error, wantedName string, wantVersion uint32) {
|
||||
t.Helper()
|
||||
require.NoError(err, step)
|
||||
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
|
||||
t.Errorf("ApiError message: %q", apiErr.Message)
|
||||
}
|
||||
assert.NotNil(h, "returned no resource", step)
|
||||
gotName := ""
|
||||
if h.Name != "" {
|
||||
gotName = h.Name
|
||||
}
|
||||
assert.Equal(wantedName, gotName, step)
|
||||
assert.Equal(wantVersion, h.Version)
|
||||
}
|
||||
|
||||
hClient := hostsets.NewClient(projClient)
|
||||
|
||||
var h *hostsets.HostSet
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Create2(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
} else {
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
}
|
||||
checkHost(t, "create", h, apiErr, err, "foo", 1)
|
||||
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Read2(tc.Context(), h.Id)
|
||||
} else {
|
||||
h, apiErr, err = hClient.Read(tc.Context(), hc.Id, h.Id)
|
||||
}
|
||||
checkHost(t, "read", h, apiErr, err, "foo", 1)
|
||||
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Update2(tc.Context(), h.Id, h.Version, hostsets.WithName("bar"))
|
||||
} else {
|
||||
h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hostsets.WithName("bar"))
|
||||
}
|
||||
checkHost(t, "update", h, apiErr, err, "bar", 2)
|
||||
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Update2(tc.Context(), h.Id, h.Version, hostsets.DefaultName())
|
||||
} else {
|
||||
h, apiErr, err = hClient.Update(tc.Context(), hc.Id, h.Id, h.Version, hostsets.DefaultName())
|
||||
}
|
||||
checkHost(t, "update", h, apiErr, err, "", 3)
|
||||
|
||||
var existed bool
|
||||
if newStyle {
|
||||
existed, apiErr, err = hClient.Delete2(tc.Context(), h.Id)
|
||||
} else {
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id)
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.True(existed, "Expected existing catalog when deleted, but it wasn't.")
|
||||
|
||||
if newStyle {
|
||||
existed, apiErr, err = hClient.Delete2(tc.Context(), h.Id)
|
||||
} else {
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), hc.Id, h.Id)
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
})
|
||||
checkHost := func(t *testing.T, step string, h *hostsets.HostSet, apiErr *api.Error, err error, wantedName string, wantVersion uint32) {
|
||||
t.Helper()
|
||||
require.NoError(err, step)
|
||||
if !assert.Nil(apiErr, step) && apiErr.Message != "" {
|
||||
t.Errorf("ApiError message: %q", apiErr.Message)
|
||||
}
|
||||
assert.NotNil(h, "returned no resource", step)
|
||||
gotName := ""
|
||||
if h.Name != "" {
|
||||
gotName = h.Name
|
||||
}
|
||||
assert.Equal(wantedName, gotName, step)
|
||||
assert.Equal(wantVersion, h.Version)
|
||||
}
|
||||
|
||||
hClient := hostsets.NewClient(client)
|
||||
|
||||
var h *hostsets.HostSet
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
checkHost(t, "create", h, apiErr, err, "foo", 1)
|
||||
|
||||
h, apiErr, err = hClient.Read(tc.Context(), h.Id)
|
||||
checkHost(t, "read", h, apiErr, err, "foo", 1)
|
||||
|
||||
h, apiErr, err = hClient.Update(tc.Context(), h.Id, h.Version, hostsets.WithName("bar"))
|
||||
checkHost(t, "update", h, apiErr, err, "bar", 2)
|
||||
|
||||
h, apiErr, err = hClient.Update(tc.Context(), h.Id, h.Version, hostsets.DefaultName())
|
||||
checkHost(t, "update", h, apiErr, err, "", 3)
|
||||
|
||||
var existed bool
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), h.Id)
|
||||
assert.NoError(err)
|
||||
assert.True(existed, "Expected existing catalog when deleted, but it wasn't.")
|
||||
existed, apiErr, err = hClient.Delete(tc.Context(), h.Id)
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
}
|
||||
|
||||
// TODO: Get better coverage for expected errors and error formats.
|
||||
func TestSet_Errors(t *testing.T) {
|
||||
for _, newStyle := range []bool{false, true} {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hc)
|
||||
|
||||
hClient := hostsets.NewClient(client)
|
||||
hClient := hostsets.NewClient(client)
|
||||
|
||||
var h *hostsets.HostSet
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Create2(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
} else {
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.NotNil(h)
|
||||
var h *hostsets.HostSet
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
assert.NotNil(h)
|
||||
|
||||
if newStyle {
|
||||
h, apiErr, err = hClient.Create2(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
} else {
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.Nil(h)
|
||||
h, apiErr, err = hClient.Create(tc.Context(), hc.Id, hostsets.WithName("foo"))
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.Nil(h)
|
||||
|
||||
if newStyle {
|
||||
_, apiErr, err = hClient.Read2(tc.Context(), static.HostSetPrefix+"_doesntexis")
|
||||
} else {
|
||||
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, static.HostSetPrefix+"_doesntexis")
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
_, apiErr, err = hClient.Read(tc.Context(), static.HostSetPrefix+"_doesntexis")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
|
||||
if newStyle {
|
||||
_, apiErr, err = hClient.Read2(tc.Context(), "invalid id")
|
||||
} else {
|
||||
_, apiErr, err = hClient.Read(tc.Context(), hc.Id, "invalid id")
|
||||
}
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
|
||||
}
|
||||
_, apiErr, err = hClient.Read(tc.Context(), "invalid id")
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
|
||||
}
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,10 @@ type structInfo struct {
|
||||
// the attributes map.
|
||||
subtypeName string
|
||||
|
||||
// For non-top-level collections, this can be used to indicate the name of
|
||||
// the argument that should be used
|
||||
parentTypeName string
|
||||
|
||||
// mappings of names of resources and param names for sub slice types, e.g.
|
||||
// role principals and group members
|
||||
sliceSubTypes map[string]string
|
||||
@@ -76,10 +80,6 @@ type structInfo struct {
|
||||
// given type, e.g. arguments only valid for one call or purpose and not
|
||||
// conveyed within the item itself
|
||||
extraOptions []fieldInfo
|
||||
|
||||
useNewStyle bool
|
||||
|
||||
disableOldStyle bool
|
||||
}
|
||||
|
||||
var inputStructs = []*structInfo{
|
||||
@@ -231,7 +231,8 @@ var inputStructs = []*structInfo{
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
pathArgs: []string{"auth-method", "account"},
|
||||
pathArgs: []string{"account"},
|
||||
parentTypeName: "auth-method",
|
||||
versionEnabled: true,
|
||||
},
|
||||
{
|
||||
@@ -278,7 +279,8 @@ var inputStructs = []*structInfo{
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
pathArgs: []string{"host-catalog", "host"},
|
||||
pathArgs: []string{"host"},
|
||||
parentTypeName: "host-catalog",
|
||||
versionEnabled: true,
|
||||
},
|
||||
{
|
||||
@@ -296,18 +298,13 @@ var inputStructs = []*structInfo{
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
createTemplate2,
|
||||
readTemplate2,
|
||||
updateTemplate2,
|
||||
deleteTemplate2,
|
||||
listTemplate2,
|
||||
},
|
||||
pathArgs: []string{"host-catalog", "host-set"},
|
||||
pathArgs: []string{"host-set"},
|
||||
parentTypeName: "host-catalog",
|
||||
sliceSubTypes: map[string]string{
|
||||
"Hosts": "hostIds",
|
||||
},
|
||||
versionEnabled: true,
|
||||
useNewStyle: true,
|
||||
},
|
||||
{
|
||||
inProto: &targets.HostSet{},
|
||||
@@ -318,19 +315,17 @@ var inputStructs = []*structInfo{
|
||||
outFile: "targets/target.gen.go",
|
||||
templates: []*template.Template{
|
||||
clientTemplate,
|
||||
createTemplate2,
|
||||
readTemplate2,
|
||||
updateTemplate2,
|
||||
deleteTemplate2,
|
||||
listTemplate2,
|
||||
createTemplate,
|
||||
readTemplate,
|
||||
updateTemplate,
|
||||
deleteTemplate,
|
||||
listTemplate,
|
||||
},
|
||||
pathArgs: []string{"target"},
|
||||
sliceSubTypes: map[string]string{
|
||||
"HostSets": "hostSetIds",
|
||||
},
|
||||
versionEnabled: true,
|
||||
typeOnCreate: true,
|
||||
useNewStyle: true,
|
||||
disableOldStyle: true,
|
||||
versionEnabled: true,
|
||||
typeOnCreate: true,
|
||||
},
|
||||
}
|
||||
@@ -39,32 +39,17 @@ func toPath(segments []string, action string) string {
|
||||
return fmt.Sprintf("fmt.Sprintf(\"%s%s\", %s)", strings.Join(printfString, "/"), action, strings.Join(printfArg, ", "))
|
||||
}
|
||||
|
||||
func getArgsAndPaths(in []string, action string) (colArgs, resArgs []string, colPath, resPath string) {
|
||||
var argNames, pathSegment []string
|
||||
for _, s := range in {
|
||||
varName := fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(s, "-", "_")))
|
||||
collectionName := fmt.Sprintf("%ss", s)
|
||||
|
||||
argNames = append(argNames, varName)
|
||||
pathSegment = append(pathSegment, collectionName, varName)
|
||||
}
|
||||
|
||||
colArgs, resArgs, colPath, resPath = argNames[:len(argNames)-1], argNames, toPath(pathSegment[:len(pathSegment)-1], action), toPath(pathSegment, action)
|
||||
|
||||
// Scopes create and list operations always need scope ID
|
||||
if colPath == `"scopes"` {
|
||||
colArgs = append(colArgs, "scopeId")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getArgsAndPathsNewStyle(in []string, action string) (colArg, resArg string, colPath, resPath string) {
|
||||
func getArgsAndPaths(in []string, parentTypeName, action string) (colArg, resArg string, colPath, resPath string) {
|
||||
resArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(in[len(in)-1], "-", "_")))
|
||||
strToReplace := "scope"
|
||||
if len(in) == 1 {
|
||||
colArg = "scopeId"
|
||||
if parentTypeName != "" {
|
||||
strToReplace = parentTypeName
|
||||
}
|
||||
} else {
|
||||
colArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(in[len(in)-2], "-", "_")))
|
||||
strToReplace = in[len(in)-2]
|
||||
}
|
||||
colArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(strToReplace, "-", "_")))
|
||||
colPath = fmt.Sprintf("%ss", in[len(in)-1])
|
||||
|
||||
if action != "" {
|
||||
@@ -75,23 +60,19 @@ func getArgsAndPathsNewStyle(in []string, action string) (colArg, resArg string,
|
||||
}
|
||||
|
||||
type templateInput struct {
|
||||
Name string
|
||||
Package string
|
||||
Fields []fieldInfo
|
||||
PathArgs []string
|
||||
CollectionFunctionArgs []string
|
||||
ResourceFunctionArgs []string
|
||||
CollectionPath string
|
||||
ResourcePath string
|
||||
CollectionFunctionArg2 string
|
||||
ResourceFunctionArg2 string
|
||||
CollectionPath2 string
|
||||
ResourcePath2 string
|
||||
SliceSubTypes map[string]string
|
||||
ExtraOptions []fieldInfo
|
||||
VersionEnabled bool
|
||||
TypeOnCreate bool
|
||||
Two string
|
||||
Name string
|
||||
Package string
|
||||
Fields []fieldInfo
|
||||
PathArgs []string
|
||||
CollectionFunctionArg string
|
||||
ResourceFunctionArg string
|
||||
CollectionPath string
|
||||
ResourcePath string
|
||||
ParentTypeName string
|
||||
SliceSubTypes map[string]string
|
||||
ExtraOptions []fieldInfo
|
||||
VersionEnabled bool
|
||||
TypeOnCreate bool
|
||||
}
|
||||
|
||||
func fillTemplates() {
|
||||
@@ -103,19 +84,14 @@ func fillTemplates() {
|
||||
Package: in.generatedStructure.pkg,
|
||||
Fields: in.generatedStructure.fields,
|
||||
PathArgs: in.pathArgs,
|
||||
ParentTypeName: in.parentTypeName,
|
||||
ExtraOptions: in.extraOptions,
|
||||
VersionEnabled: in.versionEnabled,
|
||||
TypeOnCreate: in.typeOnCreate,
|
||||
Two: "2",
|
||||
}
|
||||
|
||||
if in.useNewStyle && in.disableOldStyle {
|
||||
input.Two = ""
|
||||
}
|
||||
|
||||
if len(in.pathArgs) > 0 {
|
||||
input.CollectionFunctionArgs, input.ResourceFunctionArgs, input.CollectionPath, input.ResourcePath = getArgsAndPaths(in.pathArgs, "")
|
||||
input.CollectionFunctionArg2, input.ResourceFunctionArg2, input.CollectionPath2, input.ResourcePath2 = getArgsAndPathsNewStyle(in.pathArgs, "")
|
||||
input.CollectionFunctionArg, input.ResourceFunctionArg, input.CollectionPath, input.ResourcePath = getArgsAndPaths(in.pathArgs, in.parentTypeName, "")
|
||||
}
|
||||
|
||||
if err := structTemplate.Execute(outBuf, input); err != nil {
|
||||
@@ -125,12 +101,7 @@ func fillTemplates() {
|
||||
|
||||
if len(in.sliceSubTypes) > 0 {
|
||||
input.SliceSubTypes = in.sliceSubTypes
|
||||
if !in.disableOldStyle {
|
||||
in.templates = append(in.templates, sliceSubTypeTemplate)
|
||||
}
|
||||
if in.useNewStyle {
|
||||
in.templates = append(in.templates, sliceSubTypeTemplate2)
|
||||
}
|
||||
in.templates = append(in.templates, sliceSubTypeTemplate)
|
||||
}
|
||||
|
||||
for _, t := range in.templates {
|
||||
@@ -229,24 +200,23 @@ func fillTemplates() {
|
||||
}
|
||||
}
|
||||
|
||||
var listTemplate2 = template.Must(template.New("").Funcs(
|
||||
var listTemplate = template.Must(template.New("").Funcs(
|
||||
template.FuncMap{
|
||||
"snakeCase": snakeCase,
|
||||
},
|
||||
).Parse(`
|
||||
func (c *Client) List{{ .Two }}(ctx context.Context, {{ .CollectionFunctionArg2 }} string, opt... Option) ([]*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .CollectionFunctionArg2 }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg2 }} value passed into List request")
|
||||
func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string, opt... Option) ([]*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .CollectionFunctionArg }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
opts.queryMap["{{ snakeCase .CollectionFunctionArg2 }}"] = {{ .CollectionFunctionArg2 }}
|
||||
opts.queryMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath2 }}", nil, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath }}", nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
@@ -281,101 +251,11 @@ func (c *Client) List{{ .Two }}(ctx context.Context, {{ .CollectionFunctionArg2
|
||||
}
|
||||
`))
|
||||
|
||||
var listTemplate = template.Must(template.New("").Parse(`
|
||||
func (c *Client) List(ctx context.Context, {{ range .CollectionFunctionArgs }} {{ . }} string, {{ end }}opt... Option) ([]*{{ .Name }}, *api.Error, error) { {{ range .CollectionFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ . }} value passed into List request")
|
||||
}
|
||||
{{ end }}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", {{ .CollectionPath }}, nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
{{ if ( eq .CollectionPath "\"scopes\"" ) }}
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
{{ end }}
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during List call: %w", err)
|
||||
}
|
||||
|
||||
type listResponse struct {
|
||||
Items []*{{ .Name }}
|
||||
}
|
||||
target := &listResponse{}
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding List response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target.Items, apiErr, nil
|
||||
}
|
||||
`))
|
||||
|
||||
var readTemplate2 = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Read{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg2 }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Read request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", {{ .ResourcePath2 }}, nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Read request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Read call: %w", err)
|
||||
}
|
||||
|
||||
target := new({{ .Name }})
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Read response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
`))
|
||||
|
||||
var readTemplate = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Read(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .ResourceFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Read request")
|
||||
func (c *Client) Read(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Read request")
|
||||
}
|
||||
{{ end }}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -412,57 +292,11 @@ func (c *Client) Read(ctx context.Context, {{ range .ResourceFunctionArgs }} {{
|
||||
}
|
||||
`))
|
||||
|
||||
var deleteTemplate2 = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Delete{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, opt... Option) (bool, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg2 }} == "" {
|
||||
return false, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Delete request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", {{ .ResourcePath2 }}, nil, apiOpts...)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error creating Delete request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error performing client request during Delete call: %w", err)
|
||||
}
|
||||
|
||||
type deleteResponse struct {
|
||||
Existed bool
|
||||
}
|
||||
target := &deleteResponse{}
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return false, nil, fmt.Errorf("error decoding Delete response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return false, apiErr, nil
|
||||
}
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
`))
|
||||
|
||||
var deleteTemplate = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Delete(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (bool, *api.Error, error) { {{ range .ResourceFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return false, nil, fmt.Errorf("empty {{ . }} value passed into Delete request")
|
||||
func (c *Client) Delete(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (bool, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg }} == "" {
|
||||
return false, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Delete request")
|
||||
}
|
||||
{{ end }}
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -502,17 +336,18 @@ func (c *Client) Delete(ctx context.Context, {{ range .ResourceFunctionArgs }} {
|
||||
}
|
||||
`))
|
||||
|
||||
var createTemplate2 = template.Must(template.New("").Funcs(
|
||||
var createTemplate = template.Must(template.New("").Funcs(
|
||||
template.FuncMap{
|
||||
"snakeCase": snakeCase,
|
||||
},
|
||||
).Parse(`
|
||||
func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ .CollectionFunctionArg2 }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .CollectionFunctionArg2 }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg2 }} value passed into Create request")
|
||||
func (c *Client) Create (ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ .CollectionFunctionArg }} string, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .CollectionFunctionArg }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -522,9 +357,9 @@ func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} r
|
||||
opts.postMap["type"] = resourceType
|
||||
}{{ end }}
|
||||
|
||||
opts.postMap["{{ snakeCase .CollectionFunctionArg2 }}"] = {{ .CollectionFunctionArg2 }}
|
||||
opts.postMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "{{ .CollectionPath2 }}", opts.postMap, apiOpts...)
|
||||
req, err := c.client.NewRequest(ctx, "POST", "{{ .CollectionPath }}", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
@@ -556,121 +391,11 @@ func (c *Client) Create{{ .Two }} (ctx context.Context, {{ if .TypeOnCreate }} r
|
||||
}
|
||||
`))
|
||||
|
||||
var createTemplate = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Create(ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ range .CollectionFunctionArgs }} {{ . }} string, {{ end }} opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .CollectionFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Create request")
|
||||
}
|
||||
{{ end }}opts, apiOpts := getOpts(opt...)
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
{{ if .TypeOnCreate }} if resourceType == "" {
|
||||
return nil, nil, fmt.Errorf("empty resourceType value passed into Create request")
|
||||
} else {
|
||||
opts.postMap["type"] = resourceType
|
||||
}{{ end }}
|
||||
{{ if ( eq .CollectionPath "\"scopes\"" ) }}
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
{{ end }}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", {{ .CollectionPath }}, opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Create call: %w", err)
|
||||
}
|
||||
|
||||
target := new({{ .Name }})
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Create response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
`))
|
||||
|
||||
var updateTemplate2 = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Update{{ .Two }}(ctx context.Context, {{ .ResourceFunctionArg2 }} string, version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg2 }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg2 }} value passed into Update request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
{{ if .VersionEnabled }}
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read{{ .Two }}(ctx, {{ .ResourceFunctionArg2 }}, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
opts.postMap["version"] = version
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "PATCH", {{ .ResourcePath2 }}, opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Update request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during Update call: %w", err)
|
||||
}
|
||||
|
||||
target := new({{ .Name }})
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding Update response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
`))
|
||||
|
||||
var updateTemplate = template.Must(template.New("").Parse(`
|
||||
func (c *Client) Update(ctx context.Context, {{ range .ResourceFunctionArgs }} {{ . }} string, {{ end }}version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) { {{ range .ResourceFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ . }} value passed into Update request")
|
||||
}{{ end }}
|
||||
func (c *Client) Update(ctx context.Context, {{ .ResourceFunctionArg }} string, version uint32, opt... Option) (*{{ .Name }}, *api.Error, error) {
|
||||
if {{ .ResourceFunctionArg }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Update request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -682,7 +407,7 @@ func (c *Client) Update(ctx context.Context, {{ range .ResourceFunctionArgs }} {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ range .ResourceFunctionArgs }} {{ . }}, {{ end }} opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ .ResourceFunctionArg }}, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -741,11 +466,11 @@ var sliceSubTypeTemplate = template.Must(template.New("").Funcs(
|
||||
{{ range $key, $value := $input.SliceSubTypes }}
|
||||
{{ $fullName := print $op $key }}
|
||||
{{ $actionName := kebabCase $fullName }}
|
||||
{{ $resPath := getPathWithAction $input.PathArgs $actionName }}
|
||||
func (c *Client) {{ $fullName }}(ctx context.Context, {{ range $input.ResourceFunctionArgs }} {{ . }} string, {{ end }}version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) { {{ range $input.ResourceFunctionArgs }}
|
||||
if {{ . }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ . }} value passed into {{ $fullName }} request")
|
||||
}{{ end }}
|
||||
{{ $resPath := getPathWithAction $input.PathArgs $input.ParentTypeName $actionName }}
|
||||
func (c *Client) {{ $fullName }}(ctx context.Context, {{ $input.ResourceFunctionArg }} string, version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) {
|
||||
if {{ $input.ResourceFunctionArg }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ $input.ResourceFunctionArg }} value passed into {{ $fullName }} request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -757,92 +482,7 @@ func (c *Client) {{ $fullName }}(ctx context.Context, {{ range $input.ResourceFu
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into {{ $fullName }} request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ range $input.ResourceFunctionArgs }} {{ . }}, {{ end }} opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
if existingApiErr != nil {
|
||||
return nil, nil, fmt.Errorf("error from controller when performing initial check-and-set read: %s", pretty.Sprint(existingApiErr))
|
||||
}
|
||||
if existingTarget == nil {
|
||||
return nil, nil, errors.New("nil resource found when performing initial check-and-set read")
|
||||
}
|
||||
version = existingTarget.Version
|
||||
}
|
||||
{{ end }}
|
||||
opts.postMap["version"] = version
|
||||
|
||||
if len({{ $value }}) > 0 {
|
||||
opts.postMap["{{ snakeCase $value }}"] = {{ $value }}
|
||||
}{{ if ( eq $op "Set" ) }} else if {{ $value }} != nil {
|
||||
// In this function, a non-nil but empty list means clear out
|
||||
opts.postMap["{{ snakeCase $value }}"] = nil
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", {{ $resPath }}, opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating {{ $fullName }} request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
q.Add(k, v)
|
||||
}
|
||||
req.URL.RawQuery = q.Encode()
|
||||
}
|
||||
|
||||
resp, err := c.client.Do(req)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error performing client request during {{ $fullName }} call: %w", err)
|
||||
}
|
||||
|
||||
target := new({{ $input.Name }})
|
||||
apiErr, err := resp.Decode(target)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error decoding {{ $fullName }} response: %w", err)
|
||||
}
|
||||
if apiErr != nil {
|
||||
return nil, apiErr, nil
|
||||
}
|
||||
return target, apiErr, nil
|
||||
}
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
`))
|
||||
|
||||
var sliceSubTypeTemplate2 = template.Must(template.New("").Funcs(
|
||||
template.FuncMap{
|
||||
"makeSlice": makeSlice,
|
||||
"snakeCase": snakeCase,
|
||||
"kebabCase": kebabCase,
|
||||
"getPathWithActionNewStyle": getPathWithActionNewStyle,
|
||||
},
|
||||
).Parse(`
|
||||
{{ $input := . }}
|
||||
{{ range $index, $op := makeSlice "Add" "Set" "Remove" }}
|
||||
{{ range $key, $value := $input.SliceSubTypes }}
|
||||
{{ $fullName := print $op $key }}
|
||||
{{ $actionName := kebabCase $fullName }}
|
||||
{{ $resPath := getPathWithActionNewStyle $input.PathArgs $actionName }}
|
||||
func (c *Client) {{ $fullName }}{{ $input.Two }}(ctx context.Context, {{ $input.ResourceFunctionArg2 }} string, version uint32, {{ $value }} []string, opt... Option) (*{{ $input.Name }}, *api.Error, error) {
|
||||
if {{ $input.ResourceFunctionArg2 }} == "" {
|
||||
return nil, nil, fmt.Errorf("empty {{ $input.ResourceFunctionArg2 }} value passed into {{ $fullName }} request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
{{ if $input.VersionEnabled }}
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
return nil, nil, errors.New("zero version number passed into {{ $fullName }} request")
|
||||
}
|
||||
existingTarget, existingApiErr, existingErr := c.Read{{ $input.Two }}(ctx, {{ $input.ResourceFunctionArg2 }}, opt...)
|
||||
existingTarget, existingApiErr, existingErr := c.Read(ctx, {{ $input.ResourceFunctionArg }}, opt...)
|
||||
if existingErr != nil {
|
||||
return nil, nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
|
||||
}
|
||||
@@ -918,12 +558,22 @@ type {{ .Name }} struct { {{ range .Fields }}
|
||||
`)))
|
||||
|
||||
var clientTemplate = template.Must(template.New("").Parse(`
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{ client: c }
|
||||
return &Client{ client: c.Clone() }
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
`))
|
||||
|
||||
@@ -950,7 +600,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -967,25 +616,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
{{ range .Fields }}
|
||||
@@ -1033,12 +673,7 @@ func kebabCase(in string) string {
|
||||
return strcase.ToKebab(in)
|
||||
}
|
||||
|
||||
func getPathWithAction(resArgs []string, action string) string {
|
||||
_, _, _, resPath := getArgsAndPaths(resArgs, action)
|
||||
return resPath
|
||||
}
|
||||
|
||||
func getPathWithActionNewStyle(resArgs []string, action string) string {
|
||||
_, _, _, resPath := getArgsAndPathsNewStyle(resArgs, action)
|
||||
func getPathWithAction(resArgs []string, parentTypeName, action string) string {
|
||||
_, _, _, resPath := getArgsAndPaths(resArgs, parentTypeName, action)
|
||||
return resPath
|
||||
}
|
||||
+1
-17
@@ -13,24 +13,8 @@ type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withScopeId string
|
||||
withNewStyle bool
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
return options{
|
||||
withScopeId: "",
|
||||
}
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
func WithNewStyle() Option {
|
||||
return func(o *options) {
|
||||
o.withNewStyle = true
|
||||
}
|
||||
return options{}
|
||||
}
|
||||
+2
-12
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-6
@@ -30,24 +30,42 @@ type Role struct {
|
||||
Grants []*Grant `json:"grants,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, opt ...Option) (*Role, *api.Error, error) {
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Role, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "roles", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -74,9 +92,8 @@ func (c *Client) Create(ctx context.Context, opt ...Option) (*Role, *api.Error,
|
||||
|
||||
func (c *Client) Read(ctx context.Context, roleId string, opt ...Option) (*Role, *api.Error, error) {
|
||||
if roleId == "" {
|
||||
return nil, nil, fmt.Errorf("empty roleId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty roleId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -174,7 +191,6 @@ func (c *Client) Delete(ctx context.Context, roleId string, opt ...Option) (bool
|
||||
if roleId == "" {
|
||||
return false, nil, fmt.Errorf("empty roleId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -213,12 +229,16 @@ func (c *Client) Delete(ctx context.Context, roleId string, opt ...Option) (bool
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*Role, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*Role, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "roles", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
+65
-91
@@ -18,36 +18,29 @@ import (
|
||||
|
||||
func TestCustom(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
user, apiErr, err := users.NewClient(client).Create(tc.Context())
|
||||
user, apiErr, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
@@ -69,15 +62,15 @@ func TestCustom(t *testing.T) {
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
g, apiErr, err := groups.NewClient(tt.scopeClient).Create(tc.Context())
|
||||
g, apiErr, err := groups.NewClient(client).Create(tc.Context(), tt.scopeId)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(g)
|
||||
|
||||
rc := roles.NewClient(tt.scopeClient)
|
||||
rc := roles.NewClient(client)
|
||||
var version uint32 = 1
|
||||
|
||||
r, apiErr, err := rc.Create(tc.Context(), roles.WithName("foo"))
|
||||
r, apiErr, err := rc.Create(tc.Context(), tt.scopeId, roles.WithName("foo"))
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(r)
|
||||
@@ -129,65 +122,60 @@ func TestCustom(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRole_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
roleClient := roles.NewClient(tt.scopeClient)
|
||||
p1, apiErr, err := roleClient.List(tc.Context())
|
||||
var expected []*roles.Role
|
||||
|
||||
roleClient := roles.NewClient(client)
|
||||
p1, apiErr, err := roleClient.List(tc.Context(), tt.scopeId)
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
require.Len(p1, 0)
|
||||
require.Len(p1, 1)
|
||||
expected = append(expected, p1[0])
|
||||
|
||||
var expected []*roles.Role
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := 1; i < 11; i++ {
|
||||
expected = append(expected, &roles.Role{Name: fmt.Sprint(i)})
|
||||
}
|
||||
|
||||
expected[0], apiErr, err = roleClient.Create(tc.Context(), roles.WithName(expected[0].Name))
|
||||
expected[1], apiErr, err = roleClient.Create(tc.Context(), tt.scopeId, roles.WithName(expected[1].Name))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
|
||||
p2, apiErr, err := roleClient.List(tc.Context())
|
||||
p2, apiErr, err := roleClient.List(tc.Context(), tt.scopeId)
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(p2))
|
||||
assert.ElementsMatch(comparableSlice(expected[0:2]), comparableSlice(p2))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
expected[i], apiErr, err = roleClient.Create(tc.Context(), roles.WithName(expected[i].Name))
|
||||
for i := 2; i < 11; i++ {
|
||||
expected[i], apiErr, err = roleClient.Create(tc.Context(), tt.scopeId, roles.WithName(expected[i].Name))
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
}
|
||||
p3, apiErr, err := roleClient.List(tc.Context())
|
||||
p3, apiErr, err := roleClient.List(tc.Context(), tt.scopeId)
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected), comparableSlice(p3))
|
||||
@@ -210,34 +198,27 @@ func comparableSlice(in []*roles.Role) []roles.Role {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestRole_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
@@ -257,8 +238,8 @@ func TestRole_Crud(t *testing.T) {
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
roleClient := roles.NewClient(tt.scopeClient)
|
||||
g, apiErr, err := roleClient.Create(tc.Context(), roles.WithName("foo"))
|
||||
roleClient := roles.NewClient(client)
|
||||
g, apiErr, err := roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("foo"))
|
||||
checkRole("create", g, apiErr, err, "foo", 1)
|
||||
|
||||
g, apiErr, err = roleClient.Read(tc.Context(), g.Id)
|
||||
@@ -278,47 +259,40 @@ func TestRole_Crud(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestRole_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
projClient := client.Clone()
|
||||
projClient.SetScopeId(proj.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
scopeClient *api.Client
|
||||
name string
|
||||
scopeId string
|
||||
}{
|
||||
{
|
||||
name: "org",
|
||||
scopeClient: client,
|
||||
name: "org",
|
||||
scopeId: org.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "proj",
|
||||
scopeClient: projClient,
|
||||
name: "proj",
|
||||
scopeId: proj.GetPublicId(),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range cases {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
roleClient := roles.NewClient(tt.scopeClient)
|
||||
u, apiErr, err := roleClient.Create(tc.Context(), roles.WithName("first"))
|
||||
roleClient := roles.NewClient(client)
|
||||
u, apiErr, err := roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.NotNil(u)
|
||||
|
||||
// Create another resource with the same name.
|
||||
_, apiErr, err = roleClient.Create(tc.Context(), roles.WithName("first"))
|
||||
_, apiErr, err = roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
|
||||
@@ -18,7 +18,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -35,25 +34,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+15
-30
@@ -13,20 +13,15 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProjects_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
scps := scopes.NewClient(client)
|
||||
|
||||
@@ -63,20 +58,15 @@ func comparableSlice(in []*scopes.Scope) []scopes.Scope {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestProjects_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, _ := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, _ := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
scps := scopes.NewClient(client)
|
||||
|
||||
@@ -116,20 +106,15 @@ func TestProjects_Crud(t *testing.T) {
|
||||
}
|
||||
|
||||
// TODO: Get better coverage for expected errors and error formats.
|
||||
func TestProject_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org, _ := iam.TestScopes(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org, _ := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
scps := scopes.NewClient(client)
|
||||
|
||||
|
||||
+16
-7
@@ -24,19 +24,31 @@ type Scope struct {
|
||||
Version uint32 `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Scope, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -47,6 +59,7 @@ func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Sc
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -73,9 +86,8 @@ func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*Sc
|
||||
|
||||
func (c *Client) Read(ctx context.Context, scopeId string, opt ...Option) (*Scope, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -173,7 +185,6 @@ func (c *Client) Delete(ctx context.Context, scopeId string, opt ...Option) (boo
|
||||
if scopeId == "" {
|
||||
return false, nil, fmt.Errorf("empty scopeId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -216,20 +227,18 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*Sc
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "scopes", nil, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating List request: %w", err)
|
||||
}
|
||||
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
|
||||
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,20 +29,31 @@ type Target struct {
|
||||
DefaultPort uint32 `json:"default_port,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, resourceType string, scopeId string, opt ...Option) (*Target, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -92,7 +103,6 @@ func (c *Client) Read(ctx context.Context, targetId string, opt ...Option) (*Tar
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", fmt.Sprintf("targets/%s", targetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -132,7 +142,6 @@ func (c *Client) Update(ctx context.Context, targetId string, version uint32, op
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
@@ -191,7 +200,6 @@ func (c *Client) Delete(ctx context.Context, targetId string, opt ...Option) (bo
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "DELETE", fmt.Sprintf("targets/%s", targetId), nil, apiOpts...)
|
||||
if err != nil {
|
||||
@@ -234,7 +242,6 @@ func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*Ta
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "targets", nil, apiOpts...)
|
||||
@@ -278,7 +285,6 @@ func (c *Client) AddHostSets(ctx context.Context, targetId string, version uint3
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
@@ -341,7 +347,6 @@ func (c *Client) SetHostSets(ctx context.Context, targetId string, version uint3
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
@@ -407,7 +412,6 @@ func (c *Client) RemoveHostSets(ctx context.Context, targetId string, version ui
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
apiOpts = append(apiOpts, api.WithNewStyle())
|
||||
|
||||
if version == 0 {
|
||||
if !opts.withAutomaticVersioning {
|
||||
|
||||
@@ -24,18 +24,18 @@ func TestCustom(t *testing.T) {
|
||||
token := tc.Token()
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client := tc.Client().Clone()
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
client.SetToken(token.Token)
|
||||
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static")
|
||||
hc, apiErr, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
|
||||
hSetClient := hostsets.NewClient(client)
|
||||
hSet, apiErr, err := hSetClient.Create2(tc.Context(), hc.Id)
|
||||
hSet, apiErr, err := hSetClient.Create(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hSet)
|
||||
hSet2, apiErr, err := hSetClient.Create2(tc.Context(), hc.Id)
|
||||
hSet2, apiErr, err := hSetClient.Create(tc.Context(), hc.Id)
|
||||
require.NoError(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(hSet2)
|
||||
@@ -73,8 +73,8 @@ func TestList(t *testing.T) {
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
client.SetScopeId(proj.GetPublicId())
|
||||
|
||||
tarClient := targets.NewClient(client)
|
||||
ul, apiErr, err := tarClient.List(tc.Context(), proj.GetPublicId())
|
||||
@@ -129,6 +129,7 @@ func TestCrud(t *testing.T) {
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
checkResource := func(t *testing.T, step string, h *targets.Target, apiErr *api.Error, err error, wantedName string, wantVersion uint32) {
|
||||
@@ -175,6 +176,7 @@ func TestSet_Errors(t *testing.T) {
|
||||
|
||||
client := tc.Client()
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
|
||||
tarClient := targets.NewClient(client)
|
||||
|
||||
+2
-12
@@ -16,7 +16,6 @@ type Option func(*options)
|
||||
type options struct {
|
||||
postMap map[string]interface{}
|
||||
queryMap map[string]string
|
||||
withScopeId string
|
||||
withAutomaticVersioning bool
|
||||
}
|
||||
|
||||
@@ -33,25 +32,16 @@ func getOpts(opt ...Option) (options, []api.Option) {
|
||||
o(&opts)
|
||||
}
|
||||
var apiOpts []api.Option
|
||||
if opts.withScopeId != "" {
|
||||
apiOpts = append(apiOpts, api.WithScopeId(opts.withScopeId))
|
||||
}
|
||||
return opts, apiOpts
|
||||
}
|
||||
|
||||
func WithScopeId(id string) Option {
|
||||
return func(o *options) {
|
||||
o.withScopeId = id
|
||||
}
|
||||
}
|
||||
|
||||
// If set, and if the version is zero during an update, the API will perform a
|
||||
// fetch to get the current version of the resource and populate it during the
|
||||
// update call. This is convenient but opens up the possibility for subtle
|
||||
// order-of-modification issues, so use carefully.
|
||||
func WithAutomaticVersioning() Option {
|
||||
func WithAutomaticVersioning(enable bool) Option {
|
||||
return func(o *options) {
|
||||
o.withAutomaticVersioning = true
|
||||
o.withAutomaticVersioning = enable
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-6
@@ -25,24 +25,42 @@ type User struct {
|
||||
Version uint32 `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// Client is a client for this collection
|
||||
type Client struct {
|
||||
client *api.Client
|
||||
}
|
||||
|
||||
// Creates a new client for this collection. The submitted API client is cloned;
|
||||
// modifications to it after generating this client will not have effect. If you
|
||||
// need to make changes to the underlying API client, use ApiClient() to access
|
||||
// it.
|
||||
func NewClient(c *api.Client) *Client {
|
||||
return &Client{client: c}
|
||||
return &Client{client: c.Clone()}
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, opt ...Option) (*User, *api.Error, error) {
|
||||
// ApiClient returns the underlying API client
|
||||
func (c *Client) ApiClient() *api.Client {
|
||||
return c.client
|
||||
}
|
||||
|
||||
func (c *Client) Create(ctx context.Context, scopeId string, opt ...Option) (*User, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into Create request")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts.postMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "POST", "users", opts.postMap, apiOpts...)
|
||||
if err != nil {
|
||||
return nil, nil, fmt.Errorf("error creating Create request: %w", err)
|
||||
}
|
||||
|
||||
if len(opts.queryMap) > 0 {
|
||||
q := url.Values{}
|
||||
for k, v := range opts.queryMap {
|
||||
@@ -69,9 +87,8 @@ func (c *Client) Create(ctx context.Context, opt ...Option) (*User, *api.Error,
|
||||
|
||||
func (c *Client) Read(ctx context.Context, userId string, opt ...Option) (*User, *api.Error, error) {
|
||||
if userId == "" {
|
||||
return nil, nil, fmt.Errorf("empty userId value passed into Read request")
|
||||
return nil, nil, fmt.Errorf("empty userId value passed into Read request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -169,7 +186,6 @@ func (c *Client) Delete(ctx context.Context, userId string, opt ...Option) (bool
|
||||
if userId == "" {
|
||||
return false, nil, fmt.Errorf("empty userId value passed into Delete request")
|
||||
}
|
||||
|
||||
if c.client == nil {
|
||||
return false, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
@@ -208,12 +224,16 @@ func (c *Client) Delete(ctx context.Context, userId string, opt ...Option) (bool
|
||||
return target.Existed, apiErr, nil
|
||||
}
|
||||
|
||||
func (c *Client) List(ctx context.Context, opt ...Option) ([]*User, *api.Error, error) {
|
||||
func (c *Client) List(ctx context.Context, scopeId string, opt ...Option) ([]*User, *api.Error, error) {
|
||||
if scopeId == "" {
|
||||
return nil, nil, fmt.Errorf("empty scopeId value passed into List request")
|
||||
}
|
||||
if c.client == nil {
|
||||
return nil, nil, fmt.Errorf("nil client")
|
||||
}
|
||||
|
||||
opts, apiOpts := getOpts(opt...)
|
||||
opts.queryMap["scope_id"] = scopeId
|
||||
|
||||
req, err := c.client.NewRequest(ctx, "GET", "users", nil, apiOpts...)
|
||||
if err != nil {
|
||||
|
||||
+23
-38
@@ -13,23 +13,18 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestUsers_List(t *testing.T) {
|
||||
func TestList(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
userClient := users.NewClient(client)
|
||||
|
||||
ul, apiErr, err := userClient.List(tc.Context())
|
||||
ul, apiErr, err := userClient.List(tc.Context(), org.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.Empty(ul)
|
||||
@@ -39,21 +34,21 @@ func TestUsers_List(t *testing.T) {
|
||||
expected = append(expected, &users.User{Name: fmt.Sprint(i)})
|
||||
}
|
||||
|
||||
expected[0], apiErr, err = userClient.Create(tc.Context(), users.WithName(expected[0].Name))
|
||||
expected[0], apiErr, err = userClient.Create(tc.Context(), org.GetPublicId(), users.WithName(expected[0].Name))
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
|
||||
ul, apiErr, err = userClient.List(tc.Context())
|
||||
ul, apiErr, err = userClient.List(tc.Context(), org.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ul))
|
||||
|
||||
for i := 1; i < 10; i++ {
|
||||
expected[i], apiErr, err = userClient.Create(tc.Context(), users.WithName(expected[i].Name))
|
||||
expected[i], apiErr, err = userClient.Create(tc.Context(), org.GetPublicId(), users.WithName(expected[i].Name))
|
||||
assert.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
}
|
||||
ul, apiErr, err = userClient.List(tc.Context())
|
||||
ul, apiErr, err = userClient.List(tc.Context(), org.GetPublicId())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul))
|
||||
@@ -74,20 +69,15 @@ func comparableSlice(in []*users.User) []users.User {
|
||||
return filtered
|
||||
}
|
||||
|
||||
func TestUser_Crud(t *testing.T) {
|
||||
func TestCrud(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
userClient := users.NewClient(client)
|
||||
|
||||
checkUser := func(step string, u *users.User, apiErr *api.Error, err error, wantedName string, wantedVersion uint32) {
|
||||
@@ -104,7 +94,7 @@ func TestUser_Crud(t *testing.T) {
|
||||
assert.EqualValues(wantedVersion, u.Version)
|
||||
}
|
||||
|
||||
u, apiErr, err := userClient.Create(tc.Context(), users.WithName("foo"))
|
||||
u, apiErr, err := userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("foo"))
|
||||
checkUser("create", u, apiErr, err, "foo", 1)
|
||||
|
||||
u, apiErr, err = userClient.Read(tc.Context(), u.Id)
|
||||
@@ -127,29 +117,24 @@ func TestUser_Crud(t *testing.T) {
|
||||
assert.EqualValues(http.StatusForbidden, apiErr.Status)
|
||||
}
|
||||
|
||||
func TestUser_Errors(t *testing.T) {
|
||||
func TestErrors(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
amId := "ampw_1234567890"
|
||||
tc := controller.NewTestController(t, &controller.TestControllerOpts{
|
||||
DisableAuthorizationFailures: true,
|
||||
DefaultAuthMethodId: amId,
|
||||
DefaultLoginName: "user",
|
||||
DefaultPassword: "passpass",
|
||||
})
|
||||
tc := controller.NewTestController(t, nil)
|
||||
defer tc.Shutdown()
|
||||
|
||||
client := tc.Client()
|
||||
org := iam.TestOrg(t, tc.IamRepo())
|
||||
client.SetScopeId(org.GetPublicId())
|
||||
token := tc.Token()
|
||||
client.SetToken(token.Token)
|
||||
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
|
||||
userClient := users.NewClient(client)
|
||||
|
||||
u, apiErr, err := userClient.Create(tc.Context(), users.WithName("first"))
|
||||
u, apiErr, err := userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
assert.NotNil(u)
|
||||
|
||||
// Create another resource with the same name.
|
||||
_, apiErr, err = userClient.Create(tc.Context(), users.WithName("first"))
|
||||
_, apiErr, err = userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("first"))
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
|
||||
|
||||
+6
-244
@@ -16,7 +16,6 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/common"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/types/action"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/recovery"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
@@ -149,26 +148,12 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
return
|
||||
}
|
||||
|
||||
// check if it's new style
|
||||
if opts.withAction != action.Unknown {
|
||||
v.act = opts.withAction
|
||||
v.res = &perms.Resource{
|
||||
ScopeId: opts.withScopeId,
|
||||
Id: opts.withId,
|
||||
Pin: opts.withPin,
|
||||
Type: opts.withType,
|
||||
}
|
||||
} else {
|
||||
// This remains for legacy
|
||||
v.requestInfo.scopeId = opts.withScopeId
|
||||
if err := v.parseAuthParams(); err != nil {
|
||||
v.logger.Trace("error reading auth parameters from URL", "url", v.requestInfo.Path, "method", v.requestInfo.Method, "error", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if v.res == nil {
|
||||
v.logger.Trace("got nil resource information after decorating auth parameters")
|
||||
return
|
||||
v.act = opts.withAction
|
||||
v.res = &perms.Resource{
|
||||
ScopeId: opts.withScopeId,
|
||||
Id: opts.withId,
|
||||
Pin: opts.withPin,
|
||||
Type: opts.withType,
|
||||
}
|
||||
|
||||
var authResults *perms.ACLResults
|
||||
@@ -192,229 +177,6 @@ func Verify(ctx context.Context, opt ...Option) (ret VerifyResults) {
|
||||
return
|
||||
}
|
||||
|
||||
func (v *verifier) parseAuthParams() error {
|
||||
// Remove trailing and leading slashes
|
||||
trimmedPath := strings.Trim(v.requestInfo.Path, "/")
|
||||
// Remove `v1/`
|
||||
splitPath := strings.Split(strings.TrimPrefix(trimmedPath, "v1/"), "/")
|
||||
splitLen := len(splitPath)
|
||||
|
||||
// It must be at least length 1. If so, figure out new vs. legacy parsing
|
||||
if len(splitPath) == 0 {
|
||||
return fmt.Errorf("parse auth params: invalid path")
|
||||
}
|
||||
|
||||
for i := 1; i < splitLen; i++ {
|
||||
if splitPath[i] == "" {
|
||||
return fmt.Errorf("parse auth params: empty segment found")
|
||||
}
|
||||
}
|
||||
|
||||
// The first segment must be "scopes"
|
||||
if splitPath[0] != "scopes" {
|
||||
return fmt.Errorf("parse auth params: invalid first segment %q", splitPath[0])
|
||||
}
|
||||
|
||||
v.act = action.Unknown
|
||||
v.res = &perms.Resource{
|
||||
// Start out with scope, and replace when we walk backwards if it's
|
||||
// actually something else
|
||||
Type: resource.Scope,
|
||||
}
|
||||
|
||||
// Handle non-custom types. We'll deal with custom types, including list,
|
||||
// after parsing the path.
|
||||
switch v.requestInfo.Method {
|
||||
case "GET":
|
||||
v.act = action.Read
|
||||
case "POST":
|
||||
v.act = action.Create
|
||||
case "PATCH":
|
||||
v.act = action.Update
|
||||
case "DELETE":
|
||||
v.act = action.Delete
|
||||
default:
|
||||
return fmt.Errorf("parse auth params: unknown method %q", v.requestInfo.Method)
|
||||
}
|
||||
|
||||
// Look for a custom action
|
||||
colonSplit := strings.Split(splitPath[splitLen-1], ":")
|
||||
switch len(colonSplit) {
|
||||
case 1:
|
||||
// No custom action specified
|
||||
|
||||
case 2:
|
||||
// Parse and validate the action, then elide it
|
||||
actStr := colonSplit[len(colonSplit)-1]
|
||||
v.act = action.Map[actStr]
|
||||
if v.act == action.Unknown || v.act == action.All {
|
||||
return fmt.Errorf("parse auth params: unknown action %q", actStr)
|
||||
}
|
||||
// Keep going with the logic without the custom action
|
||||
splitPath[splitLen-1] = colonSplit[0]
|
||||
|
||||
default:
|
||||
return fmt.Errorf("parse auth params: unexpected number of colons in last segment %q", colonSplit[len(colonSplit)-1])
|
||||
}
|
||||
|
||||
// Get scope information and handle it in a special case; that is, for
|
||||
// operating on scopes, scope from the request ID, not the path scope
|
||||
switch splitLen {
|
||||
case 1:
|
||||
// We've already validated that this is "scopes"
|
||||
if v.act == action.Read {
|
||||
v.act = action.List
|
||||
}
|
||||
if v.requestInfo.scopeId == "" {
|
||||
return errors.New("parse auth params: missing scope ID information for scopes collection operation")
|
||||
}
|
||||
v.res.ScopeId = v.requestInfo.scopeId
|
||||
return nil
|
||||
|
||||
case 2:
|
||||
id := splitPath[1]
|
||||
// The next segment should be the scope ID, but it takes place not in
|
||||
// its own scope but in the parent scope. Rather than require the user
|
||||
// to provide it, look up the parent.
|
||||
switch {
|
||||
case id == "global", strings.HasPrefix(id, scope.Org.Prefix()):
|
||||
// Org scope parent is always global. Set scope for global
|
||||
// operations to global as well (it's basically acting as its own
|
||||
// parent scope). We want this so that users can e.g. modify the
|
||||
// name or description of the global scope if they have permissions
|
||||
// in the scope.
|
||||
v.res.ScopeId = "global"
|
||||
|
||||
default:
|
||||
// Project case
|
||||
iamRepo, err := v.iamRepoFn()
|
||||
if err != nil {
|
||||
return fmt.Errorf("perform auth check: failed to get iam repo: %w", err)
|
||||
}
|
||||
|
||||
scp, err := iamRepo.LookupScope(v.ctx, id)
|
||||
if err != nil {
|
||||
return fmt.Errorf("perform auth check: failed to lookup scope: %w", err)
|
||||
}
|
||||
if scp == nil {
|
||||
return fmt.Errorf("perform auth check: non-existent scope %q", id)
|
||||
}
|
||||
v.res.ScopeId = scp.GetParentId()
|
||||
}
|
||||
v.res.Id = id
|
||||
return nil
|
||||
|
||||
case 3:
|
||||
// If a custom action was being performed within a scope, it will have
|
||||
// been elided above. If the last path segment is now empty, address
|
||||
// this scenario. In this case the action took place _in_ the scope so
|
||||
// it should be bound accordingly. (This is for actions like
|
||||
// /scopes/o_abc/:deauthenticate where the action is _in_ the scope, not
|
||||
// on the scope.)
|
||||
if splitPath[2] == "" {
|
||||
v.res.ScopeId = splitPath[1]
|
||||
v.res.Id = splitPath[1]
|
||||
return nil
|
||||
}
|
||||
|
||||
fallthrough
|
||||
|
||||
default:
|
||||
// In all other cases the scope ID is the next segment
|
||||
v.res.ScopeId = splitPath[1]
|
||||
}
|
||||
|
||||
// Walk backwards. As we walk backwards we look for a pin and figure out if
|
||||
// we're operating on a resource or a collection. The rules for the pin are
|
||||
// as follows:
|
||||
//
|
||||
// * If the last segment is a collection, the pin is the immediately
|
||||
// preceding ID. This does not include scopes since those are permission
|
||||
// boundaries.
|
||||
//
|
||||
// * If the last segment is an ID, the pin is the immediately preceding ID
|
||||
// not including the last segment
|
||||
//
|
||||
// * If at the end of the logic the pin is the id of a scope then there is
|
||||
// no pin. The scopes are already enclosing so a pin is redundant.
|
||||
nextIdIsPin := true
|
||||
// Use an empty string so we can detect if we found anything in this loop.
|
||||
var foundId string
|
||||
var typStr string
|
||||
// We stop at [2] because we've already dealt with the first two segments
|
||||
// (scopes/<scope_id> above.
|
||||
for i := splitLen - 1; i >= 2; i-- {
|
||||
segment := splitPath[i]
|
||||
|
||||
if segment == "" {
|
||||
return fmt.Errorf("parse auth parameters: unexpected empty segment")
|
||||
}
|
||||
|
||||
// If the segment contains whitespace, it's not valid
|
||||
if fields := strings.Fields(segment); len(fields) != 1 || fields[0] != segment {
|
||||
return fmt.Errorf("parse auth params: segment %q contains whitespace", segment)
|
||||
}
|
||||
|
||||
// Collections don't contain underscores; every resource ID does.
|
||||
segmentIsCollection := !strings.Contains(segment, "_")
|
||||
|
||||
// If we see an ID, ensure that it's not the right-most ID; if not, it's
|
||||
// the pin
|
||||
if !segmentIsCollection && i != splitLen-1 && nextIdIsPin {
|
||||
v.res.Pin = segment
|
||||
// By definition this is the last thing we'd be looking for as
|
||||
// scopes were found above, so we can now break out
|
||||
break
|
||||
}
|
||||
|
||||
if typStr == "" {
|
||||
// The resource check takes place inside the type check because if
|
||||
// we've identified the type we have either already identified the
|
||||
// right-most resource ID or we're operating on a collection, so
|
||||
// this prevents us from finding a different ID earlier in the path.
|
||||
// We still work backwards to identify a pin.
|
||||
if foundId == "" && !segmentIsCollection {
|
||||
foundId = segment
|
||||
} else {
|
||||
// Every collection is the plural of the resource type so drop
|
||||
// the last 's'
|
||||
if !strings.HasSuffix(segment, "s") {
|
||||
return fmt.Errorf("parse auth params: invalid collection syntax for %q", segment)
|
||||
}
|
||||
typStr = strings.TrimSuffix(segment, "s")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if foundId != "" {
|
||||
v.res.Id = foundId
|
||||
}
|
||||
|
||||
if typStr != "" {
|
||||
v.res.Type = resource.Map[typStr]
|
||||
if v.res.Type == resource.Unknown {
|
||||
return fmt.Errorf("parse auth params: unknown resource type %q", typStr)
|
||||
}
|
||||
} else {
|
||||
// If we found no other type information, we walked backwards all the
|
||||
// way to the scope boundary, so the type is scope
|
||||
v.res.Type = resource.Scope
|
||||
}
|
||||
|
||||
// If we're operating on a collection (that is, the ID is blank) and it's a
|
||||
// GET, it's actually a list
|
||||
if v.res.Id == "" && v.act == action.Read {
|
||||
v.act = action.List
|
||||
}
|
||||
|
||||
// If the pin ended up being a scope, nil it out
|
||||
if v.res.Pin != "" && v.res.Pin == v.res.ScopeId {
|
||||
v.res.Pin = ""
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v verifier) performAuthCheck() (aclResults *perms.ACLResults, userId string, scopeInfo *scopes.ScopeInfo, retErr error) {
|
||||
// Ensure we return an error by default if we forget to set this somewhere
|
||||
retErr = errors.New("unknown")
|
||||
|
||||
@@ -13,263 +13,11 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/servers"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller/handlers"
|
||||
"github.com/hashicorp/boundary/internal/types/action"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/go-hclog"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHandler_AuthDecoration(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
wrapper := db.TestWrapper(t)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
iamRepoFn := func() (*iam.Repository, error) {
|
||||
return iamRepo, nil
|
||||
}
|
||||
org, proj := iam.TestScopes(t, iamRepo)
|
||||
cases := []struct {
|
||||
name string
|
||||
path string
|
||||
method string
|
||||
action action.Type
|
||||
scope string
|
||||
resource resource.Type
|
||||
id string
|
||||
pin string
|
||||
wantErrContains string
|
||||
}{
|
||||
{
|
||||
name: "global scope, read, with id",
|
||||
path: "/v1/scopes/global/users/u_anon",
|
||||
method: "GET",
|
||||
action: action.Read,
|
||||
scope: "global",
|
||||
resource: resource.User,
|
||||
id: "u_anon",
|
||||
},
|
||||
{
|
||||
name: "global scope, update, with id",
|
||||
path: "/v1/scopes/global/auth-methods/am_1234",
|
||||
method: "PATCH",
|
||||
action: action.Update,
|
||||
scope: "global",
|
||||
resource: resource.AuthMethod,
|
||||
id: "am_1234",
|
||||
},
|
||||
{
|
||||
name: "global scope, delete org",
|
||||
path: "/v1/scopes/o_1234",
|
||||
method: "DELETE",
|
||||
action: action.Delete,
|
||||
scope: "global",
|
||||
resource: resource.Scope,
|
||||
id: "o_1234",
|
||||
},
|
||||
{
|
||||
name: "org scope, delete project",
|
||||
path: fmt.Sprintf("/v1/scopes/%s", proj.GetPublicId()),
|
||||
method: "DELETE",
|
||||
action: action.Delete,
|
||||
scope: org.GetPublicId(),
|
||||
resource: resource.Scope,
|
||||
id: proj.GetPublicId(),
|
||||
},
|
||||
{
|
||||
name: "empty segments",
|
||||
path: "/v1/scopes/o_abc1234/auth-methods//am_1234",
|
||||
wantErrContains: "empty segment found",
|
||||
},
|
||||
{
|
||||
name: "global scope, create",
|
||||
path: "/v1/scopes/global/roles",
|
||||
method: "POST",
|
||||
action: action.Create,
|
||||
scope: "global",
|
||||
resource: resource.Role,
|
||||
},
|
||||
{
|
||||
name: "global, invalid collection syntax",
|
||||
path: "/v1/scope",
|
||||
wantErrContains: `parse auth params: invalid first segment "scope"`,
|
||||
},
|
||||
{
|
||||
name: "invalid scopes segment with id",
|
||||
path: "/v1/scope/o_abc",
|
||||
wantErrContains: `parse auth params: invalid first segment "scope"`,
|
||||
},
|
||||
{
|
||||
name: "org, custom action",
|
||||
path: "/v1/scopes/o_123/auth-methods/am_1234:authenticate",
|
||||
method: "POST",
|
||||
action: action.Authenticate,
|
||||
scope: "o_123",
|
||||
resource: resource.AuthMethod,
|
||||
id: "am_1234",
|
||||
},
|
||||
{
|
||||
name: "unknown action in first segment",
|
||||
path: "/v1/:authentifake",
|
||||
wantErrContains: `parse auth params: invalid first segment ":authentifake"`,
|
||||
},
|
||||
{
|
||||
name: "root, unknown action",
|
||||
path: "/v1/scopes/o_abc/:authentifake",
|
||||
wantErrContains: `parse auth params: unknown action "authentifake"`,
|
||||
},
|
||||
{
|
||||
name: "root, unknown empty action",
|
||||
path: "/v1/:",
|
||||
wantErrContains: `parse auth params: invalid first segment ":"`,
|
||||
},
|
||||
{
|
||||
name: "root, invalid method",
|
||||
path: "/v1/scopes/o_abc/:authenticate",
|
||||
method: "FOOBAR",
|
||||
wantErrContains: `unknown method "FOOBAR"`,
|
||||
},
|
||||
{
|
||||
name: "root, wrong number of colons",
|
||||
path: "/v1/scopes/o_abc/:auth:enticate",
|
||||
wantErrContains: "unexpected number of colons",
|
||||
},
|
||||
{
|
||||
name: "root, action on global",
|
||||
path: "/v1/scopes/global",
|
||||
method: "GET",
|
||||
action: action.Read,
|
||||
scope: "global",
|
||||
resource: resource.Scope,
|
||||
id: "global",
|
||||
},
|
||||
{
|
||||
name: "org scope, valid",
|
||||
path: "/v1/scopes/o_abc123/auth-methods",
|
||||
method: "POST",
|
||||
action: action.Create,
|
||||
scope: "o_abc123",
|
||||
resource: resource.AuthMethod,
|
||||
},
|
||||
{
|
||||
name: "project scope, valid",
|
||||
path: "/v1/scopes/p_1234/host-catalogs",
|
||||
method: "POST",
|
||||
action: action.Create,
|
||||
scope: "p_1234",
|
||||
resource: resource.HostCatalog,
|
||||
},
|
||||
{
|
||||
name: "project scope, action on project",
|
||||
path: "/v1/scopes/p_1234/:deauthenticate",
|
||||
method: "POST",
|
||||
action: action.Deauthenticate,
|
||||
scope: "p_1234",
|
||||
resource: resource.Scope,
|
||||
id: "p_1234",
|
||||
},
|
||||
{
|
||||
name: "global scope, action on org, token scope",
|
||||
path: "/v1/scopes/o_1234:set-principals",
|
||||
method: "POST",
|
||||
action: action.SetPrincipals,
|
||||
scope: "global",
|
||||
resource: resource.Scope,
|
||||
id: "o_1234",
|
||||
},
|
||||
{
|
||||
name: "global action, valid",
|
||||
path: "/v1/scopes/global/:read",
|
||||
action: action.Read,
|
||||
scope: "global",
|
||||
resource: resource.Scope,
|
||||
id: "global",
|
||||
},
|
||||
{
|
||||
name: "top level, invalid",
|
||||
path: "/v1/",
|
||||
wantErrContains: `invalid first segment "v1"`,
|
||||
},
|
||||
{
|
||||
name: "non-api path",
|
||||
path: "/",
|
||||
wantErrContains: `parse auth params: invalid first segment ""`,
|
||||
},
|
||||
{
|
||||
name: "project scope, pinning collection",
|
||||
path: "/v1/scopes/p_1234/host-catalogs/hc_1234/host-sets",
|
||||
action: action.List,
|
||||
scope: "p_1234",
|
||||
pin: "hc_1234",
|
||||
resource: resource.HostSet,
|
||||
},
|
||||
{
|
||||
name: "project scope, pinning collection, custom action",
|
||||
path: "/v1/scopes/p_1234/host-catalogs/hc_1234/host-sets:create",
|
||||
action: action.Create,
|
||||
scope: "p_1234",
|
||||
pin: "hc_1234",
|
||||
resource: resource.HostSet,
|
||||
},
|
||||
{
|
||||
name: "project scope, pinning id",
|
||||
path: "/v1/scopes/p_1234/host-catalogs/hc_1234/host-sets/hs_abc",
|
||||
action: action.Read,
|
||||
id: "hs_abc",
|
||||
scope: "p_1234",
|
||||
pin: "hc_1234",
|
||||
resource: resource.HostSet,
|
||||
},
|
||||
{
|
||||
name: "project scope, pinning id, custom action",
|
||||
path: "/v1/scopes/p_1234/host-catalogs/hc_1234/host-sets/hs_abc:update",
|
||||
action: action.Update,
|
||||
id: "hs_abc",
|
||||
scope: "p_1234",
|
||||
pin: "hc_1234",
|
||||
resource: resource.HostSet,
|
||||
},
|
||||
}
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require, assert := require.New(t), assert.New(t)
|
||||
if tc.method == "" {
|
||||
tc.method = "GET"
|
||||
}
|
||||
req, err := http.NewRequest(tc.method, fmt.Sprintf("http://127.0.0.1:9200:%s", tc.path), nil)
|
||||
require.NoError(err)
|
||||
|
||||
v := &verifier{
|
||||
requestInfo: RequestInfo{
|
||||
Path: req.URL.Path,
|
||||
Method: tc.method,
|
||||
},
|
||||
iamRepoFn: iamRepoFn,
|
||||
}
|
||||
|
||||
err = v.parseAuthParams()
|
||||
if tc.wantErrContains != "" {
|
||||
require.Error(err)
|
||||
assert.Contains(err.Error(), tc.wantErrContains, err.Error())
|
||||
return
|
||||
}
|
||||
require.NoError(err, pretty.Sprint(v))
|
||||
|
||||
if tc.path == "/" {
|
||||
return
|
||||
}
|
||||
|
||||
require.NotNil(v.res)
|
||||
require.NotEqual(action.Unknown, v.act)
|
||||
assert.Equal(tc.scope, v.res.ScopeId, "scope "+pretty.Sprint(v))
|
||||
assert.Equal(tc.action, v.act, "action "+pretty.Sprint(v))
|
||||
assert.Equal(tc.resource, v.res.Type, "type "+pretty.Sprint(v))
|
||||
assert.Equal(tc.id, v.res.Id, "id "+pretty.Sprint(v))
|
||||
assert.Equal(tc.pin, v.res.Pin, "pin "+pretty.Sprint(v))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAuthTokenAuthenticator(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
|
||||
@@ -288,7 +288,7 @@ func TestRepository_ChangePassword(t *testing.T) {
|
||||
wantIsErr: db.ErrInvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "invalid-no-old-password",
|
||||
name: "invalid-no-current-password",
|
||||
args: args{
|
||||
acctId: acct.PublicId,
|
||||
old: "",
|
||||
@@ -325,7 +325,7 @@ func TestRepository_ChangePassword(t *testing.T) {
|
||||
wantIsErr: db.ErrRecordNotFound,
|
||||
},
|
||||
{
|
||||
name: "auth-failure-wrong-old-password",
|
||||
name: "auth-failure-wrong-current-password",
|
||||
args: args{
|
||||
acctId: acct.PublicId,
|
||||
old: "wrong-password",
|
||||
@@ -455,13 +455,13 @@ func TestRepository_SetPassword(t *testing.T) {
|
||||
createAcct func(string) *Account
|
||||
}{
|
||||
{
|
||||
name: "valid-new-password-no-old-password",
|
||||
name: "valid-new-password-no-current-password",
|
||||
createAcct: createAccount("validnewpwnoold"),
|
||||
oldPw: "",
|
||||
newPw: "abcdefghijk",
|
||||
},
|
||||
{
|
||||
name: "valid-new-password-delete-old-password",
|
||||
name: "valid-new-password-delete-current-password",
|
||||
createAcct: createAccount("validnewpwyesold"),
|
||||
oldPw: origPasswd,
|
||||
newPw: "abcdefghijk",
|
||||
|
||||
@@ -53,7 +53,6 @@ type Command struct {
|
||||
flagsOnce sync.Once
|
||||
|
||||
flagAddr string
|
||||
flagScope string
|
||||
flagVerbose bool
|
||||
|
||||
flagTLSCACert string
|
||||
@@ -69,6 +68,7 @@ type Command struct {
|
||||
FlagRecoveryConfig string
|
||||
flagOutputCurlString bool
|
||||
|
||||
FlagScopeId string
|
||||
FlagId string
|
||||
FlagName string
|
||||
FlagDescription string
|
||||
@@ -233,39 +233,12 @@ func (c *Command) Client(opt ...Option) (*api.Client, error) {
|
||||
c.UI.Error(fmt.Sprintf("Error unmarshaling stored token information after reading from system credential store: %s", err))
|
||||
} else {
|
||||
c.client.SetToken(authToken.Token)
|
||||
if !opts.withNoTokenScope {
|
||||
c.client.SetScopeId(authToken.Scope.Id)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We do this here so we override the stored token info if it's set above
|
||||
if c.flagScope != NotSetValue {
|
||||
c.client.SetScopeId(c.flagScope)
|
||||
if c.flagFormat == "table" && c.flagVerbose {
|
||||
if c.flagScope == os.Getenv("BOUNDARY_TOKEN") {
|
||||
c.UI.Info(fmt.Sprintf("Scope of %q set from BOUNDARY_TOKEN env var", c.flagScope))
|
||||
} else {
|
||||
c.UI.Info(fmt.Sprintf("Scope of %q set from -scope command flag", c.flagScope))
|
||||
}
|
||||
}
|
||||
} else if c.client.ScopeId() != "" && !opts.withNoTokenScope {
|
||||
// If it didn't come from env or a flag but isn't empty, it must have come from the token
|
||||
if c.flagFormat == "table" && c.flagVerbose {
|
||||
c.UI.Info(fmt.Sprintf("Scope of %q set from saved token with name %q", c.client.ScopeId(), tokenName))
|
||||
}
|
||||
}
|
||||
// At this point if we haven't figured out the scope, default to "global"
|
||||
if c.client.ScopeId() == "" {
|
||||
c.client.SetScopeId("global")
|
||||
if c.flagFormat == "table" && c.flagVerbose {
|
||||
c.UI.Info(`Scope of "global" set by default`)
|
||||
}
|
||||
}
|
||||
|
||||
if opts.withNoTokenValue {
|
||||
c.client.SetToken("")
|
||||
}
|
||||
@@ -300,15 +273,6 @@ func (c *Command) FlagSet(bit FlagSetBit) *FlagSets {
|
||||
Usage: "Addr of the Boundary controller, as a complete URL (e.g. https://boundary.example.com:9200).",
|
||||
})
|
||||
|
||||
f.StringVar(&StringVar{
|
||||
Name: FlagNameScope,
|
||||
Target: &c.flagScope,
|
||||
Default: NotSetValue,
|
||||
EnvVar: api.EnvBoundaryScopeId,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: `Scope in which to make the request. If not specified, will default to the scope of a saved token (if found), otherwise will default to "global".`,
|
||||
})
|
||||
|
||||
f.StringVar(&StringVar{
|
||||
Name: FlagNameCACert,
|
||||
Target: &c.flagTLSCACert,
|
||||
|
||||
@@ -4,9 +4,6 @@ const (
|
||||
// FlagNameAddr is the flag used in the base command to read in the
|
||||
// address of the Boundary server.
|
||||
FlagNameAddr = "addr"
|
||||
// FlagNameScope is the flag used in the base command to read in the scope
|
||||
// in which to make a request.
|
||||
FlagNameScope = "scope"
|
||||
// FlagnameCACert is the flag used in the base command to read in the CA
|
||||
// cert.
|
||||
FlagNameCACert = "ca-cert"
|
||||
|
||||
@@ -51,7 +51,7 @@ func WrapSlice(prefixSpaces int, input []string) string {
|
||||
for _, v := range input {
|
||||
ret = append(ret, fmt.Sprintf("%s%s",
|
||||
strings.Repeat(" ", prefixSpaces),
|
||||
fmt.Sprintf("%s: ", v),
|
||||
v,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
+172
-2
@@ -6,6 +6,7 @@ import (
|
||||
"syscall"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/accounts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/authenticate"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/authmethods"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/authtokens"
|
||||
@@ -19,6 +20,7 @@ import (
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/proxy"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/roles"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/scopes"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/users"
|
||||
"github.com/hashicorp/boundary/internal/cmd/commands/worker"
|
||||
|
||||
@@ -77,6 +79,66 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
}, nil
|
||||
},
|
||||
|
||||
"accounts": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
}, nil
|
||||
},
|
||||
"accounts read": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "read",
|
||||
}, nil
|
||||
},
|
||||
"accounts delete": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "delete",
|
||||
}, nil
|
||||
},
|
||||
"accounts list": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "list",
|
||||
}, nil
|
||||
},
|
||||
"accounts set-password": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "set-password",
|
||||
}, nil
|
||||
},
|
||||
"accounts change-password": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "change-password",
|
||||
}, nil
|
||||
},
|
||||
"accounts create": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"accounts create password": func() (cli.Command, error) {
|
||||
return &accounts.PasswordCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"accounts update": func() (cli.Command, error) {
|
||||
return &accounts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"accounts update password": func() (cli.Command, error) {
|
||||
return &accounts.PasswordCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
|
||||
"auth-methods": func() (cli.Command, error) {
|
||||
return &authmethods.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
@@ -335,11 +397,53 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
}, nil
|
||||
},
|
||||
|
||||
"hosts create": func() (cli.Command, error) {
|
||||
return &hosts.CreateCommand{
|
||||
"hosts": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
}, nil
|
||||
},
|
||||
"hosts read": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "read",
|
||||
}, nil
|
||||
},
|
||||
"hosts delete": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "delete",
|
||||
}, nil
|
||||
},
|
||||
"hosts list": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "list",
|
||||
}, nil
|
||||
},
|
||||
"hosts create": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"hosts create static": func() (cli.Command, error) {
|
||||
return &hosts.StaticCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"hosts update": func() (cli.Command, error) {
|
||||
return &hosts.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"hosts update static": func() (cli.Command, error) {
|
||||
return &hosts.StaticCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
|
||||
"roles": func() (cli.Command, error) {
|
||||
return &roles.Command{
|
||||
@@ -449,6 +553,72 @@ func initCommands(ui, serverCmdUi cli.Ui, runOpts *RunOptions) {
|
||||
}, nil
|
||||
},
|
||||
|
||||
"targets": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
}, nil
|
||||
},
|
||||
"targets read": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "read",
|
||||
}, nil
|
||||
},
|
||||
"targets delete": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "delete",
|
||||
}, nil
|
||||
},
|
||||
"targets list": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "list",
|
||||
}, nil
|
||||
},
|
||||
"targets create": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"targets create tcp": func() (cli.Command, error) {
|
||||
return &targets.TcpCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "create",
|
||||
}, nil
|
||||
},
|
||||
"targets update": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"targets update tcp": func() (cli.Command, error) {
|
||||
return &targets.TcpCommand{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "update",
|
||||
}, nil
|
||||
},
|
||||
"targets add-host-sets": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "add-host-sets",
|
||||
}, nil
|
||||
},
|
||||
"targets remove-host-sets": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "remove-host-sets",
|
||||
}, nil
|
||||
},
|
||||
"targets set-host-sets": func() (cli.Command, error) {
|
||||
return &targets.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
Func: "set-host-sets",
|
||||
}, nil
|
||||
},
|
||||
|
||||
"users": func() (cli.Command, error) {
|
||||
return &users.Command{
|
||||
Command: base.NewCommand(ui),
|
||||
|
||||
@@ -0,0 +1,375 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/accounts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/vault/sdk/helper/password"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*Command)(nil)
|
||||
var _ cli.CommandAutocomplete = (*Command)(nil)
|
||||
|
||||
type Command struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagAuthMethodId string
|
||||
flagPassword string
|
||||
flagCurrentPassword string
|
||||
flagNewPassword string
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
switch c.Func {
|
||||
case "create":
|
||||
return "Create account resources within Boundary"
|
||||
case "update":
|
||||
return "Update account resources within Boundary"
|
||||
default:
|
||||
return common.SynopsisFunc(c.Func, "account")
|
||||
}
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"auth-method-id"},
|
||||
"set-password": {"id", "password", "version"},
|
||||
"change-password": {"id", "current-password", "new-password", "version"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("account")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows operations on Boundary account resources. Example:",
|
||||
"",
|
||||
" Read a account:",
|
||||
"",
|
||||
` $ boundary accounts read -id apw_1234567890`,
|
||||
"",
|
||||
" Please see the accounts subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary account resources. Example:",
|
||||
"",
|
||||
" Create a password-type account:",
|
||||
"",
|
||||
` $ boundary accounts create password -name prodops -description "For ProdOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary account resources. Example:",
|
||||
"",
|
||||
" Update a password-type account:",
|
||||
"",
|
||||
` $ boundary accounts update password -id apw_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "set-password":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts set-password [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows setting the password on account-type resources, if the types match and the operation is allowed by the given account type. Example:",
|
||||
"",
|
||||
" Set the password on a password-type account:",
|
||||
"",
|
||||
` $ boundary accounts set-password -id apw_1234567890 -password <empty, to be read by stdin>`,
|
||||
})
|
||||
case "change-password":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts change-password [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows changing the password (with verification of the current password) on account-type resources, if the types match and the operation is allowed by the given account type. Example:",
|
||||
"",
|
||||
" Change the password on a password-type account:",
|
||||
"",
|
||||
` $ boundary accounts change-password -id apw_1234567890 -current-password <empty, to be read by stdin> -new-password <empty, to be read by stdin>`,
|
||||
})
|
||||
default:
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
if len(flagsMap[c.Func]) > 0 {
|
||||
common.PopulateCommonFlags(c.Command, f, resource.Account.String(), flagsMap[c.Func])
|
||||
}
|
||||
|
||||
for _, name := range flagsMap[c.Func] {
|
||||
switch name {
|
||||
case "auth-method-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "auth-method-id",
|
||||
Target: &c.flagAuthMethodId,
|
||||
Usage: "The auth-method resource in which to create or update the account resource",
|
||||
})
|
||||
case "password":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "password",
|
||||
Target: &c.flagPassword,
|
||||
Usage: "The password for the account. If not specified, the command will prompt for the password to be entered in a non-echoing way.",
|
||||
})
|
||||
case "current-password":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "current-password",
|
||||
Target: &c.flagCurrentPassword,
|
||||
Usage: "The current password for the account. If not specified, the command will prompt for the password to be entered in a non-echoing way.",
|
||||
})
|
||||
case "new-password":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "new-password",
|
||||
Target: &c.flagNewPassword,
|
||||
Usage: "The new password for the account. If not specified, the command will prompt for the password to be entered in a non-echoing way.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) int {
|
||||
switch c.Func {
|
||||
case "", "create", "update":
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "auth-method-id") && c.flagAuthMethodId == "" {
|
||||
c.UI.Error("Auth Method ID must be passed in via -auth-method-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []accounts.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, accounts.DefaultName())
|
||||
default:
|
||||
opts = append(opts, accounts.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, accounts.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, accounts.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "password") && c.flagPassword == "" {
|
||||
fmt.Print("Password is not set as flag, please enter it now (will be hidden): ")
|
||||
value, err := password.Read(os.Stdin)
|
||||
fmt.Print("\n")
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
c.flagPassword = strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "current-password") && c.flagCurrentPassword == "" {
|
||||
fmt.Print("Current password is not set as flag, please enter it now (will be hidden): ")
|
||||
value, err := password.Read(os.Stdin)
|
||||
fmt.Print("\n")
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
c.flagCurrentPassword = strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "new-password") && c.flagNewPassword == "" {
|
||||
fmt.Print("New password is not set as flag, please enter it now (will be hidden): ")
|
||||
value, err := password.Read(os.Stdin)
|
||||
fmt.Print("\n")
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
c.flagNewPassword = strings.TrimSpace(value)
|
||||
}
|
||||
|
||||
// Perform check-and-set when needed
|
||||
var version uint32
|
||||
switch c.Func {
|
||||
case "create":
|
||||
// These don't update so don't need the existing version
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, accounts.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
}
|
||||
|
||||
accountClient := accounts.NewClient(client)
|
||||
|
||||
var existed bool
|
||||
var account *accounts.Account
|
||||
var listedAccounts []*accounts.Account
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "read":
|
||||
account, apiErr, err = accountClient.Read(c.Context, c.FlagId, opts...)
|
||||
case "delete":
|
||||
existed, apiErr, err = accountClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedAccounts, apiErr, err = accountClient.List(c.Context, c.flagAuthMethodId, opts...)
|
||||
case "set-password":
|
||||
account, apiErr, err = accountClient.SetPassword(c.Context, c.FlagId, c.flagPassword, version, opts...)
|
||||
case "change-password":
|
||||
account, apiErr, err = accountClient.ChangePassword(c.Context, c.FlagId, c.flagCurrentPassword, c.flagNewPassword, version, opts...)
|
||||
}
|
||||
|
||||
plural := "account"
|
||||
if c.Func == "list" {
|
||||
plural = "accounts"
|
||||
}
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
case "delete":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
c.UI.Output("null")
|
||||
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)
|
||||
}
|
||||
return 0
|
||||
|
||||
case "list":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
if len(listedAccounts) == 0 {
|
||||
c.UI.Output("null")
|
||||
return 0
|
||||
}
|
||||
b, err := base.JsonFormatter{}.Format(listedAccounts)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
|
||||
case "table":
|
||||
if len(listedAccounts) == 0 {
|
||||
c.UI.Output("No accounts found")
|
||||
return 0
|
||||
}
|
||||
var output []string
|
||||
output = []string{
|
||||
"",
|
||||
"Account information:",
|
||||
}
|
||||
for i, m := range listedAccounts {
|
||||
if i > 0 {
|
||||
output = append(output, "")
|
||||
}
|
||||
if true {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" ID: %s", m.Id),
|
||||
fmt.Sprintf(" Version: %d", m.Version),
|
||||
fmt.Sprintf(" Type: %s", m.Type),
|
||||
)
|
||||
}
|
||||
if m.Name != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Name: %s", m.Name),
|
||||
)
|
||||
}
|
||||
if m.Description != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Description: %s", m.Description),
|
||||
)
|
||||
}
|
||||
}
|
||||
c.UI.Output(base.WrapForHelpText(output))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateAccountTableOutput(account))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(account)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api/accounts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func generateAccountTableOutput(in *accounts.Account) string {
|
||||
var ret []string
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
"Auth Method ID": in.AuthMethodId,
|
||||
}
|
||||
|
||||
if in.Name != "" {
|
||||
nonAttributeMap["Name"] = in.Name
|
||||
}
|
||||
if in.Description != "" {
|
||||
nonAttributeMap["Description"] = in.Description
|
||||
}
|
||||
|
||||
maxLength := 0
|
||||
for k := range nonAttributeMap {
|
||||
if len(k) > maxLength {
|
||||
maxLength = len(k)
|
||||
}
|
||||
}
|
||||
if len(in.Attributes) > 0 {
|
||||
for k, v := range in.Attributes {
|
||||
if attributeMap[k] != "" {
|
||||
in.Attributes[attributeMap[k]] = v
|
||||
delete(in.Attributes, k)
|
||||
}
|
||||
}
|
||||
for k := range in.Attributes {
|
||||
if len(k) > maxLength {
|
||||
maxLength = len(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, "", "Account information:")
|
||||
|
||||
ret = append(ret,
|
||||
// We do +2 because there is another +2 offset for attributes below
|
||||
base.WrapMap(2, maxLength+2, nonAttributeMap),
|
||||
)
|
||||
|
||||
if len(in.Attributes) > 0 {
|
||||
if true {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
)
|
||||
}
|
||||
ret = append(ret,
|
||||
base.WrapMap(4, maxLength, in.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
var attributeMap = map[string]string{
|
||||
"login_name": "Login Name",
|
||||
}
|
||||
@@ -0,0 +1,242 @@
|
||||
package accounts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/accounts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/vault/sdk/helper/password"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*PasswordCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*PasswordCommand)(nil)
|
||||
|
||||
type PasswordCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagAuthMethodId string
|
||||
flagLoginName string
|
||||
flagPassword string
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) Synopsis() string {
|
||||
return fmt.Sprintf("%s a password-type account within Boundary", textproto.CanonicalMIMEHeaderKey(c.Func))
|
||||
}
|
||||
|
||||
var passwordFlagsMap = map[string][]string{
|
||||
"create": {"auth-method-id", "name", "description", "login-name", "password"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) Help() string {
|
||||
var info string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts password create [options] [args]",
|
||||
"",
|
||||
" Create a password-type account. Example:",
|
||||
"",
|
||||
` $ boundary accounts password create -name prodops -description "Password account for ProdOps" -address "127.0.0.1"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary accounts password update [options] [args]",
|
||||
"",
|
||||
" Update a password-type account given its ID. Example:",
|
||||
"",
|
||||
` $ boundary accounts password update -id hst_1234567890 -name "devops" -description "Password account for DevOps" -address "10.20.30.40"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return info + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
if len(passwordFlagsMap[c.Func]) > 0 {
|
||||
common.PopulateCommonFlags(c.Command, f, "password-type account", passwordFlagsMap[c.Func])
|
||||
}
|
||||
|
||||
for _, name := range passwordFlagsMap[c.Func] {
|
||||
switch name {
|
||||
case "auth-method-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "auth-method-id",
|
||||
Target: &c.flagAuthMethodId,
|
||||
Usage: "The auth-method resource in which to create or update the account resource",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
f = set.NewFlagSet("Password Account Options")
|
||||
|
||||
for _, name := range passwordFlagsMap[c.Func] {
|
||||
switch name {
|
||||
case "login-name":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "login-name",
|
||||
Target: &c.flagLoginName,
|
||||
Usage: "The login name for the account",
|
||||
})
|
||||
case "password":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "password",
|
||||
Target: &c.flagPassword,
|
||||
Usage: "The password for the account. If not specified, the command will prompt for the password to be entered in a non-echoing way.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *PasswordCommand) Run(args []string) int {
|
||||
if c.Func == "" {
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(passwordFlagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(passwordFlagsMap[c.Func], "auth-method-id") && c.flagAuthMethodId == "" {
|
||||
c.UI.Error("Auth Method ID must be passed in via -auth-method-id")
|
||||
return 1
|
||||
}
|
||||
if c.Func == "create" && c.flagLoginName == "" {
|
||||
c.UI.Error("Login Name must be passed in via -login-name")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []accounts.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, accounts.DefaultName())
|
||||
default:
|
||||
opts = append(opts, accounts.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, accounts.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, accounts.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
switch c.flagLoginName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, accounts.DefaultPasswordAccountLoginName())
|
||||
default:
|
||||
opts = append(opts, accounts.WithPasswordAccountLoginName(c.flagLoginName))
|
||||
}
|
||||
|
||||
if strutil.StrListContains(passwordFlagsMap[c.Func], "password") {
|
||||
switch c.flagPassword {
|
||||
case "":
|
||||
fmt.Print("Password is not set as flag, please enter it now (will be hidden): ")
|
||||
value, err := password.Read(os.Stdin)
|
||||
fmt.Print("\n")
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("An error occurred attempting to read the password. The raw error message is shown below but usually this is because you attempted to pipe a value into the command or you are executing outside of a terminal (TTY). The raw error was:\n\n%s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
opts = append(opts, accounts.WithPasswordAccountPassword(strings.TrimSpace(value)))
|
||||
default:
|
||||
opts = append(opts, accounts.WithPasswordAccountPassword(c.flagPassword))
|
||||
}
|
||||
}
|
||||
|
||||
accountClient := accounts.NewClient(client)
|
||||
|
||||
// Perform check-and-set when needed
|
||||
var version uint32
|
||||
switch c.Func {
|
||||
case "create":
|
||||
// These don't update so don't need the existing version
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, accounts.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
}
|
||||
|
||||
var account *accounts.Account
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
account, apiErr, err = accountClient.Create(c.Context, c.flagAuthMethodId, opts...)
|
||||
case "update":
|
||||
account, apiErr, err = accountClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
plural := "password-type account"
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateAccountTableOutput(account))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(account)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -56,14 +56,14 @@ func (c *PasswordCommand) Flags() *base.FlagSets {
|
||||
Name: "login-name",
|
||||
Target: &c.flagLoginName,
|
||||
EnvVar: envLoginName,
|
||||
Usage: "Login name",
|
||||
Usage: "The login name corresponding to an account within the given auth method",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "password",
|
||||
Target: &c.flagPassword,
|
||||
EnvVar: envPassword,
|
||||
Usage: "Password",
|
||||
Usage: "The password associated with the login name",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
@@ -121,7 +121,11 @@ func (c *PasswordCommand) Run(args []string) int {
|
||||
// note: Authenticate() calls SetToken() under the hood to set the
|
||||
// auth bearer on the client so we do not need to do anything with the
|
||||
// returned token after this call, so we ignore it
|
||||
result, apiErr, err := authmethods.NewClient(client).Authenticate(c.Context, c.flagAuthMethodId, c.flagLoginName, c.flagPassword)
|
||||
result, apiErr, err := authmethods.NewClient(client).Authenticate(c.Context, c.flagAuthMethodId,
|
||||
map[string]interface{}{
|
||||
"login_name": c.flagLoginName,
|
||||
"password": c.flagPassword,
|
||||
})
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to perform authentication: %s", err.Error()))
|
||||
return 2
|
||||
|
||||
@@ -37,10 +37,12 @@ func (c *Command) Synopsis() string {
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("auth-method")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
@@ -55,7 +57,7 @@ func (c *Command) Help() string {
|
||||
" Please see the auth-methods subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary auth-methods create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary auth-method resources. Example:",
|
||||
@@ -67,7 +69,7 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary auth-methods update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary auth-method resources. Example:",
|
||||
@@ -79,8 +81,9 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
default:
|
||||
return helpMap[c.Func]() + c.Flags().Help()
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
@@ -119,6 +122,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -157,7 +164,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = authmethodClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedMethods, apiErr, err = authmethodClient.List(c.Context, opts...)
|
||||
listedMethods, apiErr, err = authmethodClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
}
|
||||
|
||||
plural := "auth method"
|
||||
|
||||
@@ -26,6 +26,7 @@ func generateAuthMethodTableOutput(in *authmethods.AuthMethod) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
|
||||
@@ -32,7 +32,7 @@ func (c *PasswordCommand) Synopsis() string {
|
||||
}
|
||||
|
||||
var passwordFlagsMap = map[string][]string{
|
||||
"create": {"name", "description"},
|
||||
"create": {"scope-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
@@ -102,6 +102,10 @@ func (c *PasswordCommand) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(passwordFlagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -174,7 +178,7 @@ func (c *PasswordCommand) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, authmethods.WithAutomaticVersioning())
|
||||
opts = append(opts, authmethods.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -185,7 +189,7 @@ func (c *PasswordCommand) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
method, apiErr, err = authmethodClient.Create(c.Context, "password", opts...)
|
||||
method, apiErr, err = authmethodClient.Create(c.Context, "password", c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
method, apiErr, err = authmethodClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ func (c *Command) Synopsis() string {
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
@@ -76,6 +77,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -96,7 +101,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = authtokenClient.Delete(c.Context, c.FlagId)
|
||||
case "list":
|
||||
listedTokens, apiErr, err = authtokenClient.List(c.Context)
|
||||
listedTokens, apiErr, err = authtokenClient.List(c.Context, c.FlagScopeId)
|
||||
}
|
||||
|
||||
plural := "auth token"
|
||||
|
||||
@@ -75,6 +75,7 @@ func generateGroupTableOutput(in *groups.Group) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
|
||||
@@ -43,10 +43,11 @@ var helpMap = func() map[string]func() string {
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"create": {"name", "description"},
|
||||
"create": {"scope-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
"add-members": {"id", "member", "version"},
|
||||
"set-members": {"id", "member", "version"},
|
||||
"remove-members": {"id", "member", "version"},
|
||||
@@ -95,6 +96,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -151,7 +156,7 @@ func (c *Command) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, groups.WithAutomaticVersioning())
|
||||
opts = append(opts, groups.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -164,7 +169,7 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
group, apiErr, err = groupClient.Create(c.Context, opts...)
|
||||
group, apiErr, err = groupClient.Create(c.Context, c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
group, apiErr, err = groupClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
case "read":
|
||||
@@ -172,7 +177,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = groupClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedGroups, apiErr, err = groupClient.List(c.Context, opts...)
|
||||
listedGroups, apiErr, err = groupClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
case "add-members":
|
||||
group, apiErr, err = groupClient.AddMembers(c.Context, c.FlagId, version, members, opts...)
|
||||
case "set-members":
|
||||
|
||||
@@ -13,6 +13,7 @@ func generateHostCatalogTableOutput(in *hostcatalogs.HostCatalog) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
@@ -54,12 +55,8 @@ func generateHostCatalogTableOutput(in *hostcatalogs.HostCatalog) string {
|
||||
)
|
||||
|
||||
if len(in.Attributes) > 0 {
|
||||
if true {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
)
|
||||
}
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
base.WrapMap(4, maxLength, in.Attributes),
|
||||
)
|
||||
}
|
||||
@@ -67,4 +64,6 @@ func generateHostCatalogTableOutput(in *hostcatalogs.HostCatalog) string {
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
var attributeMap = map[string]string{}
|
||||
var attributeMap = map[string]string{
|
||||
"address": "Address",
|
||||
}
|
||||
@@ -26,7 +26,7 @@ type Command struct {
|
||||
func (c *Command) Synopsis() string {
|
||||
switch c.Func {
|
||||
case "create":
|
||||
return "Create host-catalolg resources within Boundary"
|
||||
return "Create host-catalog resources within Boundary"
|
||||
case "update":
|
||||
return "Update host-catalog resources within Boundary"
|
||||
default:
|
||||
@@ -37,10 +37,12 @@ func (c *Command) Synopsis() string {
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("host-catalog")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
@@ -55,7 +57,7 @@ func (c *Command) Help() string {
|
||||
" Please see the host-catalogs subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-catalogs create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary host-catalog resources. Example:",
|
||||
@@ -67,7 +69,7 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-catalogs update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary host-catalog resources. Example:",
|
||||
@@ -79,8 +81,9 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
default:
|
||||
return helpMap[c.Func]() + c.Flags().Help()
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
@@ -119,6 +122,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -157,7 +164,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = hostcatalogClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedCatalogs, apiErr, err = hostcatalogClient.List(c.Context, opts...)
|
||||
listedCatalogs, apiErr, err = hostcatalogClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
}
|
||||
|
||||
plural := "host catalog"
|
||||
|
||||
@@ -28,7 +28,7 @@ func (c *StaticCommand) Synopsis() string {
|
||||
}
|
||||
|
||||
var staticFlagsMap = map[string][]string{
|
||||
"create": {"name", "description"},
|
||||
"create": {"scope-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
@@ -95,6 +95,10 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(staticFlagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -130,7 +134,7 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, hostcatalogs.WithAutomaticVersioning())
|
||||
opts = append(opts, hostcatalogs.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -141,7 +145,7 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
catalog, apiErr, err = hostcatalogClient.Create(c.Context, "static", opts...)
|
||||
catalog, apiErr, err = hostcatalogClient.Create(c.Context, "static", c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
catalog, apiErr, err = hostcatalogClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
package hosts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api/hosts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func generateHostTableOutput(in *hosts.Host) string {
|
||||
var ret []string
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
"Host Catalog ID": in.HostCatalogId,
|
||||
}
|
||||
|
||||
if in.Name != "" {
|
||||
nonAttributeMap["Name"] = in.Name
|
||||
}
|
||||
if in.Description != "" {
|
||||
nonAttributeMap["Description"] = in.Description
|
||||
}
|
||||
|
||||
maxLength := 0
|
||||
for k := range nonAttributeMap {
|
||||
if len(k) > maxLength {
|
||||
maxLength = len(k)
|
||||
}
|
||||
}
|
||||
if len(in.Attributes) > 0 {
|
||||
for k, v := range in.Attributes {
|
||||
if attributeMap[k] != "" {
|
||||
in.Attributes[attributeMap[k]] = v
|
||||
delete(in.Attributes, k)
|
||||
}
|
||||
}
|
||||
for k := range in.Attributes {
|
||||
if len(k) > maxLength {
|
||||
maxLength = len(k)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = append(ret, "", "Host information:")
|
||||
|
||||
ret = append(ret,
|
||||
// We do +2 because there is another +2 offset for attributes below
|
||||
base.WrapMap(2, maxLength+2, nonAttributeMap),
|
||||
)
|
||||
|
||||
if len(in.HostSetIds) > 0 {
|
||||
ret = append(ret,
|
||||
" Host Set IDs:",
|
||||
base.WrapSlice(4, in.HostSetIds),
|
||||
)
|
||||
}
|
||||
|
||||
if len(in.Attributes) > 0 {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
base.WrapMap(4, maxLength, in.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
var attributeMap = map[string]string{}
|
||||
@@ -0,0 +1,278 @@
|
||||
package hosts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/hosts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*Command)(nil)
|
||||
var _ cli.CommandAutocomplete = (*Command)(nil)
|
||||
|
||||
type Command struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagHostCatalogId string
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
switch c.Func {
|
||||
case "create":
|
||||
return "Create host resources within Boundary"
|
||||
case "update":
|
||||
return "Update host resources within Boundary"
|
||||
default:
|
||||
return common.SynopsisFunc(c.Func, "host")
|
||||
}
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"host-catalog-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("host")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
"Usage: boundary hosts [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows operations on Boundary host resources. Example:",
|
||||
"",
|
||||
" Read a host:",
|
||||
"",
|
||||
` $ boundary hosts read -id hst_1234567890`,
|
||||
"",
|
||||
" Please see the hosts subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary hosts create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary host resources. Example:",
|
||||
"",
|
||||
" Create a static-type host:",
|
||||
"",
|
||||
` $ boundary hosts create static -name prodops -description "For ProdOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary hosts update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary host resources. Example:",
|
||||
"",
|
||||
" Update a static-type host:",
|
||||
"",
|
||||
` $ boundary hosts update static -id hst_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
default:
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
if len(flagsMap[c.Func]) > 0 {
|
||||
common.PopulateCommonFlags(c.Command, f, resource.Host.String(), flagsMap[c.Func])
|
||||
}
|
||||
|
||||
for _, name := range flagsMap[c.Func] {
|
||||
switch name {
|
||||
case "host-catalog-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host resource",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) int {
|
||||
switch c.Func {
|
||||
case "", "create", "update":
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "host-catalog-id") && c.flagHostCatalogId == "" {
|
||||
c.UI.Error("Host Catalog ID must be passed in via -host-catalog-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []hosts.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, hosts.DefaultName())
|
||||
default:
|
||||
opts = append(opts, hosts.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, hosts.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, hosts.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
hostClient := hosts.NewClient(client)
|
||||
|
||||
var existed bool
|
||||
var host *hosts.Host
|
||||
var listedHosts []*hosts.Host
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "read":
|
||||
host, apiErr, err = hostClient.Read(c.Context, c.FlagId, opts...)
|
||||
case "delete":
|
||||
existed, apiErr, err = hostClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedHosts, apiErr, err = hostClient.List(c.Context, c.flagHostCatalogId, opts...)
|
||||
}
|
||||
|
||||
plural := "host"
|
||||
if c.Func == "list" {
|
||||
plural = "hosts"
|
||||
}
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
case "delete":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
c.UI.Output("null")
|
||||
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)
|
||||
}
|
||||
return 0
|
||||
|
||||
case "list":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
if len(listedHosts) == 0 {
|
||||
c.UI.Output("null")
|
||||
return 0
|
||||
}
|
||||
b, err := base.JsonFormatter{}.Format(listedHosts)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
|
||||
case "table":
|
||||
if len(listedHosts) == 0 {
|
||||
c.UI.Output("No hosts found")
|
||||
return 0
|
||||
}
|
||||
var output []string
|
||||
output = []string{
|
||||
"",
|
||||
"Host information:",
|
||||
}
|
||||
for i, m := range listedHosts {
|
||||
if i > 0 {
|
||||
output = append(output, "")
|
||||
}
|
||||
if true {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" ID: %s", m.Id),
|
||||
fmt.Sprintf(" Version: %d", m.Version),
|
||||
fmt.Sprintf(" Type: %s", m.Type),
|
||||
)
|
||||
}
|
||||
if m.Name != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Name: %s", m.Name),
|
||||
)
|
||||
}
|
||||
if m.Description != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Description: %s", m.Description),
|
||||
)
|
||||
}
|
||||
}
|
||||
c.UI.Output(base.WrapForHelpText(output))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateHostTableOutput(host))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(host)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
package hosts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/api/hosts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*CreateCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*CreateCommand)(nil)
|
||||
|
||||
type CreateCommand struct {
|
||||
*base.Command
|
||||
|
||||
flagAddress string
|
||||
flagName string
|
||||
flagCatalogId string
|
||||
flagDescription string
|
||||
}
|
||||
|
||||
func (c *CreateCommand) Synopsis() string {
|
||||
return "Creates a host in the given host catalog"
|
||||
}
|
||||
|
||||
func (c *CreateCommand) Help() string {
|
||||
helpText := `
|
||||
Usage: boundary hosts create
|
||||
|
||||
Creates a host in the given host catalog. This command will result in an
|
||||
error for any catalog that does not support manual host creation.
|
||||
|
||||
Example:
|
||||
|
||||
$ boundary hosts create -catalog-id=<id> -address=<addr> -name=<name>
|
||||
|
||||
` + c.Flags().Help()
|
||||
|
||||
return strings.TrimSpace(helpText)
|
||||
}
|
||||
|
||||
func (c *CreateCommand) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "address",
|
||||
Target: &c.flagAddress,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: "The host's address; can be an IP address or DNS name",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "name",
|
||||
Target: &c.flagName,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: "An optional name assigned to the host for display purposes",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "catalog-id",
|
||||
Target: &c.flagCatalogId,
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: "The ID of the host catalog in which the host should be created",
|
||||
})
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "description",
|
||||
Target: &c.flagDescription,
|
||||
Completion: complete.PredictNothing,
|
||||
Usage: "An optional description assigned to the host for display purposes",
|
||||
})
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *CreateCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *CreateCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *CreateCommand) Run(args []string) int {
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
switch {
|
||||
case c.flagCatalogId == "":
|
||||
c.UI.Error("Catalog ID must be provided via -catalog-id")
|
||||
return 1
|
||||
case c.flagAddress == "":
|
||||
c.UI.Error("Host address must be provided via -address")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 2
|
||||
}
|
||||
|
||||
host, apiErr, err := hosts.NewClient(client).Create(c.Context,
|
||||
c.flagCatalogId,
|
||||
hosts.WithStaticHostAddress(c.flagAddress),
|
||||
hosts.WithName(c.flagName),
|
||||
hosts.WithDescription(c.flagDescription))
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
c.UI.Error(fmt.Errorf("error creating host: %w", err).Error())
|
||||
return 2
|
||||
case apiErr != nil:
|
||||
c.UI.Error(pretty.Sprint(apiErr))
|
||||
return 2
|
||||
default:
|
||||
c.UI.Info(pretty.Sprint(host))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package hosts
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/textproto"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/hosts"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*StaticCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*StaticCommand)(nil)
|
||||
|
||||
type StaticCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagHostCatalogId string
|
||||
flagAddress string
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Synopsis() string {
|
||||
return fmt.Sprintf("%s a static-type host within Boundary", textproto.CanonicalMIMEHeaderKey(c.Func))
|
||||
}
|
||||
|
||||
var staticFlagsMap = map[string][]string{
|
||||
"create": {"host-catalog-id", "name", "description", "address"},
|
||||
"update": {"id", "name", "description", "version", "address"},
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Help() string {
|
||||
var info string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary hosts static create [options] [args]",
|
||||
"",
|
||||
" Create a static-type host. Example:",
|
||||
"",
|
||||
` $ boundary hosts static create -name prodops -description "Static host for ProdOps" -address "127.0.0.1"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary hosts static update [options] [args]",
|
||||
"",
|
||||
" Update a static-type host given its ID. Example:",
|
||||
"",
|
||||
` $ boundary hosts static update -id hst_1234567890 -name "devops" -description "Static host for DevOps" -address "10.20.30.40"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return info + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
if len(staticFlagsMap[c.Func]) > 0 {
|
||||
common.PopulateCommonFlags(c.Command, f, "static-type host", staticFlagsMap[c.Func])
|
||||
}
|
||||
|
||||
for _, name := range staticFlagsMap[c.Func] {
|
||||
switch name {
|
||||
case "host-catalog-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host resource",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
f = set.NewFlagSet("Static Host Options")
|
||||
|
||||
for _, name := range staticFlagsMap[c.Func] {
|
||||
switch name {
|
||||
case "address":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "address",
|
||||
Target: &c.flagAddress,
|
||||
Usage: "The address of the host",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *StaticCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *StaticCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *StaticCommand) Run(args []string) int {
|
||||
if c.Func == "" {
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(staticFlagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(staticFlagsMap[c.Func], "host-catalog-id") && c.flagHostCatalogId == "" {
|
||||
c.UI.Error("Host Catalog ID must be passed in via -host-catalog-id")
|
||||
return 1
|
||||
}
|
||||
if c.Func == "create" && c.flagAddress == "" {
|
||||
c.UI.Error("Address must be passed in via -address")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []hosts.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, hosts.DefaultName())
|
||||
default:
|
||||
opts = append(opts, hosts.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, hosts.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, hosts.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
switch c.flagAddress {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, hosts.DefaultStaticHostAddress())
|
||||
default:
|
||||
opts = append(opts, hosts.WithStaticHostAddress(c.flagAddress))
|
||||
}
|
||||
|
||||
hostClient := hosts.NewClient(client)
|
||||
|
||||
// Perform check-and-set when needed
|
||||
var version uint32
|
||||
switch c.Func {
|
||||
case "create":
|
||||
// These don't update so don't need the existing version
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, hosts.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
}
|
||||
|
||||
var host *hosts.Host
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
host, apiErr, err = hostClient.Create(c.Context, c.flagHostCatalogId, opts...)
|
||||
case "update":
|
||||
host, apiErr, err = hostClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
plural := "static-type host"
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateHostTableOutput(host))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(host)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -13,6 +13,7 @@ func generateHostSetTableOutput(in *hostsets.HostSet) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
@@ -55,23 +56,15 @@ func generateHostSetTableOutput(in *hostsets.HostSet) string {
|
||||
)
|
||||
|
||||
if len(in.HostIds) > 0 {
|
||||
if true {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Host IDs:"),
|
||||
)
|
||||
}
|
||||
ret = append(ret,
|
||||
" Host IDs:",
|
||||
base.WrapSlice(4, in.HostIds),
|
||||
)
|
||||
}
|
||||
|
||||
if len(in.Attributes) > 0 {
|
||||
if true {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
)
|
||||
}
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Attributes: %s", ""),
|
||||
base.WrapMap(4, maxLength, in.Attributes),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ func (c *Command) Synopsis() string {
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"host-catalog-id"},
|
||||
"add-hosts": {"id", "host", "version"},
|
||||
"set-hosts": {"id", "host", "version"},
|
||||
"remove-hosts": {"id", "host", "version"},
|
||||
@@ -53,6 +54,7 @@ var flagsMap = map[string][]string{
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("host-set")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
@@ -67,7 +69,7 @@ func (c *Command) Help() string {
|
||||
" Please see the host-sets subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-sets create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary host-set resources. Example:",
|
||||
@@ -79,7 +81,7 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-sets update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary host-set resources. Example:",
|
||||
@@ -91,7 +93,7 @@ func (c *Command) Help() string {
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "add-hosts":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-sets add-hosts [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows adding hosts to host-set resources, if the types match and the operation is allowed by the given host-set type. Example:",
|
||||
@@ -101,7 +103,7 @@ func (c *Command) Help() string {
|
||||
` $ boundary host-sets add-hosts -id hsst_1234567890 -host hst_1234567890 -host hst_0987654321`,
|
||||
})
|
||||
case "remove-hosts":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-sets remove-hosts [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows removing hosts from host-set resources, if the types match and the operation is allowed by the given host-set type. Example:",
|
||||
@@ -111,7 +113,7 @@ func (c *Command) Help() string {
|
||||
` $ boundary host-sets remove-hosts -id hsst_1234567890 -host hst_0987654321`,
|
||||
})
|
||||
case "set-hosts":
|
||||
return base.WrapForHelpText([]string{
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary host-sets set-hosts [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows setting the complete set of hosts on host-set resources, if the types match and the operation is allowed by the given host-set type. Example:",
|
||||
@@ -121,8 +123,9 @@ func (c *Command) Help() string {
|
||||
` $ boundary host-sets remove-hosts -id hsst_1234567890 -host hst_1234567890`,
|
||||
})
|
||||
default:
|
||||
return helpMap[c.Func]() + c.Flags().Help()
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
@@ -134,14 +137,14 @@ func (c *Command) Flags() *base.FlagSets {
|
||||
common.PopulateCommonFlags(c.Command, f, resource.HostSet.String(), flagsMap[c.Func])
|
||||
}
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host-set resource",
|
||||
})
|
||||
|
||||
for _, name := range flagsMap[c.Func] {
|
||||
switch name {
|
||||
case "host-catalog-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host-set resource",
|
||||
})
|
||||
case "host":
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "host",
|
||||
@@ -174,11 +177,14 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "host-catalog-id") && c.flagHostCatalogId == "" {
|
||||
c.UI.Error("Host Catalog ID must be passed in via -host-catalog-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -232,7 +238,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "add-hosts", "remove-hosts", "set-hosts":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, hostsets.WithAutomaticVersioning())
|
||||
opts = append(opts, hostsets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -250,17 +256,17 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "read":
|
||||
set, apiErr, err = hostsetClient.Read(c.Context, c.flagHostCatalogId, c.FlagId, opts...)
|
||||
set, apiErr, err = hostsetClient.Read(c.Context, c.FlagId, opts...)
|
||||
case "delete":
|
||||
existed, apiErr, err = hostsetClient.Delete(c.Context, c.flagHostCatalogId, c.FlagId, opts...)
|
||||
existed, apiErr, err = hostsetClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedSets, apiErr, err = hostsetClient.List(c.Context, c.flagHostCatalogId, opts...)
|
||||
case "add-hosts":
|
||||
set, apiErr, err = hostsetClient.AddHosts(c.Context, c.flagHostCatalogId, c.FlagId, version, c.flagHosts, opts...)
|
||||
set, apiErr, err = hostsetClient.AddHosts(c.Context, c.FlagId, version, c.flagHosts, opts...)
|
||||
case "remove-hosts":
|
||||
set, apiErr, err = hostsetClient.RemoveHosts(c.Context, c.flagHostCatalogId, c.FlagId, version, c.flagHosts, opts...)
|
||||
set, apiErr, err = hostsetClient.RemoveHosts(c.Context, c.FlagId, version, c.flagHosts, opts...)
|
||||
case "set-hosts":
|
||||
set, apiErr, err = hostsetClient.SetHosts(c.Context, c.flagHostCatalogId, c.FlagId, version, c.flagHosts, opts...)
|
||||
set, apiErr, err = hostsetClient.SetHosts(c.Context, c.FlagId, version, c.flagHosts, opts...)
|
||||
}
|
||||
|
||||
plural := "host set"
|
||||
|
||||
@@ -30,7 +30,7 @@ func (c *StaticCommand) Synopsis() string {
|
||||
}
|
||||
|
||||
var staticFlagsMap = map[string][]string{
|
||||
"create": {"name", "description"},
|
||||
"create": {"host-catalog-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
@@ -71,11 +71,16 @@ func (c *StaticCommand) Flags() *base.FlagSets {
|
||||
common.PopulateCommonFlags(c.Command, f, "static-type host-set", staticFlagsMap[c.Func])
|
||||
}
|
||||
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host-set resource",
|
||||
})
|
||||
for _, name := range staticFlagsMap[c.Func] {
|
||||
switch name {
|
||||
case "host-catalog-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "host-catalog-id",
|
||||
Target: &c.flagHostCatalogId,
|
||||
Usage: "The host-catalog resource in which to create or update the host-set resource",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
@@ -104,8 +109,7 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
|
||||
if c.flagHostCatalogId == "" {
|
||||
if strutil.StrListContains(staticFlagsMap[c.Func], "host-catalog-id") && c.flagHostCatalogId == "" {
|
||||
c.UI.Error("Host Catalog ID must be passed in via -host-catalog-id")
|
||||
return 1
|
||||
}
|
||||
@@ -144,7 +148,7 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, hostsets.WithAutomaticVersioning())
|
||||
opts = append(opts, hostsets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -157,7 +161,7 @@ func (c *StaticCommand) Run(args []string) int {
|
||||
case "create":
|
||||
set, apiErr, err = hostsetClient.Create(c.Context, c.flagHostCatalogId, opts...)
|
||||
case "update":
|
||||
set, apiErr, err = hostsetClient.Update(c.Context, c.flagHostCatalogId, c.FlagId, version, opts...)
|
||||
set, apiErr, err = hostsetClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
plural := "static-type host-set"
|
||||
|
||||
@@ -91,6 +91,7 @@ func generateRoleTableOutput(in *roles.Role) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
|
||||
@@ -22,6 +22,7 @@ type Command struct {
|
||||
|
||||
Func string
|
||||
|
||||
flagScope string
|
||||
flagGrantScopeId string
|
||||
flagPrincipals []string
|
||||
flagGrants []string
|
||||
@@ -51,10 +52,11 @@ var helpMap = func() map[string]func() string {
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"create": {"name", "description", "grantscopeid"},
|
||||
"create": {"scope-id", "name", "description", "grantscopeid"},
|
||||
"update": {"id", "name", "description", "grantscopeid", "version"},
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
"add-principals": {"id", "principal", "version"},
|
||||
"set-principals": {"id", "principal", "version"},
|
||||
"remove-principals": {"id", "principal", "version"},
|
||||
@@ -105,6 +107,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -198,7 +204,7 @@ func (c *Command) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, roles.WithAutomaticVersioning())
|
||||
opts = append(opts, roles.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -211,7 +217,7 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
role, apiErr, err = roleClient.Create(c.Context, opts...)
|
||||
role, apiErr, err = roleClient.Create(c.Context, c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
role, apiErr, err = roleClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
case "read":
|
||||
@@ -219,7 +225,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = roleClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedRoles, apiErr, err = roleClient.List(c.Context, opts...)
|
||||
listedRoles, apiErr, err = roleClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
case "add-principals":
|
||||
role, apiErr, err = roleClient.AddPrincipals(c.Context, c.FlagId, version, principals, opts...)
|
||||
case "set-principals":
|
||||
|
||||
@@ -12,6 +12,7 @@ func generateScopeTableOutput(in *scopes.Scope) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
|
||||
@@ -30,10 +30,11 @@ func (c *Command) Synopsis() string {
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"create": {"name", "description", "skip-role-creation"},
|
||||
"create": {"scope-id", "name", "description", "skip-role-creation"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
@@ -86,6 +87,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -123,7 +128,7 @@ func (c *Command) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, scopes.WithAutomaticVersioning())
|
||||
opts = append(opts, scopes.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -136,7 +141,7 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
scope, apiErr, err = scopeClient.Create(c.Context, client.ScopeId(), opts...)
|
||||
scope, apiErr, err = scopeClient.Create(c.Context, c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
scope, apiErr, err = scopeClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
case "read":
|
||||
@@ -144,7 +149,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = scopeClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedScopes, apiErr, err = scopeClient.List(c.Context, client.ScopeId(), opts...)
|
||||
listedScopes, apiErr, err = scopeClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
}
|
||||
|
||||
plural := "scope"
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
package targets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/boundary/api/scopes"
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
)
|
||||
|
||||
func generateTargetTableOutput(in *targets.Target) string {
|
||||
var ret []string
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Type": in.Type,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
"Default Port": in.DefaultPort,
|
||||
}
|
||||
|
||||
if in.Name != "" {
|
||||
nonAttributeMap["Name"] = in.Name
|
||||
}
|
||||
if in.Description != "" {
|
||||
nonAttributeMap["Description"] = in.Description
|
||||
}
|
||||
|
||||
maxLength := 0
|
||||
for k := range nonAttributeMap {
|
||||
if len(k) > maxLength {
|
||||
maxLength = len(k)
|
||||
}
|
||||
}
|
||||
|
||||
var hostSetMaps []map[string]interface{}
|
||||
if len(in.HostSets) > 0 {
|
||||
for _, set := range in.HostSets {
|
||||
m := map[string]interface{}{
|
||||
"ID": set.Id,
|
||||
"Host Catalog ID": set.HostCatalogId,
|
||||
}
|
||||
hostSetMaps = append(hostSetMaps, m)
|
||||
}
|
||||
if l := len("Host Catalog ID"); l > maxLength {
|
||||
maxLength = l
|
||||
}
|
||||
}
|
||||
ret = append(ret, "", "Target information:")
|
||||
|
||||
ret = append(ret,
|
||||
// We do +2 because there is another +2 offset for host sets below
|
||||
base.WrapMap(2, maxLength+2, nonAttributeMap),
|
||||
)
|
||||
|
||||
if len(in.HostSets) > 0 {
|
||||
ret = append(ret,
|
||||
fmt.Sprintf(" Host Sets: %s", ""),
|
||||
)
|
||||
for _, m := range hostSetMaps {
|
||||
ret = append(ret,
|
||||
base.WrapMap(4, maxLength, m),
|
||||
"",
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
return base.WrapForHelpText(ret)
|
||||
}
|
||||
|
||||
func exampleOutput() string {
|
||||
in := &targets.Target{
|
||||
Id: "ttcp_1234567890",
|
||||
ScopeId: "global",
|
||||
Scope: &scopes.ScopeInfo{
|
||||
Id: "global",
|
||||
},
|
||||
Name: "foo",
|
||||
Description: "The bar of foos",
|
||||
CreatedTime: time.Now().Add(-5 * time.Minute),
|
||||
UpdatedTime: time.Now(),
|
||||
Version: 3,
|
||||
Type: "tcp",
|
||||
HostSetIds: []string{"hsst_1234567890", "hsst_0987654321"},
|
||||
HostSets: []*targets.HostSet{
|
||||
{
|
||||
Id: "hsst_1234567890",
|
||||
HostCatalogId: "hcst_1234567890",
|
||||
},
|
||||
{
|
||||
Id: "hsst_0987654321",
|
||||
HostCatalogId: "hcst_1234567890",
|
||||
},
|
||||
},
|
||||
DefaultPort: 22,
|
||||
}
|
||||
return generateTargetTableOutput(in)
|
||||
}
|
||||
@@ -0,0 +1,360 @@
|
||||
package targets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/boundary/internal/types/resource"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*Command)(nil)
|
||||
var _ cli.CommandAutocomplete = (*Command)(nil)
|
||||
|
||||
type Command struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
|
||||
flagHostSets []string
|
||||
}
|
||||
|
||||
func (c *Command) Synopsis() string {
|
||||
switch c.Func {
|
||||
case "create":
|
||||
return "Create target resources within Boundary"
|
||||
case "update":
|
||||
return "Update target resources within Boundary"
|
||||
default:
|
||||
return common.SynopsisFunc(c.Func, "target")
|
||||
}
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
"add-host-sets": {"id", "host-set", "version"},
|
||||
"remove-host-sets": {"id", "host-set", "version"},
|
||||
"set-host-sets": {"id", "host-set", "version"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
helpMap := common.HelpMap("target")
|
||||
var helpStr string
|
||||
switch c.Func {
|
||||
case "":
|
||||
return base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows operations on Boundary target resources. Example:",
|
||||
"",
|
||||
" Read a target:",
|
||||
"",
|
||||
` $ boundary targets read -id ttcp_1234567890`,
|
||||
"",
|
||||
" Please see the targets subcommand help for detailed usage information.",
|
||||
})
|
||||
case "create":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets create [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows create operations on Boundary target resources. Example:",
|
||||
"",
|
||||
" Create a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets create tcp -name prodops -description "For ProdOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "update":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets update [type] [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows update operations on Boundary target resources. Example:",
|
||||
"",
|
||||
" Update a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets update tcp -id ttcp_1234567890 -name devops -description "For DevOps usage"`,
|
||||
"",
|
||||
" Please see the typed subcommand help for detailed usage information.",
|
||||
})
|
||||
case "add-host-sets":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target add-host-sets [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows adding host-set resources to target resources. Example:",
|
||||
"",
|
||||
" Add host-set resources to a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets add-host-sets -id ttcp_1234567890 -host-set hsst_1234567890 -host-set hsst_0987654321`,
|
||||
})
|
||||
case "remove-host-sets":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target remove-host-sets [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows removing host-set resources from target resources. Example:",
|
||||
"",
|
||||
" Remove host-set resources from a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets add-host-sets -id ttcp_1234567890 -host hsst_1234567890 -host-set hsst_0987654321`,
|
||||
})
|
||||
case "set-host-sets":
|
||||
helpStr = base.WrapForHelpText([]string{
|
||||
"Usage: boundary target set-host-sets [sub command] [options] [args]",
|
||||
"",
|
||||
" This command allows setting the complete set of host-set resources on a target resource. Example:",
|
||||
"",
|
||||
" Set host-set resources on a tcp-type target:",
|
||||
"",
|
||||
` $ boundary targets set-host-sets -id ttcp_1234567890 -host-set hsst_1234567890`,
|
||||
})
|
||||
default:
|
||||
helpStr = helpMap[c.Func]()
|
||||
}
|
||||
return helpStr + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *Command) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
f := set.NewFlagSet("Command Options")
|
||||
|
||||
if len(flagsMap[c.Func]) > 0 {
|
||||
common.PopulateCommonFlags(c.Command, f, resource.Target.String(), flagsMap[c.Func])
|
||||
}
|
||||
|
||||
for _, name := range flagsMap[c.Func] {
|
||||
switch name {
|
||||
case "host-set":
|
||||
f.StringSliceVar(&base.StringSliceVar{
|
||||
Name: "host-set",
|
||||
Target: &c.flagHostSets,
|
||||
Usage: "The host-set resources to add, remove, or set. May be specified multiple times.",
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *Command) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *Command) Run(args []string) int {
|
||||
if os.Getenv("BOUNDARY_EXAMPLE_CLI_OUTPUT") != "" {
|
||||
c.UI.Output(exampleOutput())
|
||||
return 0
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
case "", "create", "update":
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(flagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []targets.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultName())
|
||||
default:
|
||||
opts = append(opts, targets.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, targets.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
hostSets := c.flagHostSets
|
||||
switch c.Func {
|
||||
case "add-host-sets", "remove-host-sets":
|
||||
if len(c.flagHostSets) == 0 {
|
||||
c.UI.Error("No host-sets supplied via -host-set")
|
||||
return 1
|
||||
}
|
||||
|
||||
case "set-host-sets":
|
||||
switch len(c.flagHostSets) {
|
||||
case 0:
|
||||
case 1:
|
||||
if c.flagHostSets[0] == "null" {
|
||||
hostSets = []string{}
|
||||
}
|
||||
}
|
||||
if hostSets == nil {
|
||||
c.UI.Error("No host-sets supplied via -host-set")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
// Perform check-and-set when needed
|
||||
var version uint32
|
||||
switch c.Func {
|
||||
case "add-host-sets", "remove-host-sets", "set-host-sets":
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
default:
|
||||
// The only other one that needs it is update, handled by the static
|
||||
// file
|
||||
}
|
||||
|
||||
targetClient := targets.NewClient(client)
|
||||
|
||||
var existed bool
|
||||
var target *targets.Target
|
||||
var listedCatalogs []*targets.Target
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "read":
|
||||
target, apiErr, err = targetClient.Read(c.Context, c.FlagId, opts...)
|
||||
case "delete":
|
||||
existed, apiErr, err = targetClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedCatalogs, apiErr, err = targetClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
case "add-host-sets":
|
||||
target, apiErr, err = targetClient.AddHostSets(c.Context, c.FlagId, version, c.flagHostSets, opts...)
|
||||
case "remove-host-sets":
|
||||
target, apiErr, err = targetClient.RemoveHostSets(c.Context, c.FlagId, version, c.flagHostSets, opts...)
|
||||
case "set-host-sets":
|
||||
target, apiErr, err = targetClient.SetHostSets(c.Context, c.FlagId, version, c.flagHostSets, opts...)
|
||||
}
|
||||
|
||||
plural := "target"
|
||||
if c.Func == "list" {
|
||||
plural = "targets"
|
||||
}
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch c.Func {
|
||||
case "delete":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
c.UI.Output("null")
|
||||
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)
|
||||
}
|
||||
return 0
|
||||
|
||||
case "list":
|
||||
switch base.Format(c.UI) {
|
||||
case "json":
|
||||
if len(listedCatalogs) == 0 {
|
||||
c.UI.Output("null")
|
||||
return 0
|
||||
}
|
||||
b, err := base.JsonFormatter{}.Format(listedCatalogs)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
|
||||
case "table":
|
||||
if len(listedCatalogs) == 0 {
|
||||
c.UI.Output("No targets found")
|
||||
return 0
|
||||
}
|
||||
var output []string
|
||||
output = []string{
|
||||
"",
|
||||
"Target information:",
|
||||
}
|
||||
for i, m := range listedCatalogs {
|
||||
if i > 0 {
|
||||
output = append(output, "")
|
||||
}
|
||||
if true {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" ID: %s", m.Id),
|
||||
fmt.Sprintf(" Version: %d", m.Version),
|
||||
fmt.Sprintf(" Type: %s", m.Type),
|
||||
)
|
||||
}
|
||||
if m.Name != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Name: %s", m.Name),
|
||||
)
|
||||
}
|
||||
if m.Description != "" {
|
||||
output = append(output,
|
||||
fmt.Sprintf(" Description: %s", m.Description),
|
||||
)
|
||||
}
|
||||
}
|
||||
c.UI.Output(base.WrapForHelpText(output))
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateTargetTableOutput(target))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(target)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -0,0 +1,176 @@
|
||||
package targets
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/textproto"
|
||||
|
||||
"github.com/hashicorp/boundary/api"
|
||||
"github.com/hashicorp/boundary/api/targets"
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/hashicorp/boundary/internal/cmd/common"
|
||||
"github.com/hashicorp/vault/sdk/helper/strutil"
|
||||
"github.com/kr/pretty"
|
||||
"github.com/mitchellh/cli"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
var _ cli.Command = (*TcpCommand)(nil)
|
||||
var _ cli.CommandAutocomplete = (*TcpCommand)(nil)
|
||||
|
||||
type TcpCommand struct {
|
||||
*base.Command
|
||||
|
||||
Func string
|
||||
}
|
||||
|
||||
func (c *TcpCommand) Synopsis() string {
|
||||
return fmt.Sprintf("%s a tcp-type target within Boundary", textproto.CanonicalMIMEHeaderKey(c.Func))
|
||||
}
|
||||
|
||||
var tcpFlagsMap = map[string][]string{
|
||||
"create": {"scope-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
}
|
||||
|
||||
func (c *TcpCommand) Help() string {
|
||||
var info string
|
||||
switch c.Func {
|
||||
case "create":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets tcp create [options] [args]",
|
||||
"",
|
||||
" Create a tcp-type target. Example:",
|
||||
"",
|
||||
` $ boundary targets tcp create -name prodops -description "Tcp target for ProdOps"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
|
||||
case "update":
|
||||
info = base.WrapForHelpText([]string{
|
||||
"Usage: boundary targets tcp update [options] [args]",
|
||||
"",
|
||||
" Update a tcp-type target given its ID. Example:",
|
||||
"",
|
||||
` $ boundary targets tcp update -id ttcp_1234567890 -name "devops" -description "Tcp target for DevOps"`,
|
||||
"",
|
||||
"",
|
||||
})
|
||||
}
|
||||
return info + c.Flags().Help()
|
||||
}
|
||||
|
||||
func (c *TcpCommand) Flags() *base.FlagSets {
|
||||
set := c.FlagSet(base.FlagSetHTTP | base.FlagSetClient | base.FlagSetOutputFormat)
|
||||
|
||||
if len(tcpFlagsMap[c.Func]) > 0 {
|
||||
f := set.NewFlagSet("Command Options")
|
||||
common.PopulateCommonFlags(c.Command, f, "tcp-type target", tcpFlagsMap[c.Func])
|
||||
}
|
||||
|
||||
return set
|
||||
}
|
||||
|
||||
func (c *TcpCommand) AutocompleteArgs() complete.Predictor {
|
||||
return complete.PredictAnything
|
||||
}
|
||||
|
||||
func (c *TcpCommand) AutocompleteFlags() complete.Flags {
|
||||
return c.Flags().Completions()
|
||||
}
|
||||
|
||||
func (c *TcpCommand) Run(args []string) int {
|
||||
if c.Func == "" {
|
||||
return cli.RunResultHelp
|
||||
}
|
||||
|
||||
f := c.Flags()
|
||||
|
||||
if err := f.Parse(args); err != nil {
|
||||
c.UI.Error(err.Error())
|
||||
return 1
|
||||
}
|
||||
|
||||
if strutil.StrListContains(tcpFlagsMap[c.Func], "id") && c.FlagId == "" {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(tcpFlagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error creating API client: %s", err.Error()))
|
||||
return 2
|
||||
}
|
||||
|
||||
var opts []targets.Option
|
||||
|
||||
switch c.FlagName {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultName())
|
||||
default:
|
||||
opts = append(opts, targets.WithName(c.FlagName))
|
||||
}
|
||||
|
||||
switch c.FlagDescription {
|
||||
case "":
|
||||
case "null":
|
||||
opts = append(opts, targets.DefaultDescription())
|
||||
default:
|
||||
opts = append(opts, targets.WithDescription(c.FlagDescription))
|
||||
}
|
||||
|
||||
targetClient := targets.NewClient(client)
|
||||
|
||||
// Perform check-and-set when needed
|
||||
var version uint32
|
||||
switch c.Func {
|
||||
case "create":
|
||||
// These don't update so don't need the existing version
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, targets.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
}
|
||||
|
||||
var catalog *targets.Target
|
||||
var apiErr *api.Error
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
catalog, apiErr, err = targetClient.Create(c.Context, "tcp", c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
catalog, apiErr, err = targetClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
}
|
||||
|
||||
plural := "tcp-type target"
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error trying to %s %s: %s", c.Func, plural, err.Error()))
|
||||
return 2
|
||||
}
|
||||
if apiErr != nil {
|
||||
c.UI.Error(fmt.Sprintf("Error from controller when performing %s on %s: %s", c.Func, plural, pretty.Sprint(apiErr)))
|
||||
return 1
|
||||
}
|
||||
|
||||
switch base.Format(c.UI) {
|
||||
case "table":
|
||||
c.UI.Output(generateTargetTableOutput(catalog))
|
||||
case "json":
|
||||
b, err := base.JsonFormatter{}.Format(catalog)
|
||||
if err != nil {
|
||||
c.UI.Error(fmt.Errorf("Error formatting as JSON: %w", err).Error())
|
||||
return 1
|
||||
}
|
||||
c.UI.Output(string(b))
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
||||
@@ -12,6 +12,7 @@ func generateUserTableOutput(in *users.User) string {
|
||||
|
||||
nonAttributeMap := map[string]interface{}{
|
||||
"ID": in.Id,
|
||||
"Scope ID": in.Scope.Id,
|
||||
"Version": in.Version,
|
||||
"Created Time": in.CreatedTime.Local().Format(time.RFC3339),
|
||||
"Updated Time": in.UpdatedTime.Local().Format(time.RFC3339),
|
||||
|
||||
@@ -28,10 +28,11 @@ func (c *Command) Synopsis() string {
|
||||
}
|
||||
|
||||
var flagsMap = map[string][]string{
|
||||
"create": {"name", "description"},
|
||||
"create": {"scope-id", "name", "description"},
|
||||
"update": {"id", "name", "description", "version"},
|
||||
"read": {"id"},
|
||||
"delete": {"id"},
|
||||
"list": {"scope-id"},
|
||||
}
|
||||
|
||||
func (c *Command) Help() string {
|
||||
@@ -77,6 +78,10 @@ func (c *Command) Run(args []string) int {
|
||||
c.UI.Error("ID is required but not passed in via -id")
|
||||
return 1
|
||||
}
|
||||
if strutil.StrListContains(flagsMap[c.Func], "scope-id") && c.FlagScopeId == "" {
|
||||
c.UI.Error("Scope ID must be passed in via -scope-id")
|
||||
return 1
|
||||
}
|
||||
|
||||
client, err := c.Client()
|
||||
if err != nil {
|
||||
@@ -112,7 +117,7 @@ func (c *Command) Run(args []string) int {
|
||||
default:
|
||||
switch c.FlagVersion {
|
||||
case 0:
|
||||
opts = append(opts, users.WithAutomaticVersioning())
|
||||
opts = append(opts, users.WithAutomaticVersioning(true))
|
||||
default:
|
||||
version = uint32(c.FlagVersion)
|
||||
}
|
||||
@@ -125,7 +130,7 @@ func (c *Command) Run(args []string) int {
|
||||
|
||||
switch c.Func {
|
||||
case "create":
|
||||
user, apiErr, err = userClient.Create(c.Context, opts...)
|
||||
user, apiErr, err = userClient.Create(c.Context, c.FlagScopeId, opts...)
|
||||
case "update":
|
||||
user, apiErr, err = userClient.Update(c.Context, c.FlagId, version, opts...)
|
||||
case "read":
|
||||
@@ -133,7 +138,7 @@ func (c *Command) Run(args []string) int {
|
||||
case "delete":
|
||||
existed, apiErr, err = userClient.Delete(c.Context, c.FlagId, opts...)
|
||||
case "list":
|
||||
listedUsers, apiErr, err = userClient.List(c.Context, opts...)
|
||||
listedUsers, apiErr, err = userClient.List(c.Context, c.FlagScopeId, opts...)
|
||||
}
|
||||
|
||||
plural := "user"
|
||||
|
||||
@@ -4,11 +4,20 @@ import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/cmd/base"
|
||||
"github.com/posener/complete"
|
||||
)
|
||||
|
||||
func PopulateCommonFlags(c *base.Command, f *base.FlagSet, resourceType string, flagNames []string) {
|
||||
for _, name := range flagNames {
|
||||
switch name {
|
||||
case "scope-id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "scope-id",
|
||||
Target: &c.FlagScopeId,
|
||||
Default: "global",
|
||||
Completion: complete.PredictAnything,
|
||||
Usage: `Scope in which to make the request. Defaults to "global".`,
|
||||
})
|
||||
case "id":
|
||||
f.StringVar(&base.StringVar{
|
||||
Name: "id",
|
||||
|
||||
@@ -289,6 +289,40 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/auth-methods/{auth_method_id}:authenticate": {
|
||||
"post": {
|
||||
"summary": "Authenticate a user to an scope and retrieve an authentication token.",
|
||||
"operationId": "AuthenticationService_Authenticate",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.resources.authtokens.v1.AuthToken"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "auth_method_id",
|
||||
"description": "The id to the authmethod in the system being used for authentication. The auth method must be in the scope\nbeing logged in to.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"name": "body",
|
||||
"in": "body",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"$ref": "#/definitions/controller.api.services.v1.AuthenticateRequest"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"controller.api.services.v1.AuthenticationService"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/auth-methods/{id}": {
|
||||
"get": {
|
||||
"summary": "Gets a single AuthMethod",
|
||||
@@ -1881,7 +1915,7 @@
|
||||
"/v1/scopes/*/auth-methods/{auth_method_id}:authenticate": {
|
||||
"post": {
|
||||
"summary": "Authenticate a user to an scope and retrieve an authentication token.",
|
||||
"operationId": "AuthenticationService_Authenticate",
|
||||
"operationId": "AuthenticationService_Authenticate2",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "",
|
||||
@@ -4984,7 +5018,7 @@
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"old_password": {
|
||||
"current_password": {
|
||||
"type": "string"
|
||||
},
|
||||
"new_password": {
|
||||
|
||||
@@ -659,10 +659,10 @@ type ChangePasswordRequest struct {
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
OldPassword string `protobuf:"bytes,3,opt,name=old_password,proto3" json:"old_password,omitempty"`
|
||||
NewPassword string `protobuf:"bytes,4,opt,name=new_password,proto3" json:"new_password,omitempty"`
|
||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||
Version uint32 `protobuf:"varint,2,opt,name=version,proto3" json:"version,omitempty"`
|
||||
CurrentPassword string `protobuf:"bytes,3,opt,name=current_password,proto3" json:"current_password,omitempty"`
|
||||
NewPassword string `protobuf:"bytes,4,opt,name=new_password,proto3" json:"new_password,omitempty"`
|
||||
}
|
||||
|
||||
func (x *ChangePasswordRequest) Reset() {
|
||||
@@ -711,9 +711,9 @@ func (x *ChangePasswordRequest) GetVersion() uint32 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *ChangePasswordRequest) GetOldPassword() string {
|
||||
func (x *ChangePasswordRequest) GetCurrentPassword() string {
|
||||
if x != nil {
|
||||
return x.OldPassword
|
||||
return x.CurrentPassword
|
||||
}
|
||||
return ""
|
||||
}
|
||||
@@ -858,138 +858,139 @@ var file_controller_api_services_v1_account_service_proto_rawDesc = []byte{
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65,
|
||||
0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x22, 0x89, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73,
|
||||
0x6d, 0x22, 0x91, 0x01, 0x0a, 0x15, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73,
|
||||
0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69,
|
||||
0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x69, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x5f, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6c, 0x64,
|
||||
0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x77,
|
||||
0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x5b, 0x0a,
|
||||
0x16, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x41, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x52, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x32, 0xfc, 0x0d, 0x0a, 0x0e, 0x41,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xd9, 0x01,
|
||||
0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x6c, 0x82, 0xd3, 0xe4,
|
||||
0x93, 0x02, 0x4c, 0x12, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x31, 0x12, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63,
|
||||
0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68,
|
||||
0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b,
|
||||
0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
|
||||
0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c,
|
||||
0x65, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0xf0, 0x01, 0x0a, 0x0c, 0x4c, 0x69,
|
||||
0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82,
|
||||
0xd3, 0xe4, 0x93, 0x02, 0x45, 0x12, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x5a, 0x35, 0x12, 0x33, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73,
|
||||
0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64,
|
||||
0x7d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x92, 0x41, 0x2f, 0x12, 0x2d, 0x4c,
|
||||
0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73, 0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20,
|
||||
0x61, 0x75, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x12, 0x99, 0x02, 0x0a,
|
||||
0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61,
|
||||
0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
|
||||
0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70,
|
||||
0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0xa2, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x62, 0x22, 0x0c, 0x2f, 0x76,
|
||||
0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x5a, 0x46, 0x22, 0x38, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a,
|
||||
0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f,
|
||||
0x69, 0x64, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41,
|
||||
0x37, 0x12, 0x35, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e,
|
||||
0x67, 0x6c, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x61, 0x75, 0x74, 0x68,
|
||||
0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e, 0x12, 0xec, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65,
|
||||
0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0x76, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x58, 0x32, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x5a, 0x37, 0x32, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a,
|
||||
0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f,
|
||||
0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92,
|
||||
0x41, 0x15, 0x12, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x12, 0xd4, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65,
|
||||
0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74,
|
||||
0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69,
|
||||
0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f,
|
||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72,
|
||||
0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e,
|
||||
0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x2a, 0x11, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x2b, 0x2a, 0x29, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d,
|
||||
0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41, 0x15, 0x12, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74,
|
||||
0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x12, 0x93,
|
||||
0x02, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2e,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
|
||||
0xa2, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6c, 0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d,
|
||||
0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x01, 0x2a, 0x5a, 0x41, 0x22, 0x36, 0x2f,
|
||||
0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x2a, 0x0a, 0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74,
|
||||
0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||
0x10, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x12, 0x22, 0x0a, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72,
|
||||
0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x6e, 0x65, 0x77, 0x5f, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x22, 0x5b, 0x0a, 0x16, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12,
|
||||
0x41, 0x0a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2d, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x72,
|
||||
0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x2e, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x04, 0x69, 0x74,
|
||||
0x65, 0x6d, 0x32, 0xfc, 0x0d, 0x0a, 0x0e, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x53, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xd9, 0x01, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x47, 0x65, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f,
|
||||
0x6e, 0x73, 0x65, 0x22, 0x6c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x4c, 0x12, 0x11, 0x2f, 0x76, 0x31,
|
||||
0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x5a, 0x31,
|
||||
0x12, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61,
|
||||
0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x62, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x17, 0x12, 0x15, 0x47, 0x65, 0x74, 0x73,
|
||||
0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x12, 0xf0, 0x01, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x12, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73,
|
||||
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x7d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x45, 0x12, 0x0c, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x5a, 0x35, 0x12, 0x33, 0x2f,
|
||||
0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68,
|
||||
0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x73,
|
||||
0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04,
|
||||
0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2d, 0x12, 0x2b, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68,
|
||||
0x65, 0x20, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74,
|
||||
0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x2e, 0x12, 0xa2, 0x02, 0x0a, 0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65,
|
||||
0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77,
|
||||
0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e,
|
||||
0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa8,
|
||||
0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x72, 0x22, 0x21, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x01, 0x2a, 0x5a, 0x44, 0x22,
|
||||
0x39, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75,
|
||||
0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63,
|
||||
0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x63, 0x68, 0x61, 0x6e, 0x67,
|
||||
0x65, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69,
|
||||
0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2d, 0x12, 0x2b, 0x53, 0x65,
|
||||
0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20,
|
||||
0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64,
|
||||
0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d,
|
||||
0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x92, 0x41, 0x2f, 0x12, 0x2d, 0x4c, 0x69, 0x73, 0x74, 0x73, 0x20, 0x61, 0x6c, 0x6c,
|
||||
0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x20, 0x69, 0x6e, 0x20, 0x61, 0x20, 0x73,
|
||||
0x70, 0x65, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x61, 0x75, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74,
|
||||
0x68, 0x6f, 0x64, 0x2e, 0x12, 0x99, 0x02, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41,
|
||||
0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63,
|
||||
0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa2, 0x01, 0x82, 0xd3,
|
||||
0xe4, 0x93, 0x02, 0x62, 0x22, 0x0c, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x46, 0x22, 0x38, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x69, 0x74, 0x65, 0x6d, 0x2e, 0x61, 0x75, 0x74, 0x68,
|
||||
0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x2f, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x73, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x37, 0x12, 0x35, 0x43, 0x72, 0x65, 0x61, 0x74,
|
||||
0x65, 0x73, 0x20, 0x61, 0x20, 0x73, 0x69, 0x6e, 0x67, 0x6c, 0x65, 0x20, 0x61, 0x63, 0x63, 0x6f,
|
||||
0x75, 0x6e, 0x74, 0x20, 0x69, 0x6e, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69,
|
||||
0x64, 0x65, 0x64, 0x20, 0x61, 0x75, 0x74, 0x68, 0x20, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x2e,
|
||||
0x12, 0xec, 0x01, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75,
|
||||
0x6e, 0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71,
|
||||
0x75, 0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76,
|
||||
0x31, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x76, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x58, 0x32,
|
||||
0x11, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69,
|
||||
0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x5a, 0x37, 0x32, 0x29, 0x2f, 0x76, 0x31, 0x2f,
|
||||
0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65,
|
||||
0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73,
|
||||
0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x3a, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x15, 0x12, 0x13, 0x55, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x12,
|
||||
0xd4, 0x01, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e,
|
||||
0x74, 0x12, 0x30, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61,
|
||||
0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x44,
|
||||
0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75,
|
||||
0x65, 0x73, 0x74, 0x1a, 0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72,
|
||||
0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x41, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x5e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x40, 0x2a, 0x11,
|
||||
0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64,
|
||||
0x7d, 0x5a, 0x2b, 0x2a, 0x29, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f,
|
||||
0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x2a,
|
||||
0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d, 0x92, 0x41,
|
||||
0x15, 0x12, 0x13, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x73, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x63,
|
||||
0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x12, 0x93, 0x02, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x50, 0x61,
|
||||
0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12, 0x2e, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52,
|
||||
0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2f, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c,
|
||||
0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x53, 0x65, 0x74, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52,
|
||||
0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa2, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x6c,
|
||||
0x22, 0x1e, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b,
|
||||
0x69, 0x64, 0x7d, 0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64,
|
||||
0x3a, 0x01, 0x2a, 0x5a, 0x41, 0x22, 0x36, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65,
|
||||
0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73,
|
||||
0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69, 0x64, 0x7d,
|
||||
0x3a, 0x73, 0x65, 0x74, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x3a, 0x01, 0x2a,
|
||||
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x2d, 0x12,
|
||||
0x2b, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70, 0x72, 0x6f, 0x76, 0x69,
|
||||
0x64, 0x65, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x2e, 0x12, 0xa2, 0x02, 0x0a,
|
||||
0x0e, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x12,
|
||||
0x31, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69,
|
||||
0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x43, 0x68, 0x61,
|
||||
0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65,
|
||||
0x73, 0x74, 0x1a, 0x32, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x61, 0x70, 0x69, 0x2e, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x52, 0x65,
|
||||
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa8, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x72, 0x22,
|
||||
0x21, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69,
|
||||
0x64, 0x7d, 0x3a, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x3a, 0x01, 0x2a, 0x5a, 0x44, 0x22, 0x39, 0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f,
|
||||
0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f,
|
||||
0x64, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x73, 0x2f, 0x7b, 0x69,
|
||||
0x64, 0x7d, 0x3a, 0x63, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x2d, 0x70, 0x61, 0x73, 0x73, 0x77, 0x6f,
|
||||
0x72, 0x64, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x62, 0x04, 0x69, 0x74, 0x65,
|
||||
0x6d, 0x92, 0x41, 0x2d, 0x12, 0x2b, 0x53, 0x65, 0x74, 0x73, 0x20, 0x74, 0x68, 0x65, 0x20, 0x70,
|
||||
0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x74, 0x68, 0x65, 0x20,
|
||||
0x70, 0x72, 0x6f, 0x76, 0x69, 0x64, 0x65, 0x64, 0x20, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74,
|
||||
0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
|
||||
0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61,
|
||||
0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73,
|
||||
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -334,8 +334,8 @@ var file_controller_api_services_v1_authenticate_service_proto_rawDesc = []byte{
|
||||
0x17, 0x0a, 0x15, 0x44, 0x65, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74,
|
||||
0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x18, 0x0a, 0x16, 0x44, 0x65, 0x61, 0x75,
|
||||
0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
|
||||
0x73, 0x65, 0x32, 0xa0, 0x02, 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x86, 0x02, 0x0a,
|
||||
0x73, 0x65, 0x32, 0xdb, 0x02, 0x0a, 0x15, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63,
|
||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0xc1, 0x02, 0x0a,
|
||||
0x0c, 0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x2f, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x73,
|
||||
0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x65,
|
||||
@@ -343,21 +343,25 @@ var file_controller_api_services_v1_authenticate_service_proto_rawDesc = []byte{
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x61, 0x70, 0x69, 0x2e,
|
||||
0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x2e, 0x76, 0x31, 0x2e, 0x41, 0x75, 0x74, 0x68,
|
||||
0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
|
||||
0x22, 0x92, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x42, 0x22, 0x37, 0x2f, 0x76, 0x31, 0x2f, 0x73,
|
||||
0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74,
|
||||
0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f,
|
||||
0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61,
|
||||
0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x47, 0x12, 0x45,
|
||||
0x41, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75,
|
||||
0x73, 0x65, 0x72, 0x20, 0x74, 0x6f, 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x20,
|
||||
0x61, 0x6e, 0x64, 0x20, 0x72, 0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20,
|
||||
0x61, 0x75, 0x74, 0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74,
|
||||
0x6f, 0x6b, 0x65, 0x6e, 0x2e, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
|
||||
0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f,
|
||||
0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f,
|
||||
0x67, 0x65, 0x6e, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61,
|
||||
0x70, 0x69, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76,
|
||||
0x69, 0x63, 0x65, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x22, 0xcd, 0x01, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x7d, 0x22, 0x2e, 0x2f, 0x76, 0x31, 0x2f, 0x61,
|
||||
0x75, 0x74, 0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74,
|
||||
0x68, 0x5f, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74,
|
||||
0x68, 0x65, 0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x5a, 0x42, 0x22, 0x37,
|
||||
0x2f, 0x76, 0x31, 0x2f, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x73, 0x2f, 0x2a, 0x2f, 0x61, 0x75, 0x74,
|
||||
0x68, 0x2d, 0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x73, 0x2f, 0x7b, 0x61, 0x75, 0x74, 0x68, 0x5f,
|
||||
0x6d, 0x65, 0x74, 0x68, 0x6f, 0x64, 0x5f, 0x69, 0x64, 0x7d, 0x3a, 0x61, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x3a, 0x01, 0x2a, 0x62, 0x04, 0x69, 0x74, 0x65, 0x6d,
|
||||
0x62, 0x04, 0x69, 0x74, 0x65, 0x6d, 0x92, 0x41, 0x47, 0x12, 0x45, 0x41, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x65, 0x20, 0x61, 0x20, 0x75, 0x73, 0x65, 0x72, 0x20, 0x74,
|
||||
0x6f, 0x20, 0x61, 0x6e, 0x20, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x72,
|
||||
0x65, 0x74, 0x72, 0x69, 0x65, 0x76, 0x65, 0x20, 0x61, 0x6e, 0x20, 0x61, 0x75, 0x74, 0x68, 0x65,
|
||||
0x6e, 0x74, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x2e,
|
||||
0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68,
|
||||
0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72,
|
||||
0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x63,
|
||||
0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x73, 0x65,
|
||||
0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x3b, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x73, 0x62,
|
||||
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
|
||||
@@ -97,6 +97,74 @@ func local_request_AuthenticationService_Authenticate_0(ctx context.Context, mar
|
||||
|
||||
}
|
||||
|
||||
func request_AuthenticationService_Authenticate_1(ctx context.Context, marshaler runtime.Marshaler, client AuthenticationServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AuthenticateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["auth_method_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
|
||||
}
|
||||
|
||||
protoReq.AuthMethodId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
|
||||
}
|
||||
|
||||
msg, err := client.Authenticate(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_AuthenticationService_Authenticate_1(ctx context.Context, marshaler runtime.Marshaler, server AuthenticationServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq AuthenticateRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
newReader, berr := utilities.IOReaderFactory(req.Body)
|
||||
if berr != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", berr)
|
||||
}
|
||||
if err := marshaler.NewDecoder(newReader()).Decode(&protoReq); err != nil && err != io.EOF {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
|
||||
}
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["auth_method_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "auth_method_id")
|
||||
}
|
||||
|
||||
protoReq.AuthMethodId, err = runtime.String(val)
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "auth_method_id", err)
|
||||
}
|
||||
|
||||
msg, err := server.Authenticate(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterAuthenticationServiceHandlerServer registers the http handlers for service AuthenticationService to "mux".
|
||||
// UnaryRPC :call AuthenticationServiceServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -123,6 +191,26 @@ func RegisterAuthenticationServiceHandlerServer(ctx context.Context, mux *runtim
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_AuthenticationService_Authenticate_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/controller.api.services.v1.AuthenticationService/Authenticate")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_AuthenticationService_Authenticate_1(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AuthenticationService_Authenticate_1(ctx, mux, outboundMarshaler, w, req, response_AuthenticationService_Authenticate_1{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -184,6 +272,26 @@ func RegisterAuthenticationServiceHandlerClient(ctx context.Context, mux *runtim
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("POST", pattern_AuthenticationService_Authenticate_1, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req, "/controller.api.services.v1.AuthenticationService/Authenticate")
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_AuthenticationService_Authenticate_1(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_AuthenticationService_Authenticate_1(ctx, mux, outboundMarshaler, w, req, response_AuthenticationService_Authenticate_1{resp}, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -196,10 +304,23 @@ func (m response_AuthenticationService_Authenticate_0) XXX_ResponseBody() interf
|
||||
return response.Item
|
||||
}
|
||||
|
||||
type response_AuthenticationService_Authenticate_1 struct {
|
||||
proto.Message
|
||||
}
|
||||
|
||||
func (m response_AuthenticationService_Authenticate_1) XXX_ResponseBody() interface{} {
|
||||
response := m.Message.(*AuthenticateResponse)
|
||||
return response.Item
|
||||
}
|
||||
|
||||
var (
|
||||
pattern_AuthenticationService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "auth-methods", "auth_method_id"}, "authenticate"))
|
||||
pattern_AuthenticationService_Authenticate_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "auth-methods", "auth_method_id"}, "authenticate"))
|
||||
|
||||
pattern_AuthenticationService_Authenticate_1 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 2, 2, 1, 0, 4, 1, 5, 3}, []string{"v1", "scopes", "auth-methods", "auth_method_id"}, "authenticate"))
|
||||
)
|
||||
|
||||
var (
|
||||
forward_AuthenticationService_Authenticate_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_AuthenticationService_Authenticate_1 = runtime.ForwardResponseMessage
|
||||
)
|
||||
@@ -178,16 +178,16 @@ func TestRepository_AddSetMembers_Combinations(t *testing.T) {
|
||||
|
||||
// second call - add new set of hosts - should succeed
|
||||
set.Version = set.Version + 1
|
||||
hosts2 := TestHosts(t, conn, c.PublicId, 5)
|
||||
Hosts := TestHosts(t, conn, c.PublicId, 5)
|
||||
var hostIds2 []string
|
||||
for _, h := range hosts2 {
|
||||
for _, h := range Hosts {
|
||||
hostIds2 = append(hostIds2, h.PublicId)
|
||||
}
|
||||
got2, err2 := repo.AddSetMembers(context.Background(), prj.PublicId, set.PublicId, set.Version, hostIds2)
|
||||
require.NoError(err2)
|
||||
require.NotNil(got2)
|
||||
|
||||
hosts = append(hosts, hosts2...)
|
||||
hosts = append(hosts, Hosts...)
|
||||
assert.Len(got2, len(hosts))
|
||||
assert.Empty(cmp.Diff(hosts, got2, opts...))
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, set.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
@@ -391,9 +391,9 @@ func TestRepository_DeleteSetMembers_Combinations(t *testing.T) {
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, set.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_DELETE), db.WithCreateNotBefore(10*time.Second)))
|
||||
|
||||
// verify no members remain
|
||||
members2, err := getHosts(context.Background(), repo.reader, set.PublicId, unlimited)
|
||||
Members, err := getHosts(context.Background(), repo.reader, set.PublicId, unlimited)
|
||||
require.NoError(err)
|
||||
require.Empty(members2)
|
||||
require.Empty(Members)
|
||||
}
|
||||
|
||||
func TestRepository_SetSetMembers_Parameters(t *testing.T) {
|
||||
|
||||
@@ -539,14 +539,14 @@ func TestRepository_UpdateSet(t *testing.T) {
|
||||
assert.Empty(gotHosts1)
|
||||
|
||||
sB.Name = name
|
||||
got2, gotHosts2, gotCount2, err := repo.UpdateSet(context.Background(), prj.GetPublicId(), sB, 1, []string{"name"})
|
||||
got2, gotHosts, gotCount2, err := repo.UpdateSet(context.Background(), prj.GetPublicId(), sB, 1, []string{"name"})
|
||||
assert.Truef(errors.Is(err, db.ErrNotUnique), "want err: %v got: %v", db.ErrNotUnique, err)
|
||||
assert.Nil(got2)
|
||||
assert.Equal(db.NoRowsAffected, gotCount2, "row count")
|
||||
err = db.TestVerifyOplog(t, rw, sB.PublicId, db.WithOperation(oplog.OpType_OP_TYPE_UPDATE), db.WithCreateNotBefore(10*time.Second))
|
||||
assert.Error(err)
|
||||
assert.True(errors.Is(db.ErrRecordNotFound, err))
|
||||
assert.Empty(gotHosts2)
|
||||
assert.Empty(gotHosts)
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-Catalogs", func(t *testing.T) {
|
||||
|
||||
@@ -46,16 +46,16 @@ func TestScopes(t *testing.T, repo *Repository, opt ...Option) (org *Scope, prj
|
||||
|
||||
opts := getOpts(opt...)
|
||||
|
||||
org, err := NewOrg()
|
||||
org, err := NewOrg(opt...)
|
||||
require.NoError(err)
|
||||
org, err = repo.CreateScope(context.Background(), org, opts.withUserId)
|
||||
org, err = repo.CreateScope(context.Background(), org, opts.withUserId, opt...)
|
||||
require.NoError(err)
|
||||
require.NotNil(org)
|
||||
require.NotEmpty(org.GetPublicId())
|
||||
|
||||
prj, err = NewProject(org.GetPublicId())
|
||||
prj, err = NewProject(org.GetPublicId(), opt...)
|
||||
require.NoError(err)
|
||||
prj, err = repo.CreateScope(context.Background(), prj, opts.withUserId)
|
||||
prj, err = repo.CreateScope(context.Background(), prj, opts.withUserId, opt...)
|
||||
require.NoError(err)
|
||||
require.NotNil(prj)
|
||||
require.NotEmpty(prj.GetPublicId())
|
||||
|
||||
@@ -205,7 +205,7 @@ message SetPasswordResponse {
|
||||
message ChangePasswordRequest {
|
||||
string id = 1;
|
||||
uint32 version = 2;
|
||||
string old_password = 3 [json_name="old_password"];
|
||||
string current_password = 3 [json_name="current_password"];
|
||||
string new_password = 4 [json_name="new_password"];
|
||||
}
|
||||
|
||||
|
||||
@@ -13,9 +13,14 @@ service AuthenticationService {
|
||||
// Authenticate validates credentials provided and returns an auth token.
|
||||
rpc Authenticate(AuthenticateRequest) returns (AuthenticateResponse) {
|
||||
option (google.api.http) = {
|
||||
post: "/v1/scopes/*/auth-methods/{auth_method_id}:authenticate"
|
||||
post: "/v1/auth-methods/{auth_method_id}:authenticate"
|
||||
body: "*"
|
||||
response_body: "item"
|
||||
additional_bindings: {
|
||||
post: "/v1/scopes/*/auth-methods/{auth_method_id}:authenticate"
|
||||
body: "*"
|
||||
response_body: "item"
|
||||
}
|
||||
};
|
||||
option (grpc.gateway.protoc_gen_openapiv2.options.openapiv2_operation) = {
|
||||
summary: "Authenticate a user to an scope and retrieve an authentication token."
|
||||
|
||||
@@ -141,7 +141,7 @@ func (s Service) ChangePassword(ctx context.Context, req *pbs.ChangePasswordRequ
|
||||
if authResults.Error != nil {
|
||||
return nil, authResults.Error
|
||||
}
|
||||
u, err := s.changePasswordInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetVersion(), req.GetOldPassword(), req.GetNewPassword())
|
||||
u, err := s.changePasswordInRepo(ctx, authResults.Scope.GetId(), req.GetId(), req.GetVersion(), req.GetCurrentPassword(), req.GetNewPassword())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -295,12 +295,12 @@ func (s Service) listFromRepo(ctx context.Context, authMethodId string) ([]*pb.A
|
||||
return outUl, nil
|
||||
}
|
||||
|
||||
func (s Service) changePasswordInRepo(ctx context.Context, scopeId, id string, version uint32, oldPassword, newPassword string) (*pb.Account, error) {
|
||||
func (s Service) changePasswordInRepo(ctx context.Context, scopeId, id string, version uint32, currentPassword, newPassword string) (*pb.Account, error) {
|
||||
repo, err := s.repoFn()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := repo.ChangePassword(ctx, scopeId, id, oldPassword, newPassword, version)
|
||||
out, err := repo.ChangePassword(ctx, scopeId, id, currentPassword, newPassword, version)
|
||||
if err != nil {
|
||||
return nil, status.Errorf(codes.Internal, "Unable to change password: %v.", err)
|
||||
}
|
||||
@@ -448,8 +448,8 @@ func validateChangePasswordRequest(req *pbs.ChangePasswordRequest) error {
|
||||
if req.GetNewPassword() == "" {
|
||||
badFields["new_password"] = "This is a required field."
|
||||
}
|
||||
if req.GetOldPassword() == "" {
|
||||
badFields["old_password"] = "This is a required field."
|
||||
if req.GetCurrentPassword() == "" {
|
||||
badFields["current_password"] = "This is a required field."
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Improperly formatted identifier.", badFields)
|
||||
|
||||
@@ -950,10 +950,10 @@ func TestChangePassword(t *testing.T) {
|
||||
acct := createAccount(t, "originalpassword")
|
||||
|
||||
changeResp, err := tested.ChangePassword(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.ChangePasswordRequest{
|
||||
Id: acct.GetId(),
|
||||
Version: acct.GetVersion(),
|
||||
OldPassword: "originalpassword",
|
||||
NewPassword: "a different password",
|
||||
Id: acct.GetId(),
|
||||
Version: acct.GetVersion(),
|
||||
CurrentPassword: "originalpassword",
|
||||
NewPassword: "a different password",
|
||||
})
|
||||
require.NoError(err)
|
||||
assert.Equal(acct.GetVersion()+1, changeResp.GetItem().GetVersion())
|
||||
@@ -969,10 +969,10 @@ func TestChangePassword(t *testing.T) {
|
||||
acct := createAccount(t, "originalpassword")
|
||||
|
||||
changeResp, err := tested.ChangePassword(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.ChangePasswordRequest{
|
||||
Id: acct.GetId(),
|
||||
Version: acct.GetVersion(),
|
||||
OldPassword: "thewrongpassword",
|
||||
NewPassword: "a different password",
|
||||
Id: acct.GetId(),
|
||||
Version: acct.GetVersion(),
|
||||
CurrentPassword: "thewrongpassword",
|
||||
NewPassword: "a different password",
|
||||
})
|
||||
assert.Error(err)
|
||||
assert.Nil(changeResp)
|
||||
@@ -1042,10 +1042,10 @@ func TestChangePassword(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
changeResp, err := tested.ChangePassword(auth.DisabledAuthTestContext(auth.WithScopeId(o.GetPublicId())), &pbs.ChangePasswordRequest{
|
||||
Id: tt.accountId,
|
||||
Version: tt.version,
|
||||
OldPassword: tt.oldPW,
|
||||
NewPassword: tt.newPW,
|
||||
Id: tt.accountId,
|
||||
Version: tt.version,
|
||||
CurrentPassword: tt.oldPW,
|
||||
NewPassword: tt.newPW,
|
||||
})
|
||||
assert.Error(err)
|
||||
assert.Nil(changeResp)
|
||||
|
||||
@@ -199,7 +199,7 @@ func validateAuthenticateRequest(req *pbs.AuthenticateRequest) error {
|
||||
}
|
||||
tType := strings.ToLower(strings.TrimSpace(req.GetTokenType()))
|
||||
if tType != "" && tType != "token" && tType != "cookie" {
|
||||
badFields["token_type"] = "The only accepted type is 'token'."
|
||||
badFields["token_type"] = `The only accepted types are "token" and "cookie".`
|
||||
}
|
||||
if len(badFields) > 0 {
|
||||
return handlers.InvalidArgumentErrorf("Invalid fields provided in request.", badFields)
|
||||
|
||||
@@ -36,14 +36,14 @@ func TestAuthenticationMulti(t *testing.T) {
|
||||
defer c2.Shutdown()
|
||||
|
||||
auth := authmethods.NewClient(c1.Client())
|
||||
token1, apiErr, err := auth.Authenticate(c1.Context(), amId, user, password)
|
||||
token1, apiErr, err := auth.Authenticate(c1.Context(), amId, map[string]interface{}{"login_name": user, "password": password})
|
||||
require.Nil(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(token1)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
auth = authmethods.NewClient(c2.Client())
|
||||
token2, apiErr, err := auth.Authenticate(c2.Context(), amId, user, password)
|
||||
token2, apiErr, err := auth.Authenticate(c2.Context(), amId, map[string]interface{}{"login_name": user, "password": password})
|
||||
require.Nil(err)
|
||||
require.Nil(apiErr)
|
||||
require.NotNil(token2)
|
||||
@@ -51,9 +51,7 @@ func TestAuthenticationMulti(t *testing.T) {
|
||||
assert.NotEqual(token1.Token, token2.Token)
|
||||
|
||||
c1.Client().SetToken(token1.Token)
|
||||
c1.Client().SetScopeId(scope.Global.String())
|
||||
c2.Client().SetToken(token1.Token) // Same token, as it should work on both
|
||||
c2.Client().SetScopeId(scope.Global.String())
|
||||
|
||||
// Create a project, read from the other
|
||||
org, apiErr, err := scopes.NewClient(c1.Client()).Create(c1.Context(), scope.Global.String())
|
||||
|
||||
@@ -103,8 +103,10 @@ func (tc *TestController) Token() *authtokens.AuthToken {
|
||||
token, apiErr, err := authmethods.NewClient(tc.Client()).Authenticate(
|
||||
tc.Context(),
|
||||
tc.b.DevAuthMethodId,
|
||||
tc.b.DevLoginName,
|
||||
tc.b.DevPassword,
|
||||
map[string]interface{}{
|
||||
"login_name": tc.b.DevLoginName,
|
||||
"password": tc.b.DevPassword,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
tc.t.Error(fmt.Errorf("error logging in: %w", err))
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"github.com/hashicorp/boundary/globals"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/servers/controller"
|
||||
"github.com/hashicorp/boundary/internal/types/scope"
|
||||
"github.com/hashicorp/boundary/recovery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -40,7 +41,7 @@ func TestRecoveryNonces(t *testing.T) {
|
||||
// Token 1, try 1
|
||||
client.SetToken(token1)
|
||||
roleClient := roles.NewClient(client)
|
||||
_, apiErr, err := roleClient.Create(tc.Context())
|
||||
_, apiErr, err := roleClient.Create(tc.Context(), scope.Global.String())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
nonces, err := repo.ListNonces(tc.Context())
|
||||
@@ -48,7 +49,7 @@ func TestRecoveryNonces(t *testing.T) {
|
||||
assert.Len(nonces, 1)
|
||||
|
||||
// Token 1, try 2
|
||||
_, apiErr, err = roleClient.Create(tc.Context())
|
||||
_, apiErr, err = roleClient.Create(tc.Context(), scope.Global.String())
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
nonces, err = repo.ListNonces(tc.Context())
|
||||
@@ -56,8 +57,8 @@ func TestRecoveryNonces(t *testing.T) {
|
||||
assert.Len(nonces, 1)
|
||||
|
||||
// Token 2
|
||||
client.SetToken(token2)
|
||||
_, apiErr, err = roleClient.Create(tc.Context())
|
||||
roleClient.ApiClient().SetToken(token2)
|
||||
_, apiErr, err = roleClient.Create(tc.Context(), scope.Global.String())
|
||||
require.NoError(err)
|
||||
assert.Nil(apiErr)
|
||||
nonces, err = repo.ListNonces(tc.Context())
|
||||
@@ -72,8 +73,8 @@ func TestRecoveryNonces(t *testing.T) {
|
||||
|
||||
// And finally, make sure they still can't be used
|
||||
for _, token := range []string{token1, token2} {
|
||||
client.SetToken(token)
|
||||
_, apiErr, err = roleClient.Create(tc.Context())
|
||||
roleClient.ApiClient().SetToken(token)
|
||||
_, apiErr, err = roleClient.Create(tc.Context(), scope.Global.String())
|
||||
require.NoError(err)
|
||||
assert.NotNil(apiErr)
|
||||
nonces, err = repo.ListNonces(tc.Context())
|
||||
|
||||
Reference in new issue
Block a user