Shuffle things around out of new modules

This commit is contained in:
Jeff Mitchell committed 2020-10-07 14:03:42 -04:00
1 parent 70a8051974
commit 5cbfcf8eb6
20 files changed
+2 -29

No files matched your search

-193
View File
@@ -1,193 +0,0 @@
package accounts_test
import (
"fmt"
"net/http"
"os"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/accounts"
"github.com/hashicorp/boundary/api/authmethods"
"github.com/hashicorp/boundary/internal/auth/password"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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, nil)
defer tc.Shutdown()
client := tc.Client()
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)
amResult, err := amClient.Create(tc.Context(), "password", org.GetPublicId())
require.NoError(err)
require.NotNil(amResult)
am := amResult.Item
accountClient := accounts.NewClient(client)
lr, err := accountClient.List(tc.Context(), am.Id)
require.NoError(err)
expected := lr.Items
assert.Len(expected, 0)
expected = append(expected, &accounts.Account{Attributes: map[string]interface{}{"login_name": "loginname0"}})
cr, err := accountClient.Create(tc.Context(), am.Id, accounts.WithPasswordAccountLoginName(expected[0].Attributes["login_name"].(string)))
require.NoError(err)
expected[0] = cr.Item
ulResult, err := accountClient.List(tc.Context(), am.Id)
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ulResult.Items))
for i := 1; i < 10; i++ {
newAcctResult, err := accountClient.Create(tc.Context(), am.Id, accounts.WithPasswordAccountLoginName(fmt.Sprintf("loginname%d", i)))
require.NoError(err)
expected = append(expected, newAcctResult.Item)
}
ulResult, err = accountClient.List(tc.Context(), am.Id)
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ulResult.Items))
}
func comparableSlice(in []*accounts.Account) []accounts.Account {
var filtered []accounts.Account
for _, i := range in {
p := accounts.Account{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
Attributes: i.Attributes,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
amId := token.AuthMethodId
accountClient := accounts.NewClient(client)
checkAccount := func(step string, u *accounts.Account, err error, wantedName string, wantedVersion uint32) {
assert.NoError(err, step)
require.NotNil(u, "returned no resource", step)
gotName := ""
if u.Name != "" {
gotName = u.Name
}
assert.Equal(wantedName, gotName, step)
assert.EqualValues(wantedVersion, u.Version)
}
u, err := accountClient.Create(tc.Context(), amId, accounts.WithName("foo"), accounts.WithPasswordAccountLoginName("loginname"))
checkAccount("create", u.Item, err, "foo", 1)
u, err = accountClient.Read(tc.Context(), u.Item.Id)
checkAccount("read", u.Item, err, "foo", 1)
u, err = accountClient.Update(tc.Context(), u.Item.Id, u.Item.Version, accounts.WithName("bar"))
checkAccount("update", u.Item, err, "bar", 2)
u, err = accountClient.Update(tc.Context(), u.Item.Id, u.Item.Version, accounts.DefaultName())
checkAccount("update", u.Item, err, "", 3)
_, err = accountClient.Delete(tc.Context(), u.Item.Id)
require.NoError(err)
}
func TestCustomMethods(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()
client.SetToken(token.Token)
amId := token.AuthMethodId
accountClient := accounts.NewClient(client)
al, err := accountClient.List(tc.Context(), amId)
require.NoError(err)
require.Len(al.Items, 1)
acct := al.Items[0]
setAcct, err := accountClient.SetPassword(tc.Context(), acct.Id, "setpassword", acct.Version)
require.NoError(err)
require.NotNil(setAcct)
assert.Equal(acct.Version+1, setAcct.Item.Version)
changeAcct, err := accountClient.ChangePassword(tc.Context(), acct.Id, "setpassword", "changepassword", setAcct.Item.Version)
require.NoError(err)
require.NotNil(changeAcct)
assert.Equal(setAcct.Item.Version+1, changeAcct.Item.Version)
}
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()
client.SetToken(token.Token)
amId := token.AuthMethodId
accountClient := accounts.NewClient(client)
u, err := accountClient.Create(tc.Context(), amId, accounts.WithPasswordAccountLoginName("first"))
require.NoError(err)
assert.NotNil(u)
// Updating the wrong version should fail.
_, err = accountClient.Update(tc.Context(), u.Item.Id, 73, accounts.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
// Create another resource with the same name.
_, err = accountClient.Create(tc.Context(), amId, accounts.WithPasswordAccountLoginName("first"))
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
_, err = accountClient.Read(tc.Context(), password.AccountPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = accountClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, err = accountClient.Update(tc.Context(), u.Item.Id, u.Item.Version)
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-36
View File
@@ -1,36 +0,0 @@
package authmethods_test
import (
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/authmethods"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestAuthenticate(t *testing.T) {
assert, require := assert.New(t), require.New(t)
amId := "ampw_1234567890"
tc := controller.NewTestController(t, &controller.TestControllerOpts{
DefaultAuthMethodId: amId,
DefaultLoginName: "user",
DefaultPassword: "passpass",
})
defer tc.Shutdown()
client := tc.Client()
methods := authmethods.NewClient(client)
tok, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
require.NoError(err)
assert.NotNil(tok)
_, err = methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "wrong"})
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValuesf(http.StatusUnauthorized, apiErr.Status, "Expected unauthorized, got %q", apiErr.Message)
}
-155
View File
@@ -1,155 +0,0 @@
package authtokens_test
import (
"net/http"
"sort"
"testing"
"github.com/hashicorp/boundary/api"
"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"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestList(t *testing.T) {
assert, require := assert.New(t), require.New(t)
amId := "ampw_1234567890"
tc := controller.NewTestController(t, &controller.TestControllerOpts{
DefaultAuthMethodId: amId,
DefaultLoginName: "user",
DefaultPassword: "passpass",
})
defer tc.Shutdown()
token := tc.Token()
client := tc.Client()
client.SetToken(token.Token)
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
amClient := authmethods.NewClient(client)
amResult, err := amClient.Create(tc.Context(), "password", org.GetPublicId())
require.NoError(err)
require.NotNil(amResult)
amId = amResult.Item.Id
rolesClient := roles.NewClient(client)
role, err := rolesClient.Create(tc.Context(), org.GetPublicId())
require.NoError(err)
require.NotNil(role)
role, err = rolesClient.AddPrincipals(tc.Context(), role.Item.Id, 0, []string{"u_anon"}, roles.WithAutomaticVersioning(true))
require.NoError(err)
require.NotNil(role)
role, err = rolesClient.AddGrants(tc.Context(), role.Item.Id, 0, []string{"id=*;type=auth-method;actions=authenticate"}, roles.WithAutomaticVersioning(true))
require.NoError(err)
require.NotNil(role)
acctClient := accounts.NewClient(client)
acct, err := acctClient.Create(tc.Context(), amId, accounts.WithPasswordAccountLoginName("user"), accounts.WithPasswordAccountPassword("passpass"))
require.NoError(err)
require.NotNil(acct)
tokens := authtokens.NewClient(client)
atl, err := tokens.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.Empty(atl.Items)
var expected []*authtokens.AuthToken
methods := authmethods.NewClient(client)
at, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
require.NoError(err)
expected = append(expected, at.Item)
atl, err = tokens.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(atl.Items))
for i := 1; i < 10; i++ {
at, err = methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
require.NoError(err)
expected = append(expected, at.Item)
}
atl, err = tokens.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(atl.Items))
}
func comparableResource(i *authtokens.AuthToken) authtokens.AuthToken {
return authtokens.AuthToken{
Id: i.Id,
UserId: i.UserId,
AuthMethodId: i.AuthMethodId,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
ApproximateLastUsedTime: i.ApproximateLastUsedTime,
ExpirationTime: i.ExpirationTime,
}
}
func comparableSlice(in []*authtokens.AuthToken) []authtokens.AuthToken {
var filtered []authtokens.AuthToken
for _, i := range in {
filtered = append(filtered, comparableResource(i))
}
sort.Slice(filtered, func(i, j int) bool {
return filtered[i].Id < filtered[j].Id
})
return filtered
}
func TestCrud(t *testing.T) {
assert, require := assert.New(t), require.New(t)
amId := "ampw_1234567890"
tc := controller.NewTestController(t, &controller.TestControllerOpts{
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, err := methods.Authenticate(tc.Context(), amId, map[string]interface{}{"login_name": "user", "password": "passpass"})
require.NoError(err)
at, err := tokens.Read(tc.Context(), want.Item.Id)
require.NoError(err)
assert.EqualValues(comparableResource(want.Item), comparableResource(at.Item))
_, err = tokens.Delete(tc.Context(), at.Item.Id)
require.NoError(err)
}
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()
client.SetToken(token.Token)
tokens := authtokens.NewClient(client)
_, err := tokens.Read(tc.Context(), authtoken.AuthTokenPrefix+"_doesntexis")
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = tokens.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-72
View File
@@ -1,72 +0,0 @@
package api
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestConfigSetAddress(t *testing.T) {
type test struct {
name string
input string
address string
err string
}
tests := []test{
{
"bare",
"http://127.0.0.1:9200",
"http://127.0.0.1:9200",
"",
},
{
"bare with version",
"http://127.0.0.1:9200/v1",
"http://127.0.0.1:9200",
"",
},
{
"bare with version and trailing slash",
"http://127.0.0.1:9200/v1/",
"http://127.0.0.1:9200",
"",
},
{
"valid top level scope",
"http://127.0.0.1:9200/v1/scopes",
"http://127.0.0.1:9200",
"",
},
{
"valid scope",
"http://127.0.0.1:9200/v1/scopes/scopeid",
"http://127.0.0.1:9200",
"",
},
{
"longer path project",
"http://127.0.0.1:9200/v1/auth-methods",
"http://127.0.0.1:9200",
"",
},
{
"valid project",
"http://127.0.0.1:9200/my-install",
"http://127.0.0.1:9200/my-install",
"",
},
}
for _, v := range tests {
t.Run(v.name, func(t *testing.T) {
var c Config
err := c.setAddr(v.input)
if err != nil {
assert.Equal(t, v.err, err.Error())
}
assert.Equal(t, v.address, c.Addr)
})
}
}
-221
View File
@@ -1,221 +0,0 @@
package groups_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/groups"
"github.com/hashicorp/boundary/api/users"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
grps := groups.NewClient(client)
pl, err := grps.List(tc.Context(), tt.scopeId)
assert.NoError(err)
assert.Empty(pl.Items)
expected := make([]*groups.Group, 10)
for i := 0; i < 10; i++ {
createResult, err := grps.Create(tc.Context(), tt.scopeId, groups.WithName(fmt.Sprint(i)))
require.NoError(err)
expected[i] = createResult.Item
}
pl, err = grps.List(tc.Context(), tt.scopeId)
require.NoError(err)
require.NotNil(pl)
require.Len(pl.Items, 10)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(pl.Items))
})
}
}
func comparableSlice(in []*groups.Group) []groups.Group {
var filtered []groups.Group
for _, i := range in {
p := groups.Group{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
checkGroup := func(step string, g *groups.Group, err error, wantedName string, wantedVersion uint32, expectedUserIds []string) {
require.NoError(err, step)
assert.NotNil(g, "returned no resource", step)
gotName := ""
if g.Name != "" {
gotName = g.Name
}
assert.Equal(wantedName, gotName, step)
assert.EqualValues(wantedVersion, g.Version)
assert.Equal(len(expectedUserIds), len(g.MemberIds))
if len(expectedUserIds) > 0 {
assert.EqualValues(expectedUserIds, g.MemberIds)
}
}
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
user1, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
require.NoError(err)
user2, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
require.NoError(err)
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
groupsClient := groups.NewClient(client)
g, err := groupsClient.Create(tc.Context(), tt.scopeId, groups.WithName("foo"))
checkGroup("create", g.Item, err, "foo", 1, nil)
g, err = groupsClient.Read(tc.Context(), g.Item.Id)
checkGroup("read", g.Item, err, "foo", 1, nil)
g, err = groupsClient.Update(tc.Context(), g.Item.Id, g.Item.Version, groups.WithName("bar"))
checkGroup("update", g.Item, err, "bar", 2, nil)
g, err = groupsClient.Update(tc.Context(), g.Item.Id, g.Item.Version, groups.DefaultName())
checkGroup("update", g.Item, err, "", 3, nil)
g, err = groupsClient.AddMembers(tc.Context(), g.Item.Id, g.Item.Version, []string{user1.Item.Id})
checkGroup("update", g.Item, err, "", 4, []string{user1.Item.Id})
g, err = groupsClient.SetMembers(tc.Context(), g.Item.Id, g.Item.Version, []string{user2.Item.Id})
checkGroup("update", g.Item, err, "", 5, []string{user2.Item.Id})
g, err = groupsClient.RemoveMembers(tc.Context(), g.Item.Id, g.Item.Version, []string{user2.Item.Id})
checkGroup("update", g.Item, err, "", 6, nil)
_, err = groupsClient.Delete(tc.Context(), g.Item.Id)
require.NoError(err)
_, err = groupsClient.Delete(tc.Context(), g.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
})
}
}
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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
groupClient := groups.NewClient(client)
g, err := groupClient.Create(tc.Context(), tt.scopeId, groups.WithName("first"))
require.NoError(err)
assert.NotNil(g)
// Updating the wrong version should fail.
_, err = groupClient.Update(tc.Context(), g.Item.Id, 73, groups.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
// Create another resource with the same name.
_, err = groupClient.Create(tc.Context(), tt.scopeId, groups.WithName("first"))
require.Error(err)
_, err = groupClient.Read(tc.Context(), iam.GroupPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = groupClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, err = groupClient.Update(tc.Context(), g.Item.Id, g.Item.Version)
require.Error(err)
apiErr = api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
})
}
}
-155
View File
@@ -1,155 +0,0 @@
package hostcatalogs_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/hostcatalogs"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
catalogClient := hostcatalogs.NewClient(client)
ul, err := catalogClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.Empty(ul.Items)
var expected []*hostcatalogs.HostCatalog
for i := 0; i < 10; i++ {
expected = append(expected, &hostcatalogs.HostCatalog{Name: fmt.Sprint(i)})
}
cr, err := catalogClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName(expected[0].Name))
require.NoError(err)
expected[0] = cr.Item
ul, err = catalogClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableCatalogSlice(expected[:1]), comparableCatalogSlice(ul.Items))
for i := 1; i < 10; i++ {
cr, err = catalogClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName(expected[i].Name))
require.NoError(err)
expected[i] = cr.Item
}
ul, err = catalogClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableCatalogSlice(expected), comparableCatalogSlice(ul.Items))
}
func comparableCatalogSlice(in []*hostcatalogs.HostCatalog) []hostcatalogs.HostCatalog {
var filtered []hostcatalogs.HostCatalog
for _, i := range in {
p := hostcatalogs.HostCatalog{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
checkCatalog := func(step string, hc *hostcatalogs.HostCatalog, err error, wantedName string, wantVersion uint32) {
require.NoError(err, step)
assert.NotNil(hc, "returned no resource", step)
gotName := ""
if hc.Name != "" {
gotName = hc.Name
}
assert.Equal(wantedName, gotName, step)
assert.Equal(wantVersion, hc.Version)
}
hcClient := hostcatalogs.NewClient(client)
hc, err := hcClient.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
checkCatalog("create", hc.Item, err, "foo", 1)
hc, err = hcClient.Read(tc.Context(), hc.Item.Id)
checkCatalog("read", hc.Item, err, "foo", 1)
hc, err = hcClient.Update(tc.Context(), hc.Item.Id, hc.Item.Version, hostcatalogs.WithName("bar"))
checkCatalog("update", hc.Item, err, "bar", 2)
hc, err = hcClient.Update(tc.Context(), hc.Item.Id, hc.Item.Version, hostcatalogs.DefaultName())
checkCatalog("update", hc.Item, err, "", 3)
_, err = hcClient.Delete(tc.Context(), hc.Item.Id)
assert.NoError(err)
_, err = hcClient.Delete(tc.Context(), hc.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
pc := hostcatalogs.NewClient(client)
hc, err := pc.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
require.NoError(err)
apiErr := api.AsServerError(err)
assert.Nil(apiErr)
assert.NotNil(hc)
// Updating the wrong version should fail.
_, err = pc.Update(tc.Context(), hc.Item.Id, 73, hostcatalogs.WithName("anything"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = pc.Create(tc.Context(), "static", proj.GetPublicId(), hostcatalogs.WithName("foo"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
_, err = pc.Read(tc.Context(), static.HostCatalogPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = pc.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-168
View File
@@ -1,168 +0,0 @@
package hosts_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/hostcatalogs"
"github.com/hashicorp/boundary/api/hosts"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
hClient := hosts.NewClient(client)
ul, err := hClient.List(tc.Context(), hc.Item.Id)
assert.NoError(err)
assert.Empty(ul.Items)
var expected []*hosts.Host
for i := 0; i < 10; i++ {
expected = append(expected, &hosts.Host{Name: fmt.Sprint(i)})
}
hcr, err := hClient.Create(tc.Context(), hc.Item.Id, hosts.WithName(expected[0].Name), hosts.WithStaticHostAddress("someaddress"))
assert.NoError(err)
expected[0] = hcr.Item
ul, err = hClient.List(tc.Context(), hc.Item.Id)
assert.NoError(err)
assert.ElementsMatch(comparableHostSlice(expected[:1]), comparableHostSlice(ul.Items))
for i := 1; i < 10; i++ {
hcr, err = hClient.Create(tc.Context(), hc.Item.Id, hosts.WithName(expected[i].Name), hosts.WithStaticHostAddress("someaddress"))
assert.NoError(err)
expected[i] = hcr.Item
}
ul, err = hClient.List(tc.Context(), hc.Item.Id)
require.NoError(err)
assert.ElementsMatch(comparableHostSlice(expected), comparableHostSlice(ul.Items))
}
func comparableHostSlice(in []*hosts.Host) []hosts.Host {
var filtered []hosts.Host
for _, i := range in {
p := hosts.Host{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
checkHost := func(step string, h *hosts.Host, err error, wantedName string, wantVersion uint32) {
require.NoError(err, step)
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 := hosts.NewClient(client)
h, err := hClient.Create(tc.Context(), hc.Item.Id, hosts.WithName("foo"), hosts.WithStaticHostAddress("someaddress"))
checkHost("create", h.Item, err, "foo", 1)
h, err = hClient.Read(tc.Context(), h.Item.Id)
checkHost("read", h.Item, err, "foo", 1)
h, err = hClient.Update(tc.Context(), h.Item.Id, h.Item.Version, hosts.WithName("bar"))
checkHost("update", h.Item, err, "bar", 2)
h, err = hClient.Update(tc.Context(), h.Item.Id, h.Item.Version, hosts.DefaultName())
checkHost("update", h.Item, err, "", 3)
_, err = hClient.Delete(tc.Context(), h.Item.Id)
assert.NoError(err)
_, err = hClient.Delete(tc.Context(), h.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
hClient := hosts.NewClient(client)
h, err := hClient.Create(tc.Context(), hc.Item.Id, hosts.WithName("foo"), hosts.WithStaticHostAddress("someaddress"))
require.NoError(err)
assert.NotNil(h)
// Updating the wrong version should fail.
_, err = hClient.Update(tc.Context(), h.Item.Id, 73, hosts.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = hClient.Create(tc.Context(), hc.Item.Id, hosts.WithName("foo"), hosts.WithStaticHostAddress("someaddress"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
_, err = hClient.Read(tc.Context(), static.HostPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = hClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-207
View File
@@ -1,207 +0,0 @@
package hostsets_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/hostcatalogs"
"github.com/hashicorp/boundary/api/hosts"
"github.com/hashicorp/boundary/api/hostsets"
"github.com/hashicorp/boundary/internal/host/static"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCustom(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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
hClient := hosts.NewClient(client)
h1, err := hClient.Create(tc.Context(), hc.Item.Id, hosts.WithStaticHostAddress("someaddress"))
require.NoError(err)
h2, err := hClient.Create(tc.Context(), hc.Item.Id, hosts.WithStaticHostAddress("someaddress"))
require.NoError(err)
hSetClient := hostsets.NewClient(client)
hSet, err := hSetClient.Create(tc.Context(), hc.Item.Id)
require.NoError(err)
hSet, err = hSetClient.AddHosts(tc.Context(), hSet.Item.Id, hSet.Item.Version, []string{h1.Item.Id, h2.Item.Id})
require.NoError(err)
assert.Contains(hSet.Item.HostIds, h1.Item.Id, h2.Item.Id)
hSet, err = hSetClient.SetHosts(tc.Context(), hSet.Item.Id, hSet.Item.Version, []string{h1.Item.Id})
require.NoError(err)
assert.ElementsMatch([]string{h1.Item.Id}, hSet.Item.HostIds)
hSet, err = hSetClient.RemoveHosts(tc.Context(), hSet.Item.Id, hSet.Item.Version, []string{h1.Item.Id})
require.NoError(err)
assert.Empty(hSet.Item.HostIds)
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
hClient := hostsets.NewClient(client)
ul, err := hClient.List(tc.Context(), hc.Item.Id)
require.NoError(err)
assert.Empty(ul.Items)
var expected []*hostsets.HostSet
for i := 0; i < 10; i++ {
expected = append(expected, &hostsets.HostSet{Name: fmt.Sprint(i)})
}
hcr, err := hClient.Create(tc.Context(), hc.Item.Id, hostsets.WithName(expected[0].Name))
require.NoError(err)
expected[0] = hcr.Item
ul, err = hClient.List(tc.Context(), hc.Item.Id)
require.NoError(err)
assert.ElementsMatch(comparableSetSlice(expected[:1]), comparableSetSlice(ul.Items))
for i := 1; i < 10; i++ {
hcr, err = hClient.Create(tc.Context(), hc.Item.Id, hostsets.WithName(expected[i].Name))
require.NoError(err)
expected[i] = hcr.Item
}
ul, err = hClient.List(tc.Context(), hc.Item.Id)
require.NoError(err)
assert.ElementsMatch(comparableSetSlice(expected), comparableSetSlice(ul.Items))
}
func comparableSetSlice(in []*hostsets.HostSet) []hostsets.HostSet {
var filtered []hostsets.HostSet
for _, i := range in {
p := hostsets.HostSet{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
checkHost := func(t *testing.T, step string, h *hostsets.HostSet, err error, wantedName string, wantVersion uint32) {
t.Helper()
require.NoError(err, step)
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)
h, err := hClient.Create(tc.Context(), hc.Item.Id, hostsets.WithName("foo"))
checkHost(t, "create", h.Item, err, "foo", 1)
h, err = hClient.Read(tc.Context(), h.Item.Id)
checkHost(t, "read", h.Item, err, "foo", 1)
h, err = hClient.Update(tc.Context(), h.Item.Id, h.Item.Version, hostsets.WithName("bar"))
checkHost(t, "update", h.Item, err, "bar", 2)
h, err = hClient.Update(tc.Context(), h.Item.Id, h.Item.Version, hostsets.DefaultName())
checkHost(t, "update", h.Item, err, "", 3)
_, err = hClient.Delete(tc.Context(), h.Item.Id)
assert.NoError(err)
_, err = hClient.Delete(tc.Context(), h.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
require.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
// TODO: Get better coverage for expected errors and error formats.
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
require.NotNil(hc)
hClient := hostsets.NewClient(client)
h, err := hClient.Create(tc.Context(), hc.Item.Id, hostsets.WithName("foo"))
require.NoError(err)
assert.NotNil(h)
// Updating the wrong version should fail.
_, err = hClient.Update(tc.Context(), h.Item.Id, 73, hostsets.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
h, err = hClient.Create(tc.Context(), hc.Item.Id, hostsets.WithName("foo"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.Nil(h)
_, err = hClient.Read(tc.Context(), static.HostSetPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = hClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-11
View File
@@ -1,11 +0,0 @@
# Determine this makefile's path.
# Be sure to place this BEFORE `include` directives, if any.
THIS_FILE := $(lastword $(MAKEFILE_LIST))
export API_GEN_BASEPATH := ${GEN_BASEPATH}/api
api:
go run .
goimports -w ${API_GEN_BASEPATH}
.PHONY: api
-408
View File
@@ -1,408 +0,0 @@
package main
import (
"text/template"
"github.com/hashicorp/boundary/internal/gen/controller/api"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/accounts"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/authmethods"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/authtokens"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/groups"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/hostcatalogs"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/hosts"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/hostsets"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/roles"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/scopes"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/sessions"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/targets"
"github.com/hashicorp/boundary/internal/gen/controller/api/resources/users"
"google.golang.org/protobuf/proto"
)
type structureInfo struct {
pkg string
name string
fields []fieldInfo
}
type fieldInfo struct {
Name string
ProtoName string
FieldType string
GenerateSdkOption bool
SubtypeName string
Query bool
SkipDefault bool
}
type structInfo struct {
inProto proto.Message
outFile string
generatedStructure structureInfo
templates []*template.Template
// Subtype name for types implementing an abstract resource type. This is
// used as text to insert into With/Default function calls to separate out
// implementations of the same abstract type. This way e.g. a WithLoginName
// option turns into WithPasswordAccountLoginName which is wordy but
// unambiguous. It also switches the behavior of the functions to work on
// 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
// outputOnly indicates that we shouldn't create options for setting members
// for this struct
outputOnly bool
// versionEnabled indicates that we should build a Version handler in
// update. Some structs are embedded in others and shouldn't have version
// fields.
versionEnabled bool
// The parameters passed into the path. These should be non-pluralized resource names.
// The templates will convert '-' to '_' and append an _id to them in the SDK param
// and append an 's' to it when building the path.
// The final value should be the path name of the resource since for single resource
// operations all values are used for the function argument.
// For collection based operations the last value is ignored for generating function argument.
pathArgs []string
// typeOnCreate indicates that create will be creating a concrete
// implementation of an abstract type and thus a type field is necessary
typeOnCreate bool
// extraOptions allows specifying extra options that will be created for a
// given type, e.g. arguments only valid for one call or purpose and not
// conveyed within the item itself
extraOptions []fieldInfo
// createResponseTypes controls for which structs response types are created
createResponseTypes bool
// fieldFilter is a set of field names that will not result in generated API
// fields
fieldFilter []string
}
var inputStructs = []*structInfo{
{
inProto: &api.Error{},
outFile: "error.gen.go",
outputOnly: true,
},
{
inProto: &api.ErrorDetails{},
outFile: "error_details.gen.go",
outputOnly: true,
},
{
inProto: &api.FieldError{},
outFile: "field_error.gen.go",
outputOnly: true,
},
// Scope related resources
{
inProto: &scopes.ScopeInfo{},
outFile: "scopes/scope_info.gen.go",
outputOnly: true,
},
{
inProto: &scopes.Scope{},
outFile: "scopes/scope.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"scope"},
extraOptions: []fieldInfo{
{
Name: "SkipAdminRoleCreation",
ProtoName: "skip_admin_role_creation",
FieldType: "bool",
Query: true,
},
{
Name: "SkipDefaultRoleCreation",
ProtoName: "skip_default_role_creation",
FieldType: "bool",
Query: true,
},
},
versionEnabled: true,
createResponseTypes: true,
},
// User related resources
{
inProto: &users.Account{},
outFile: "users/account.gen.go",
outputOnly: true,
},
{
inProto: &users.User{},
outFile: "users/user.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
sliceSubTypes: map[string]string{
"Accounts": "accountIds",
},
pathArgs: []string{"user"},
versionEnabled: true,
createResponseTypes: true,
},
// Group related resources
{
inProto: &groups.Member{},
outFile: "groups/member.gen.go",
outputOnly: true,
},
{
inProto: &groups.Group{},
outFile: "groups/group.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
sliceSubTypes: map[string]string{
"Members": "memberIds",
},
pathArgs: []string{"group"},
versionEnabled: true,
createResponseTypes: true,
},
// Role related resources
{
inProto: &roles.Grant{},
outFile: "roles/grant.gen.go",
outputOnly: true,
},
{
inProto: &roles.Principal{},
outFile: "roles/principal.gen.go",
outputOnly: true,
},
{
inProto: &roles.GrantJson{},
outFile: "roles/grant_json.gen.go",
outputOnly: true,
},
{
inProto: &roles.Role{},
outFile: "roles/role.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
sliceSubTypes: map[string]string{
"Principals": "principalIds",
"Grants": "grantStrings",
},
pathArgs: []string{"role"},
versionEnabled: true,
createResponseTypes: true,
},
// Auth Methods related resources
{
inProto: &authmethods.AuthMethod{},
outFile: "authmethods/authmethods.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"auth-method"},
typeOnCreate: true,
versionEnabled: true,
createResponseTypes: true,
},
{
inProto: &authmethods.PasswordAuthMethodAttributes{},
outFile: "authmethods/password_auth_method_attributes.gen.go",
subtypeName: "PasswordAuthMethod",
},
// Accounts
{
inProto: &accounts.Account{},
outFile: "accounts/account.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"account"},
parentTypeName: "auth-method",
versionEnabled: true,
createResponseTypes: true,
},
{
inProto: &accounts.PasswordAccountAttributes{},
outFile: "accounts/password_account_attributes.gen.go",
subtypeName: "PasswordAccount",
},
// Auth Tokens
{
inProto: &authtokens.AuthToken{},
outFile: "authtokens/authtokens.gen.go",
templates: []*template.Template{
clientTemplate,
readTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"auth-token"},
createResponseTypes: true,
},
// Host related resources
{
inProto: &hostcatalogs.HostCatalog{},
outFile: "hostcatalogs/host_catalog.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"host-catalog"},
typeOnCreate: true,
versionEnabled: true,
createResponseTypes: true,
},
{
inProto: &hosts.Host{},
outFile: "hosts/host.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"host"},
parentTypeName: "host-catalog",
versionEnabled: true,
createResponseTypes: true,
},
{
inProto: &hosts.StaticHostAttributes{},
outFile: "hosts/static_host_attributes.gen.go",
subtypeName: "StaticHost",
},
{
inProto: &hostsets.HostSet{},
outFile: "hostsets/host_set.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"host-set"},
parentTypeName: "host-catalog",
sliceSubTypes: map[string]string{
"Hosts": "hostIds",
},
versionEnabled: true,
createResponseTypes: true,
},
{
inProto: &targets.HostSet{},
outFile: "targets/host_set.gen.go",
},
{
inProto: &targets.Target{},
outFile: "targets/target.gen.go",
templates: []*template.Template{
clientTemplate,
createTemplate,
readTemplate,
updateTemplate,
deleteTemplate,
listTemplate,
},
pathArgs: []string{"target"},
sliceSubTypes: map[string]string{
"HostSets": "hostSetIds",
},
extraOptions: []fieldInfo{
{
Name: "HostId",
ProtoName: "host_id",
FieldType: "string",
SkipDefault: true,
},
},
versionEnabled: true,
typeOnCreate: true,
createResponseTypes: true,
},
{
inProto: &targets.TcpTargetAttributes{},
outFile: "targets/tcp_target_attributes.gen.go",
subtypeName: "TcpTarget",
},
{
inProto: &sessions.Session{},
outFile: "sessions/session.gen.go",
templates: []*template.Template{
clientTemplate,
readTemplate,
listTemplate,
},
pathArgs: []string{"session"},
createResponseTypes: true,
fieldFilter: []string{"private_key"},
},
{
inProto: &sessions.SessionState{},
outFile: "sessions/state.gen.go",
},
{
inProto: &sessions.WorkerInfo{},
outFile: "sessions/workers.gen.go",
},
{
inProto: &targets.SessionAuthorization{},
outFile: "targets/session_authorization.gen.go",
subtypeName: "SessionAuthorization",
},
{
inProto: &targets.WorkerInfo{},
outFile: "targets/worker_info.gen.go",
subtypeName: "WorkerInfo",
},
}
-6
View File
@@ -1,6 +0,0 @@
package main
func main() {
parsePBs()
fillTemplates()
}
-116
View File
@@ -1,116 +0,0 @@
package main
import (
"fmt"
_struct "github.com/golang/protobuf/ptypes/struct"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/descriptorpb"
"google.golang.org/protobuf/types/known/timestamppb"
"google.golang.org/protobuf/types/known/wrapperspb"
"github.com/hashicorp/boundary/internal/gen/controller/protooptions"
"github.com/hashicorp/boundary/sdk/strutil"
"github.com/iancoleman/strcase"
)
func printDebug(desc protoreflect.MessageDescriptor) {
fmt.Printf("Evaluating: %q\n", desc.FullName())
fmt.Printf("Name: %q\n", strcase.ToCamel(string(desc.Name())))
fmt.Printf("ProtoName: %q\n", desc.Name())
fmt.Printf("Double Parent: %q\n", desc.FullName().Parent().Parent().Name())
fmt.Printf("Field Descriptors:\n")
for i := 0; i < desc.Fields().Len(); i++ {
fieldDesc := desc.Fields().Get(i)
fmt.Printf(" field %d: %#v\n", i, fieldDesc)
fieldDesc.Options()
}
fmt.Println()
}
func parsePBs() {
for _, in := range inputStructs {
msg := in.inProto.ProtoReflect()
desc := msg.Descriptor()
//printDebug(desc)
// Evaluate above, populate below.
in.generatedStructure.pkg = packageFromFullName(desc.FullName())
in.generatedStructure.name = string(desc.Name())
for i := 0; i < desc.Fields().Len(); i++ {
fd := desc.Fields().Get(i)
if strutil.StrListContains(in.fieldFilter, string(fd.Name())) {
continue
}
fi := fieldInfo{
Name: strcase.ToCamel(string(fd.Name())),
ProtoName: string(fd.Name()),
}
// Adjust for slices
sliceText := ""
if fd.Cardinality() == protoreflect.Repeated {
sliceText = "[]"
}
// Add generate option info
opts := fd.Options().(*descriptorpb.FieldOptions)
if proto.GetExtension(opts, protooptions.E_GenerateSdkOption).(bool) {
fi.GenerateSdkOption = true
}
switch k := fd.Kind(); k {
case protoreflect.MessageKind:
ptr, pkg, name := messageKind(fd)
if pkg != "" && pkg != in.generatedStructure.pkg {
name = fmt.Sprintf("%s.%s", pkg, name)
}
fi.FieldType = sliceText + ptr + name
case protoreflect.BytesKind:
fi.FieldType = "[]byte"
default:
fi.FieldType = sliceText + k.String()
}
in.generatedStructure.fields = append(in.generatedStructure.fields, fi)
}
//fmt.Printf("Parsed: %#v\n", in.generatedStructure)
}
}
func packageFromFullName(fullName protoreflect.FullName) string {
// Example full name: controller.api.resources.groups.v1.Group
// Crawling up the parent twice jumps back past v1.Group placing us at "groups".
pkgName := fullName.Parent().Parent().Name()
if pkgName.IsValid() {
return string(pkgName)
}
return ""
}
var (
stringValueName = (&wrapperspb.StringValue{}).ProtoReflect().Descriptor().FullName()
boolValueName = (&wrapperspb.BoolValue{}).ProtoReflect().Descriptor().FullName()
uInt32ValueName = (&wrapperspb.UInt32Value{}).ProtoReflect().Descriptor().FullName()
int32ValueName = (&wrapperspb.Int32Value{}).ProtoReflect().Descriptor().FullName()
structValueName = (&_struct.Struct{}).ProtoReflect().Descriptor().FullName()
timestampName = (&timestamppb.Timestamp{}).ProtoReflect().Descriptor().FullName()
)
func messageKind(fd protoreflect.FieldDescriptor) (ptr, pkg, name string) {
switch fd.Message().FullName() {
case stringValueName:
return "", "", "string"
case boolValueName:
return "", "", "bool"
case uInt32ValueName:
return "", "", "uint32"
case int32ValueName:
return "", "", "int32"
case structValueName:
return "", "", "map[string]interface{}"
case timestampName:
return "", "time", "Time"
default:
return "*", packageFromFullName(fd.Message().FullName()), string(fd.Message().Name())
}
}
-738
View File
@@ -1,738 +0,0 @@
package main
import (
"bytes"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"strings"
"text/template"
"github.com/iancoleman/strcase"
)
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 {
if parentTypeName != "" {
strToReplace = parentTypeName
}
} else {
strToReplace = in[len(in)-2]
}
colArg = fmt.Sprintf("%sId", strcase.ToLowerCamel(strings.ReplaceAll(strToReplace, "-", "_")))
colPath = fmt.Sprintf("%ss", in[len(in)-1])
if action != "" {
action = fmt.Sprintf(":%s", action)
}
resPath = fmt.Sprintf("fmt.Sprintf(\"%s/%%s%s\", %s)", colPath, action, resArg)
return
}
type templateInput struct {
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
CreateResponseTypes bool
}
func fillTemplates() {
optionsMap := map[string]map[string]fieldInfo{}
for _, in := range inputStructs {
outBuf := new(bytes.Buffer)
input := templateInput{
Name: in.generatedStructure.name,
Package: in.generatedStructure.pkg,
Fields: in.generatedStructure.fields,
PathArgs: in.pathArgs,
ParentTypeName: in.parentTypeName,
ExtraOptions: in.extraOptions,
VersionEnabled: in.versionEnabled,
TypeOnCreate: in.typeOnCreate,
CreateResponseTypes: in.createResponseTypes,
}
if len(in.pathArgs) > 0 {
input.CollectionFunctionArg, input.ResourceFunctionArg, input.CollectionPath, input.ResourcePath = getArgsAndPaths(in.pathArgs, in.parentTypeName, "")
}
if err := structTemplate.Execute(outBuf, input); err != nil {
fmt.Printf("error executing struct template for resource %s: %v\n", in.generatedStructure.name, err)
os.Exit(1)
}
if len(in.sliceSubTypes) > 0 {
input.SliceSubTypes = in.sliceSubTypes
in.templates = append(in.templates, sliceSubTypeTemplate)
}
for _, t := range in.templates {
if err := t.Execute(outBuf, input); err != nil {
fmt.Printf("error executing function template for resource %s: %v\n", in.generatedStructure.name, err)
os.Exit(1)
}
}
// We want to generate options per-package, not per-struct, so we
// collate them all here for writing later. The map argument of the
// package map is to prevent duplicates since we may have multiple e.g.
// Name or Description fields.
if !in.outputOnly {
pkgOptionMap := map[string]fieldInfo{}
for _, val := range input.Fields {
if val.GenerateSdkOption {
val.SubtypeName = in.subtypeName
pkgOptionMap[val.Name] = val
}
}
optionMap := optionsMap[input.Package]
if optionMap == nil {
optionMap = map[string]fieldInfo{}
}
for name, val := range pkgOptionMap {
optionMap[name] = val
}
optionsMap[input.Package] = optionMap
}
// Add in extra defined options
if len(in.extraOptions) > 0 {
optionMap := optionsMap[input.Package]
if optionMap == nil {
optionMap = map[string]fieldInfo{}
}
for _, val := range in.extraOptions {
optionMap[val.Name] = val
}
optionsMap[input.Package] = optionMap
}
outFile, err := filepath.Abs(fmt.Sprintf("%s/%s", os.Getenv("API_GEN_BASEPATH"), in.outFile))
if err != nil {
fmt.Printf("error opening file %q: %v\n", in.outFile, err)
os.Exit(1)
}
outDir := filepath.Dir(outFile)
if _, err := os.Stat(outDir); os.IsNotExist(err) {
_ = os.Mkdir(outDir, os.ModePerm)
}
if err := ioutil.WriteFile(outFile, outBuf.Bytes(), 0644); err != nil {
fmt.Printf("error writing file %q: %v\n", outFile, err)
os.Exit(1)
}
}
// Now reconstruct options per package and write them out
for pkg, options := range optionsMap {
outBuf := new(bytes.Buffer)
var fieldNames []string
for _, v := range options {
fieldNames = append(fieldNames, v.Name)
}
sort.Strings(fieldNames)
var fields []fieldInfo
for _, v := range fieldNames {
fields = append(fields, options[v])
}
input := templateInput{
Package: pkg,
Fields: fields,
}
if err := optionTemplate.Execute(outBuf, input); err != nil {
fmt.Printf("error executing option template for package %s: %v\n", pkg, err)
os.Exit(1)
}
outFile, err := filepath.Abs(fmt.Sprintf("%s/%s/%s", os.Getenv("API_GEN_BASEPATH"), pkg, "option.gen.go"))
if err != nil {
fmt.Printf("error opening file %q: %v\n", "option.gen.go", err)
os.Exit(1)
}
outDir := filepath.Dir(outFile)
if _, err := os.Stat(outDir); os.IsNotExist(err) {
_ = os.Mkdir(outDir, os.ModePerm)
}
if err := ioutil.WriteFile(outFile, outBuf.Bytes(), 0644); err != nil {
fmt.Printf("error writing file %q: %v\n", outFile, err)
os.Exit(1)
}
}
}
var listTemplate = template.Must(template.New("").Funcs(
template.FuncMap{
"snakeCase": snakeCase,
},
).Parse(`
func (c *Client) List(ctx context.Context, {{ .CollectionFunctionArg }} string, opt... Option) (*{{ .Name }}ListResult, error) {
if {{ .CollectionFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into List request")
}
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
opts.queryMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
req, err := c.client.NewRequest(ctx, "GET", "{{ .CollectionPath }}", nil, apiOpts...)
if err != nil {
return 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, fmt.Errorf("error performing client request during List call: %w", err)
}
target := new({{ .Name }}ListResult)
apiErr, err := resp.Decode(target)
if err != nil {
return nil, fmt.Errorf("error decoding List response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.responseBody = resp.Body
target.responseMap = resp.Map
return target, nil
}
`))
var readTemplate = template.Must(template.New("").Parse(`
func (c *Client) Read(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (*{{ .Name }}ReadResult, error) {
if {{ .ResourceFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Read request")
}
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
req, err := c.client.NewRequest(ctx, "GET", {{ .ResourcePath }}, nil, apiOpts...)
if err != nil {
return 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, fmt.Errorf("error performing client request during Read call: %w", err)
}
target := new({{ .Name }}ReadResult)
target.Item = new({{ .Name }})
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding Read response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.responseBody = resp.Body
target.responseMap = resp.Map
return target, nil
}
`))
var deleteTemplate = template.Must(template.New("").Parse(`
func (c *Client) Delete(ctx context.Context, {{ .ResourceFunctionArg }} string, opt... Option) (*{{ .Name }}DeleteResult, error) {
if {{ .ResourceFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Delete request")
}
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
req, err := c.client.NewRequest(ctx, "DELETE", {{ .ResourcePath }}, nil, apiOpts...)
if err != nil {
return 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 nil, fmt.Errorf("error performing client request during Delete call: %w", err)
}
apiErr, err := resp.Decode(nil)
if err != nil {
return nil, fmt.Errorf("error decoding Delete response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target := &{{ .Name }}DeleteResult{
responseBody: resp.Body,
responseMap: resp.Map,
}
return target, nil
}
`))
var createTemplate = template.Must(template.New("").Funcs(
template.FuncMap{
"snakeCase": snakeCase,
},
).Parse(`
func (c *Client) Create (ctx context.Context, {{ if .TypeOnCreate }} resourceType string, {{ end }} {{ .CollectionFunctionArg }} string, opt... Option) (*{{ .Name }}CreateResult, error) {
if {{ .CollectionFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ .CollectionFunctionArg }} value passed into Create request")
}
opts, apiOpts := getOpts(opt...)
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
{{ if .TypeOnCreate }} if resourceType == "" {
return nil, fmt.Errorf("empty resourceType value passed into Create request")
} else {
opts.postMap["type"] = resourceType
}{{ end }}
opts.postMap["{{ snakeCase .CollectionFunctionArg }}"] = {{ .CollectionFunctionArg }}
req, err := c.client.NewRequest(ctx, "POST", "{{ .CollectionPath }}", opts.postMap, apiOpts...)
if err != nil {
return nil, fmt.Errorf("error creating Create 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, fmt.Errorf("error performing client request during Create call: %w", err)
}
target := new({{ .Name }}CreateResult)
target.Item = new({{ .Name }})
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding Create response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.responseBody = resp.Body
target.responseMap = resp.Map
return target, nil
}
`))
var updateTemplate = template.Must(template.New("").Parse(`
func (c *Client) Update(ctx context.Context, {{ .ResourceFunctionArg }} string, version uint32, opt... Option) (*{{ .Name }}UpdateResult, error) {
if {{ .ResourceFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ .ResourceFunctionArg }} value passed into Update request")
}
if c.client == nil {
return nil, fmt.Errorf("nil client")
}
opts, apiOpts := getOpts(opt...)
{{ if .VersionEnabled }}
if version == 0 {
if !opts.withAutomaticVersioning {
return nil, errors.New("zero version number passed into Update request and automatic versioning not specified")
}
existingTarget, existingErr := c.Read(ctx, {{ .ResourceFunctionArg }}, opt...)
if existingErr != nil {
if api.AsServerError(existingErr) != nil {
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
}
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
if existingTarget == nil {
return nil, errors.New("nil resource response found when performing initial check-and-set read")
}
if existingTarget.Item == nil {
return nil, errors.New("nil resource found when performing initial check-and-set read")
}
version = existingTarget.Item.Version
}
{{ end }}
opts.postMap["version"] = version
req, err := c.client.NewRequest(ctx, "PATCH", {{ .ResourcePath }}, opts.postMap, apiOpts...)
if err != nil {
return 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, fmt.Errorf("error performing client request during Update call: %w", err)
}
target := new({{ .Name }}UpdateResult)
target.Item = new({{ .Name }})
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding Update response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.responseBody = resp.Body
target.responseMap = resp.Map
return target, nil
}
`))
var sliceSubTypeTemplate = template.Must(template.New("").Funcs(
template.FuncMap{
"makeSlice": makeSlice,
"snakeCase": snakeCase,
"kebabCase": kebabCase,
"getPathWithAction": getPathWithAction,
},
).Parse(`
{{ $input := . }}
{{ range $index, $op := makeSlice "Add" "Set" "Remove" }}
{{ range $key, $value := $input.SliceSubTypes }}
{{ $fullName := print $op $key }}
{{ $actionName := kebabCase $fullName }}
{{ $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 }}UpdateResult, error) {
if {{ $input.ResourceFunctionArg }} == "" {
return nil, fmt.Errorf("empty {{ $input.ResourceFunctionArg }} value passed into {{ $fullName }} request")
}
{{ if ( not ( eq $op "Set" ) ) }}if len({{ $value }}) == 0 {
return nil, errors.New("empty {{ $value }} passed into {{ $fullName }} request")
}{{ end }}
if c.client == nil {
return nil, errors.New("nil client")
}
opts, apiOpts := getOpts(opt...)
{{ if $input.VersionEnabled }}
if version == 0 {
if !opts.withAutomaticVersioning {
return nil, errors.New("zero version number passed into {{ $fullName }} request")
}
existingTarget, existingErr := c.Read(ctx, {{ $input.ResourceFunctionArg }}, opt...)
if existingErr != nil {
if api.AsServerError(existingErr) != nil {
return nil, fmt.Errorf("error from controller when performing initial check-and-set read: %w", existingErr)
}
return nil, fmt.Errorf("error performing initial check-and-set read: %w", existingErr)
}
if existingTarget == nil {
return nil, errors.New("nil resource response found when performing initial check-and-set read")
}
if existingTarget.Item == nil {
return nil, errors.New("nil resource found when performing initial check-and-set read")
}
version = existingTarget.Item.Version
}
{{ end }}
opts.postMap["version"] = version
opts.postMap["{{ snakeCase $value }}"] = {{ $value }}
req, err := c.client.NewRequest(ctx, "POST", {{ $resPath }}, opts.postMap, apiOpts...)
if err != nil {
return 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, fmt.Errorf("error performing client request during {{ $fullName }} call: %w", err)
}
target := new({{ $input.Name }}UpdateResult)
target.Item = new({{ $input.Name }})
apiErr, err := resp.Decode(target.Item)
if err != nil {
return nil, fmt.Errorf("error decoding {{ $fullName }} response: %w", err)
}
if apiErr != nil {
return nil, apiErr
}
target.responseBody = resp.Body
target.responseMap = resp.Map
return target, nil
}
{{ end }}
{{ end }}
`))
var structTemplate = template.Must(template.New("").Parse(
fmt.Sprint(`// Code generated by "make api"; DO NOT EDIT.
package {{ .Package }}
import (
"context"
"fmt"
"time"
"github.com/kr/pretty"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/scopes"
)
type {{ .Name }} struct { {{ range .Fields }}
{{ .Name }} {{ .FieldType }} `, "`json:\"{{ .ProtoName }},omitempty\"`", `{{ end }}
{{ if ( or .CreateResponseTypes ( eq .Name "Error" ) ) }}
responseBody *bytes.Buffer
responseMap map[string]interface{}
{{ end }}
}
{{ if ( or .CreateResponseTypes ( eq .Name "Error" ) ) }}
func (n {{ .Name }}) ResponseBody() *bytes.Buffer {
return n.responseBody
}
func (n {{ .Name }}) ResponseMap() map[string]interface{} {
return n.responseMap
}
{{ end }}
{{ if .CreateResponseTypes }}
type {{ .Name }}ReadResult struct {
Item *{{ .Name }}
responseBody *bytes.Buffer
responseMap map[string]interface{}
}
func (n {{ .Name }}ReadResult) GetItem() interface{} {
return n.Item
}
func (n {{ .Name }}ReadResult) GetResponseBody() *bytes.Buffer {
return n.responseBody
}
func (n {{ .Name }}ReadResult) GetResponseMap() map[string]interface{} {
return n.responseMap
}
type {{ .Name }}CreateResult = {{ .Name }}ReadResult
type {{ .Name }}UpdateResult = {{ .Name }}ReadResult
type {{ .Name }}DeleteResult struct {
responseBody *bytes.Buffer
responseMap map[string]interface{}
}
func (n {{ .Name }}DeleteResult) GetResponseBody() *bytes.Buffer {
return n.responseBody
}
func (n {{ .Name }}DeleteResult) GetResponseMap() map[string]interface{} {
return n.responseMap
}
type {{ .Name }}ListResult struct {
Items []*{{ .Name }}
responseBody *bytes.Buffer
responseMap map[string]interface{}
}
func (n {{ .Name }}ListResult) GetItems() interface{} {
return n.Items
}
func (n {{ .Name }}ListResult) GetResponseBody() *bytes.Buffer {
return n.responseBody
}
func (n {{ .Name }}ListResult) GetResponseMap() map[string]interface{} {
return n.responseMap
}
{{ end }}
`)))
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.Clone() }
}
// ApiClient returns the underlying API client
func (c *Client) ApiClient() *api.Client {
return c.client
}
`))
var optionTemplate = template.Must(template.New("").Parse(`
package {{ .Package }}
import (
"context"
"fmt"
"time"
"github.com/hashicorp/boundary/api"
)
// Option is a func that sets optional attributes for a call. This does not need
// to be used directly, but instead option arguments are built from the
// functions in this package. WithX options set a value to that given in the
// argument; DefaultX options indicate that the value should be set to its
// default. When an API call is made options are processed in ther order they
// appear in the function call, so for a given argument X, a succession of WithX
// or DefaultX calls will result in the last call taking effect.
type Option func(*options)
type options struct {
postMap map[string]interface{}
queryMap map[string]string
withAutomaticVersioning bool
}
func getDefaultOptions() options {
return options{
postMap: make(map[string]interface{}),
queryMap: make(map[string]string),
}
}
func getOpts(opt ...Option) (options, []api.Option) {
opts := getDefaultOptions()
for _, o := range opt {
o(&opts)
}
var apiOpts []api.Option
return opts, apiOpts
}
// 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(enable bool) Option {
return func(o *options) {
o.withAutomaticVersioning = enable
}
}
{{ range .Fields }}
func With{{ .SubtypeName }}{{ .Name }}(in{{ .Name }} {{ .FieldType }}) Option {
return func(o *options) { {{ if ( not ( eq .SubtypeName "" ) ) }}
raw, ok := o.postMap["attributes"]
if !ok {
raw = interface{}(map[string]interface{}{})
}
val := raw.(map[string]interface{})
val["{{ .ProtoName }}"] = in{{ .Name }}
o.postMap["attributes"] = val
{{ else if .Query }}
o.queryMap["{{ .ProtoName }}"] = fmt.Sprintf("%v", in{{ .Name }})
{{ else }}
o.postMap["{{ .ProtoName }}"] = in{{ .Name }}
{{ end }} }
}
{{ if ( not .SkipDefault ) }}
func Default{{ .SubtypeName }}{{ .Name }}() Option {
return func(o *options) { {{ if ( not ( eq .SubtypeName "" ) ) }}
raw, ok := o.postMap["attributes"]
if !ok {
raw = interface{}(map[string]interface{}{})
}
val := raw.(map[string]interface{})
val["{{ .ProtoName }}"] = nil
o.postMap["attributes"] = val
{{ else }}
o.postMap["{{ .ProtoName }}"] = nil
{{ end }} }
}
{{ end }}
{{ end }}
`))
func makeSlice(strs ...string) []string {
return strs
}
func snakeCase(in string) string {
return strcase.ToSnake(in)
}
func kebabCase(in string) string {
return strcase.ToKebab(in)
}
func getPathWithAction(resArgs []string, parentTypeName, action string) string {
_, _, _, resPath := getArgsAndPaths(resArgs, parentTypeName, action)
return resPath
}
@@ -1,28 +0,0 @@
package tests
// TODO: Reenable once we reimplement generation of As functions once static hosts lands
/*
func TestDetailTemplating(t *testing.T) {
lt := time.Now()
c := hosts.HostCatalog{
Id: "id",
CreatedTime: lt,
Attributes: map[string]interface{}{
"regions": []string{"a", "b"},
"access_key": "access",
"secret_key": "secret",
"rotate": true,
},
}
ac, err := c.AsAwsEc2HostCatalog()
assert.NoError(t, err)
assert.Equal(t, &hosts.AwsEc2HostCatalog{
HostCatalog: &c,
Regions: []string{"a", "b"},
AccessKey: api.String("access"),
SecretKey: api.String("secret"),
Rotate: api.Bool(true),
}, ac)
}
*/
-307
View File
@@ -1,307 +0,0 @@
package roles_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/groups"
"github.com/hashicorp/boundary/api/roles"
"github.com/hashicorp/boundary/api/users"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCustom(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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
user, err := users.NewClient(client).Create(tc.Context(), org.GetPublicId())
require.NoError(err)
hasPrincipal := func(role *roles.Role, principalId string) bool {
var foundInPrincipals bool
var foundInPrincipalIds bool
for _, v := range role.Principals {
if v.Id == principalId {
foundInPrincipals = true
}
}
for _, v := range role.PrincipalIds {
if v == principalId {
foundInPrincipalIds = true
}
}
return foundInPrincipals && foundInPrincipalIds
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
g, err := groups.NewClient(client).Create(tc.Context(), tt.scopeId)
require.NoError(err)
require.NotNil(g)
rc := roles.NewClient(client)
var version uint32 = 1
r, err := rc.Create(tc.Context(), tt.scopeId, roles.WithName("foo"))
require.NoError(err)
require.NotNil(r)
require.EqualValues(r.Item.Version, version)
version++
updatedRole, err := rc.AddPrincipals(tc.Context(), r.Item.Id, r.Item.Version, []string{g.Item.Id})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.True(hasPrincipal(updatedRole.Item, g.Item.Id))
version++
updatedRole, err = rc.SetPrincipals(tc.Context(), updatedRole.Item.Id, updatedRole.Item.Version, []string{user.Item.Id})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.True(hasPrincipal(updatedRole.Item, user.Item.Id))
version++
updatedRole, err = rc.RemovePrincipals(tc.Context(), updatedRole.Item.Id, updatedRole.Item.Version, []string{user.Item.Id})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.Empty(updatedRole.Item.Principals)
version++
updatedRole, err = rc.AddGrants(tc.Context(), updatedRole.Item.Id, updatedRole.Item.Version, []string{"id=*;type=*;actions=read"})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.Contains(updatedRole.Item.GrantStrings, "id=*;type=*;actions=read")
version++
updatedRole, err = rc.SetGrants(tc.Context(), updatedRole.Item.Id, updatedRole.Item.Version, []string{"id=*;type=*;actions=*"})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.Contains(updatedRole.Item.GrantStrings, "id=*;type=*;actions=*")
version++
updatedRole, err = rc.RemoveGrants(tc.Context(), updatedRole.Item.Id, updatedRole.Item.Version, []string{"id=*;type=*;actions=*"})
require.NoError(err)
assert.EqualValues(updatedRole.Item.Version, version)
assert.Empty(updatedRole.Item.Grants)
version++
})
}
}
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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
var expected []*roles.Role
roleClient := roles.NewClient(client)
p1, err := roleClient.List(tc.Context(), tt.scopeId)
require.NoError(err)
require.Len(p1.Items, 2)
expected = append(expected, p1.Items[0:2]...)
for i := 2; i < 12; i++ {
expected = append(expected, &roles.Role{Name: fmt.Sprint(i)})
}
rcr, err := roleClient.Create(tc.Context(), tt.scopeId, roles.WithName(expected[2].Name))
require.NoError(err)
expected[2] = rcr.Item
p2, err := roleClient.List(tc.Context(), tt.scopeId)
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected[0:3]), comparableSlice(p2.Items))
for i := 3; i < 12; i++ {
rcr, err = roleClient.Create(tc.Context(), tt.scopeId, roles.WithName(expected[i].Name))
assert.NoError(err)
expected[i] = rcr.Item
}
p3, err := roleClient.List(tc.Context(), tt.scopeId)
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(p3.Items))
})
}
}
func comparableSlice(in []*roles.Role) []roles.Role {
var filtered []roles.Role
for _, i := range in {
p := roles.Role{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
checkRole := func(step string, g *roles.Role, err error, wantedName string, wantedVersion uint32) {
assert.NoError(err, step)
assert.NotNil(g, "returned no resource", step)
gotName := ""
if g.Name != "" {
gotName = g.Name
}
assert.Equal(wantedName, gotName, step)
assert.EqualValues(wantedVersion, g.Version)
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
roleClient := roles.NewClient(client)
g, err := roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("foo"))
checkRole("create", g.Item, err, "foo", 1)
g, err = roleClient.Read(tc.Context(), g.Item.Id)
checkRole("read", g.Item, err, "foo", 1)
g, err = roleClient.Update(tc.Context(), g.Item.Id, g.Item.Version, roles.WithName("bar"))
checkRole("update", g.Item, err, "bar", 2)
g, err = roleClient.Update(tc.Context(), g.Item.Id, g.Item.Version, roles.DefaultName())
checkRole("update", g.Item, err, "", 3)
_, err = roleClient.Delete(tc.Context(), g.Item.Id)
require.NoError(err)
})
}
}
func TestErrors(t *testing.T) {
tc := controller.NewTestController(t, nil)
defer tc.Shutdown()
client := tc.Client()
token := tc.Token()
client.SetToken(token.Token)
org, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
cases := []struct {
name string
scopeId string
}{
{
name: "org",
scopeId: org.GetPublicId(),
},
{
name: "proj",
scopeId: proj.GetPublicId(),
},
}
for _, tt := range cases {
t.Run(tt.name, func(t *testing.T) {
assert, require := assert.New(t), require.New(t)
roleClient := roles.NewClient(client)
u, err := roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("first"))
require.NoError(err)
assert.NotNil(u)
// Updating the wrong version should fail.
_, err = roleClient.Update(tc.Context(), u.Item.Id, 73, roles.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
// Create another resource with the same name.
_, err = roleClient.Create(tc.Context(), tt.scopeId, roles.WithName("first"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
_, err = roleClient.Read(tc.Context(), iam.RolePrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = roleClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, err = roleClient.Update(tc.Context(), u.Item.Id, u.Item.Version)
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
})
}
}
-138
View File
@@ -1,138 +0,0 @@
package scopes_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/scopes"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
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()
client.SetToken(token.Token)
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
scps := scopes.NewClient(client)
pl, err := scps.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.Empty(pl.Items)
expected := make([]*scopes.Scope, 10)
for i := 0; i < 10; i++ {
scr, err := scps.Create(tc.Context(), org.GetPublicId(), scopes.WithName(fmt.Sprintf("%d", i)))
require.NoError(err)
expected[i] = scr.Item
}
pl, err = scps.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(pl.Items))
}
func comparableSlice(in []*scopes.Scope) []scopes.Scope {
var filtered []scopes.Scope
for _, i := range in {
p := scopes.Scope{
Id: i.Id,
ScopeId: i.ScopeId,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
org, _ := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
scps := scopes.NewClient(client)
checkProject := func(step string, s *scopes.Scope, err error, wantedName string, wantedVersion uint32) {
require.NoError(err, step)
assert.NotNil(s, "returned project", step)
gotName := ""
if s.Name != "" {
gotName = s.Name
}
assert.Equal(wantedName, gotName, step)
assert.Equal(wantedVersion, s.Version)
}
s, err := scps.Create(tc.Context(), org.GetPublicId(), scopes.WithName("foo"))
checkProject("create", s.Item, err, "foo", 1)
s, err = scps.Read(tc.Context(), s.Item.Id)
checkProject("read", s.Item, err, "foo", 1)
s, err = scps.Update(tc.Context(), s.Item.Id, s.Item.Version, scopes.WithName("bar"))
checkProject("update", s.Item, err, "bar", 2)
s, err = scps.Update(tc.Context(), s.Item.Id, s.Item.Version, scopes.DefaultName())
checkProject("update, unset name", s.Item, err, "", 3)
_, err = scps.Delete(tc.Context(), s.Item.Id)
require.NoError(err)
_, err = scps.Delete(tc.Context(), s.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
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()
client.SetToken(token.Token)
org, _ := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
scps := scopes.NewClient(client)
createdProj, err := scps.Create(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.NotNil(createdProj)
// Updating the wrong version should fail.
_, err = scps.Update(tc.Context(), createdProj.Item.Id, 73, scopes.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = scps.Read(tc.Context(), "p_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = scps.Read(tc.Context(), "invalid id")
assert.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-198
View File
@@ -1,198 +0,0 @@
package targets_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/hostcatalogs"
"github.com/hashicorp/boundary/api/hostsets"
"github.com/hashicorp/boundary/api/targets"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/hashicorp/boundary/internal/target"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCustom(t *testing.T) {
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.SetToken(token.Token)
hc, err := hostcatalogs.NewClient(client).Create(tc.Context(), "static", proj.GetPublicId())
require.NoError(err)
hSetClient := hostsets.NewClient(client)
hSet, err := hSetClient.Create(tc.Context(), hc.Item.Id)
require.NoError(err)
require.NotNil(hSet)
hSet2, err := hSetClient.Create(tc.Context(), hc.Item.Id)
require.NoError(err)
require.NotNil(hSet2)
tarClient := targets.NewClient(client)
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"))
require.NoError(err)
require.NotNil(tar)
assert.Empty(tar.Item.HostSetIds)
tar, err = tarClient.AddHostSets(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet.Item.Id})
require.NoError(err)
require.NotNil(tar)
assert.ElementsMatch(tar.Item.HostSetIds, []string{hSet.Item.Id})
tar, err = tarClient.SetHostSets(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet2.Item.Id})
require.NoError(err)
require.NotNil(tar)
assert.ElementsMatch(tar.Item.HostSetIds, []string{hSet2.Item.Id})
tar, err = tarClient.RemoveHostSets(tc.Context(), tar.Item.Id, tar.Item.Version, []string{hSet2.Item.Id})
require.NoError(err)
require.NotNil(tar)
assert.Empty(tar.Item.HostSetIds)
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
tarClient := targets.NewClient(client)
ul, err := tarClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.Empty(ul.Items)
var expected []*targets.Target
for i := 0; i < 10; i++ {
expected = append(expected, &targets.Target{Name: fmt.Sprint(i)})
}
tcr, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName(expected[0].Name))
require.NoError(err)
expected[0] = tcr.Item
ul, err = tarClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ul.Items))
for i := 1; i < 10; i++ {
tcr, err = tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName(expected[i].Name))
require.NoError(err)
expected[i] = tcr.Item
}
ul, err = tarClient.List(tc.Context(), proj.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul.Items))
}
func comparableSlice(in []*targets.Target) []targets.Target {
var filtered []targets.Target
for _, i := range in {
p := targets.Target{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
checkResource := func(t *testing.T, step string, h *targets.Target, err error, wantedName string, wantVersion uint32) {
t.Helper()
require.NoError(err, step)
assert.NotNil(h, "returned no resource", step)
gotName := ""
if h.Name != "" {
gotName = h.Name
}
assert.Equal(wantedName, gotName, step)
assert.Equal(wantVersion, h.Version)
}
tarClient := targets.NewClient(client)
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"))
checkResource(t, "create", tar.Item, err, "foo", 1)
tar, err = tarClient.Read(tc.Context(), tar.Item.Id)
checkResource(t, "read", tar.Item, err, "foo", 1)
tar, err = tarClient.Update(tc.Context(), tar.Item.Id, tar.Item.Version, targets.WithName("bar"))
checkResource(t, "update", tar.Item, err, "bar", 2)
_, err = tarClient.Delete(tc.Context(), tar.Item.Id)
assert.NoError(err)
_, err = tarClient.Delete(tc.Context(), tar.Item.Id)
assert.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
func TestSet_Errors(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()
client.SetToken(token.Token)
_, proj := iam.TestScopes(t, tc.IamRepo(), iam.WithUserId(token.UserId))
tarClient := targets.NewClient(client)
tar, err := tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"))
require.NoError(err)
assert.NotNil(tar)
// Updating the wrong version should fail.
_, err = tarClient.Update(tc.Context(), tar.Item.Id, 73, targets.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
tar, err = tarClient.Create(tc.Context(), "tcp", proj.GetPublicId(), targets.WithName("foo"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.Nil(tar)
_, err = tarClient.Read(tc.Context(), target.TcpTargetPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = tarClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}
-199
View File
@@ -1,199 +0,0 @@
package users_test
import (
"fmt"
"net/http"
"testing"
"github.com/hashicorp/boundary/api"
"github.com/hashicorp/boundary/api/accounts"
"github.com/hashicorp/boundary/api/users"
"github.com/hashicorp/boundary/internal/iam"
"github.com/hashicorp/boundary/internal/servers/controller"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestCustom(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()
client.SetToken(token.Token)
uClient := users.NewClient(client)
aClient := accounts.NewClient(client)
usr1, err := uClient.Create(tc.Context(), "global")
require.NoError(err)
acct1, err := aClient.Create(tc.Context(), token.AuthMethodId, accounts.WithPasswordAccountLoginName("accountname"))
require.NoError(err)
acct2, err := aClient.Create(tc.Context(), token.AuthMethodId, accounts.WithPasswordAccountLoginName("accountname2"))
require.NoError(err)
addResult, err := uClient.AddAccounts(tc.Context(), usr1.Item.Id, 0, []string{acct1.Item.Id, acct2.Item.Id}, users.WithAutomaticVersioning(true))
assert.NoError(err)
assert.ElementsMatch([]string{acct1.Item.Id, acct2.Item.Id}, addResult.Item.AccountIds)
// Add the account to the default user
_, err = uClient.AddAccounts(tc.Context(), token.UserId, 0, []string{acct1.Item.Id}, users.WithAutomaticVersioning(true))
assert.Error(err)
remResult, err := uClient.RemoveAccounts(tc.Context(), usr1.Item.Id, 0, []string{acct1.Item.Id}, users.WithAutomaticVersioning(true))
assert.NoError(err)
assert.ElementsMatch([]string{acct2.Item.Id}, remResult.Item.AccountIds)
// Cannot remove an account that isn't associated with a user.
_, err = uClient.RemoveAccounts(tc.Context(), usr1.Item.Id, 0, []string{acct1.Item.Id}, users.WithAutomaticVersioning(true))
assert.Error(err)
setResult, err := uClient.SetAccounts(tc.Context(), usr1.Item.Id, 0, []string{acct1.Item.Id, acct2.Item.Id}, users.WithAutomaticVersioning(true))
assert.NoError(err)
assert.ElementsMatch([]string{acct1.Item.Id, acct2.Item.Id}, setResult.Item.AccountIds)
}
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()
client.SetToken(token.Token)
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
userClient := users.NewClient(client)
ul, err := userClient.List(tc.Context(), org.GetPublicId())
assert.NoError(err)
assert.Empty(ul.Items)
var expected []*users.User
for i := 0; i < 10; i++ {
expected = append(expected, &users.User{Name: fmt.Sprint(i)})
}
ucr, err := userClient.Create(tc.Context(), org.GetPublicId(), users.WithName(expected[0].Name))
assert.NoError(err)
expected[0] = ucr.Item
ul, err = userClient.List(tc.Context(), org.GetPublicId())
assert.NoError(err)
assert.ElementsMatch(comparableSlice(expected[:1]), comparableSlice(ul.Items))
for i := 1; i < 10; i++ {
ucr, err = userClient.Create(tc.Context(), org.GetPublicId(), users.WithName(expected[i].Name))
assert.NoError(err)
expected[i] = ucr.Item
}
ul, err = userClient.List(tc.Context(), org.GetPublicId())
require.NoError(err)
assert.ElementsMatch(comparableSlice(expected), comparableSlice(ul.Items))
}
func comparableSlice(in []*users.User) []users.User {
var filtered []users.User
for _, i := range in {
p := users.User{
Id: i.Id,
Name: i.Name,
Description: i.Description,
CreatedTime: i.CreatedTime,
UpdatedTime: i.UpdatedTime,
}
filtered = append(filtered, p)
}
return filtered
}
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()
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, err error, wantedName string, wantedVersion uint32) {
assert.NoError(err, step)
assert.NotNil(u, "returned no resource", step)
gotName := ""
if u.Name != "" {
gotName = u.Name
}
assert.Equal(wantedName, gotName, step)
assert.EqualValues(wantedVersion, u.Version)
}
u, err := userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("foo"))
checkUser("create", u.Item, err, "foo", 1)
u, err = userClient.Read(tc.Context(), u.Item.Id)
checkUser("read", u.Item, err, "foo", 1)
u, err = userClient.Update(tc.Context(), u.Item.Id, u.Item.Version, users.WithName("bar"))
checkUser("update", u.Item, err, "bar", 2)
u, err = userClient.Update(tc.Context(), u.Item.Id, u.Item.Version, users.DefaultName())
checkUser("update", u.Item, err, "", 3)
_, err = userClient.Delete(tc.Context(), u.Item.Id)
require.NoError(err)
_, err = userClient.Delete(tc.Context(), u.Item.Id)
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
}
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()
client.SetToken(token.Token)
org := iam.TestOrg(t, tc.IamRepo(), iam.WithUserId(token.UserId))
userClient := users.NewClient(client)
u, err := userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("first"))
require.NoError(err)
assert.NotNil(u)
// Updating the wrong version should fail.
_, err = userClient.Update(tc.Context(), u.Item.Id, 73, users.WithName("anything"))
require.Error(err)
apiErr := api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
// Create another resource with the same name.
_, err = userClient.Create(tc.Context(), org.GetPublicId(), users.WithName("first"))
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
_, err = userClient.Read(tc.Context(), iam.UserPrefix+"_doesntexis")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusNotFound, apiErr.Status)
_, err = userClient.Read(tc.Context(), "invalid id")
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
_, err = userClient.Update(tc.Context(), u.Item.Id, u.Item.Version)
require.Error(err)
apiErr = api.AsServerError(err)
assert.NotNil(apiErr)
assert.EqualValues(http.StatusBadRequest, apiErr.Status)
}