Refactor static host package (#263)
* Refactor: inline tablename constants * Refactor: move functionality to new files
This commit is contained in:
1 parent
b75a6fc5e5
commit
7ac4be51c0
17 files changed
+1791
-1727
No files matched your search
@@ -1,64 +0,0 @@
|
||||
package static
|
||||
|
||||
const (
|
||||
defaultHostCatalogTableName = "static_host_catalog"
|
||||
defaultHostTableName = "static_host"
|
||||
defaultHostSetTableName = "static_host_set"
|
||||
defaultHostSetMemberTableName = "static_host_set_member"
|
||||
)
|
||||
|
||||
// TableName returns the table name for the host catalog.
|
||||
func (c *HostCatalog) TableName() string {
|
||||
if c.tableName != "" {
|
||||
return c.tableName
|
||||
}
|
||||
return defaultHostCatalogTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (c *HostCatalog) SetTableName(n string) {
|
||||
c.tableName = n
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host.
|
||||
func (h *Host) TableName() string {
|
||||
if h.tableName != "" {
|
||||
return h.tableName
|
||||
}
|
||||
return defaultHostTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (h *Host) SetTableName(n string) {
|
||||
h.tableName = n
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host set.
|
||||
func (s *HostSet) TableName() string {
|
||||
if s.tableName != "" {
|
||||
return s.tableName
|
||||
}
|
||||
return defaultHostSetTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (s *HostSet) SetTableName(n string) {
|
||||
s.tableName = n
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host set.
|
||||
func (m *HostSetMember) TableName() string {
|
||||
if m.tableName != "" {
|
||||
return m.tableName
|
||||
}
|
||||
return defaultHostSetMemberTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (m *HostSetMember) SetTableName(n string) {
|
||||
m.tableName = n
|
||||
}
|
||||
@@ -1,159 +0,0 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHostCatalog_SetTableName(t *testing.T) {
|
||||
defaultTableName := defaultHostCatalogTableName
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := allocCatalog()
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHost_SetTableName(t *testing.T) {
|
||||
defaultTableName := defaultHostTableName
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &Host{
|
||||
Host: &store.Host{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &Host{
|
||||
Host: &store.Host{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostSet_SetTableName(t *testing.T) {
|
||||
defaultTableName := defaultHostSetTableName
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &HostSet{
|
||||
HostSet: &store.HostSet{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostSet{
|
||||
HostSet: &store.HostSet{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostSetMember_SetTableName(t *testing.T) {
|
||||
defaultTableName := defaultHostSetMemberTableName
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
)
|
||||
|
||||
// A Host contains a static address.
|
||||
type Host struct {
|
||||
*store.Host
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHost creates a new in memory Host for address assigned to catalogId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHost(catalogId, address string, opt ...Option) (*Host, error) {
|
||||
if catalogId == "" {
|
||||
return nil, fmt.Errorf("new: static host: no catalog id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if address == "" {
|
||||
return nil, fmt.Errorf("new: static host: no address: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
host := &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: catalogId,
|
||||
Address: address,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host.
|
||||
func (h *Host) TableName() string {
|
||||
if h.tableName != "" {
|
||||
return h.tableName
|
||||
}
|
||||
return "static_host"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (h *Host) SetTableName(n string) {
|
||||
h.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// A HostCatalog contains static hosts and static host sets. It is owned by
|
||||
// a scope.
|
||||
type HostCatalog struct {
|
||||
*store.HostCatalog
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostCatalog creates a new in memory HostCatalog assigned to scopeId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHostCatalog(scopeId string, opt ...Option) (*HostCatalog, error) {
|
||||
if scopeId == "" {
|
||||
return nil, fmt.Errorf("new: static host catalog: no scope id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
hc := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: scopeId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return hc, nil
|
||||
}
|
||||
|
||||
func (c *HostCatalog) clone() *HostCatalog {
|
||||
cp := proto.Clone(c.HostCatalog)
|
||||
return &HostCatalog{
|
||||
HostCatalog: cp.(*store.HostCatalog),
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host catalog.
|
||||
func (c *HostCatalog) TableName() string {
|
||||
if c.tableName != "" {
|
||||
return c.tableName
|
||||
}
|
||||
return "static_host_catalog"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (c *HostCatalog) SetTableName(n string) {
|
||||
c.tableName = n
|
||||
}
|
||||
|
||||
func allocCatalog() *HostCatalog {
|
||||
fresh := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
}
|
||||
return fresh
|
||||
}
|
||||
|
||||
func newCatalogMetadata(c *HostCatalog, op oplog.OpType) oplog.Metadata {
|
||||
metadata := oplog.Metadata{
|
||||
"resource-public-id": []string{c.GetPublicId()},
|
||||
"resource-type": []string{"static host catalog"},
|
||||
"op-type": []string{op.String()},
|
||||
}
|
||||
if c.ScopeId != "" {
|
||||
metadata["scope-id"] = []string{c.ScopeId}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
@@ -0,0 +1,172 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHostCatalog_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
|
||||
type args struct {
|
||||
scopeId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *HostCatalog
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-scopeId",
|
||||
args: args{
|
||||
scopeId: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostCatalog(tt.args.scopeId, tt.args.opts...)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testCatalogs(t *testing.T, conn *gorm.DB, count int) []*HostCatalog {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
var cats []*HostCatalog
|
||||
for i := 0; i < count; i++ {
|
||||
cat, err := NewHostCatalog(prj.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.NotNil(cat)
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
cat.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), cat)
|
||||
assert.NoError(err2)
|
||||
cats = append(cats, cat)
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
func testCatalog(t *testing.T, conn *gorm.DB) *HostCatalog {
|
||||
t.Helper()
|
||||
cats := testCatalogs(t, conn, 1)
|
||||
return cats[0]
|
||||
}
|
||||
|
||||
func TestHostCatalog_SetTableName(t *testing.T) {
|
||||
defaultTableName := "static_host_catalog"
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := allocCatalog()
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
)
|
||||
|
||||
// A HostSet is a collection of hosts from the set's catalog.
|
||||
type HostSet struct {
|
||||
*store.HostSet
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostSet creates a new in memory HostSet assigned to catalogId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHostSet(catalogId string, opt ...Option) (*HostSet, error) {
|
||||
if catalogId == "" {
|
||||
return nil, fmt.Errorf("new: static host set: no catalog id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
set := &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: catalogId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return set, nil
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host set.
|
||||
func (s *HostSet) TableName() string {
|
||||
if s.tableName != "" {
|
||||
return s.tableName
|
||||
}
|
||||
return "static_host_set"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (s *HostSet) SetTableName(n string) {
|
||||
s.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
)
|
||||
|
||||
// A HostSetMember represents the membership of a host in a host set.
|
||||
type HostSetMember struct {
|
||||
*store.HostSetMember
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostSetMember creates a new in memory HostSetMember representing the
|
||||
// membership of hostId in hostSetId.
|
||||
func NewHostSetMember(hostSetId, hostId string, opt ...Option) (*HostSetMember, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, fmt.Errorf("new: static host set member: no host set id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if hostId == "" {
|
||||
return nil, fmt.Errorf("new: static host set member: no host id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
member := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{
|
||||
StaticHostSetId: hostSetId,
|
||||
StaticHostId: hostId,
|
||||
},
|
||||
}
|
||||
return member, nil
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host set.
|
||||
func (m *HostSetMember) TableName() string {
|
||||
if m.tableName != "" {
|
||||
return m.tableName
|
||||
}
|
||||
return "static_host_set_member"
|
||||
}
|
||||
|
||||
// SetTableName sets the table name. If the caller attempts to
|
||||
// set the name to "" the name will be reset to the default name.
|
||||
func (m *HostSetMember) SetTableName(n string) {
|
||||
m.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHostSetMember_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
conn.LogMode(false)
|
||||
|
||||
cats := testCatalogs(t, conn, 2)
|
||||
|
||||
blueCat := cats[0]
|
||||
blueSets := testSets(t, conn, blueCat.GetPublicId(), 2)
|
||||
blueHosts := testHosts(t, conn, blueCat.GetPublicId(), 2)
|
||||
|
||||
// TODO(mgaffney) 05/2020:
|
||||
// these will be needed when the repository code is done
|
||||
// greenCat := cats[1]
|
||||
// greenSets := testSets(t, conn, greenCat.GetPublicId(), 2)
|
||||
// greenHosts := testHosts(t, conn, greenCat.GetPublicId(), 2)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
set *HostSet
|
||||
host *Host
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid-host-in-set",
|
||||
set: blueSets[0],
|
||||
host: blueHosts[0],
|
||||
},
|
||||
// {
|
||||
// name: "invalid-diff-catalogs",
|
||||
// set: greenSets[0],
|
||||
// host: blueHosts[0],
|
||||
// wantErr: true,
|
||||
// },
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostSetMember(tt.set.PublicId, tt.host.PublicId)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostSetMember_SetTableName(t *testing.T) {
|
||||
defaultTableName := "static_host_set_member"
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,168 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHostSet_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
|
||||
conn.LogMode(false)
|
||||
type args struct {
|
||||
catalogId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *HostSet
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-catalogId",
|
||||
args: args{
|
||||
catalogId: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostSet(tt.args.catalogId, tt.args.opts...)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostSetId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testSets(t *testing.T, conn *gorm.DB, catalogId string, count int) []*HostSet {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
var sets []*HostSet
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
set, err := NewHostSet(catalogId)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(set)
|
||||
id, err := newHostSetId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
set.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), set)
|
||||
assert.NoError(err2)
|
||||
sets = append(sets, set)
|
||||
}
|
||||
return sets
|
||||
}
|
||||
|
||||
func TestHostSet_SetTableName(t *testing.T) {
|
||||
defaultTableName := "static_host_set"
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &HostSet{
|
||||
HostSet: &store.HostSet{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &HostSet{
|
||||
HostSet: &store.HostSet{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
func TestHost_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
|
||||
conn.LogMode(false)
|
||||
type args struct {
|
||||
catalogId string
|
||||
address string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *Host
|
||||
wantCreateErr bool
|
||||
wantWriteErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-catalogId",
|
||||
args: args{
|
||||
catalogId: "",
|
||||
address: "127.0.0.1",
|
||||
},
|
||||
want: nil,
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-address",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "",
|
||||
},
|
||||
want: nil,
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "address-to-short",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "1234567",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "1234567",
|
||||
},
|
||||
},
|
||||
wantWriteErr: true,
|
||||
},
|
||||
{
|
||||
name: "minimum-address",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "12345678",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "12345678",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHost(tt.args.catalogId, tt.args.address, tt.args.opts...)
|
||||
if tt.wantCreateErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
if tt.wantWriteErr {
|
||||
assert.Error(err2)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testHosts(t *testing.T, conn *gorm.DB, catalogId string, count int) []*Host {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
var hosts []*Host
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
host, err := NewHost(catalogId, fmt.Sprintf("%s-%d", catalogId, i))
|
||||
assert.NoError(err)
|
||||
assert.NotNil(host)
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
host.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), host)
|
||||
assert.NoError(err2)
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
|
||||
func TestHost_SetTableName(t *testing.T) {
|
||||
defaultTableName := "static_host"
|
||||
tests := []struct {
|
||||
name string
|
||||
initialName string
|
||||
setNameTo string
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "new-name",
|
||||
initialName: "",
|
||||
setNameTo: "new-name",
|
||||
want: "new-name",
|
||||
},
|
||||
{
|
||||
name: "reset to default",
|
||||
initialName: "initial",
|
||||
setNameTo: "",
|
||||
want: defaultTableName,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
def := &Host{
|
||||
Host: &store.Host{},
|
||||
}
|
||||
require.Equal(defaultTableName, def.TableName())
|
||||
s := &Host{
|
||||
Host: &store.Host{},
|
||||
tableName: tt.initialName,
|
||||
}
|
||||
s.SetTableName(tt.setNameTo)
|
||||
assert.Equal(tt.want, s.TableName())
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
)
|
||||
|
||||
// PublicId prefixes for the resources in the static package.
|
||||
const (
|
||||
HostCatalogPrefix = "sthc"
|
||||
HostSetPrefix = "sths"
|
||||
HostPrefix = "sth"
|
||||
)
|
||||
|
||||
func newHostCatalogId() (string, error) {
|
||||
id, err := db.NewPublicId(HostCatalogPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host catalog id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
func newHostId() (string, error) {
|
||||
id, err := db.NewPublicId(HostPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
func newHostSetId() (string, error) {
|
||||
id, err := db.NewPublicId(HostSetPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host set id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
@@ -1,15 +1,11 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
)
|
||||
|
||||
// A Repository stores and retrieves the persistent types in the static
|
||||
@@ -39,216 +35,3 @@ func NewRepository(r db.Reader, w db.Writer, wrapper wrapping.Wrapper) (*Reposit
|
||||
wrapper: wrapper,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CreateCatalog inserts c into the repository and returns a new
|
||||
// HostCatalog containing the catalog's PublicId. c is not changed. c must
|
||||
// contain a valid ScopeID. c must not contain a PublicId. The PublicId is
|
||||
// generated and assigned by the this method. opt is ignored.
|
||||
//
|
||||
// Both c.Name and c.Description are optional. If c.Name is set, it must be
|
||||
// unique within c.ScopeID.
|
||||
//
|
||||
// Both c.CreateTime and c.UpdateTime are ignored.
|
||||
func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, opt ...Option) (*HostCatalog, error) {
|
||||
if c == nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.HostCatalog == nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: embedded HostCatalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.ScopeId == "" {
|
||||
return nil, fmt.Errorf("create: static host catalog: no scope id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if c.PublicId != "" {
|
||||
return nil, fmt.Errorf("create: static host catalog: public id not empty: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
c = c.clone()
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: %w", err)
|
||||
}
|
||||
c.PublicId = id
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_CREATE)
|
||||
|
||||
var newHostCatalog *HostCatalog
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
newHostCatalog = c.clone()
|
||||
return w.Create(
|
||||
ctx,
|
||||
newHostCatalog,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if db.IsUniqueError(err) {
|
||||
return nil, fmt.Errorf("create: static host catalog: in scope: %s: name %s already exists: %w",
|
||||
c.ScopeId, c.Name, db.ErrNotUnique)
|
||||
}
|
||||
return nil, fmt.Errorf("create: static host catalog: in scope: %s: %w", c.ScopeId, err)
|
||||
}
|
||||
return newHostCatalog, nil
|
||||
}
|
||||
|
||||
// UpdateCatalog updates the repository entry for c.PublicId with the
|
||||
// values in c for the fields listed in fieldMask. It returns a new
|
||||
// HostCatalog containing the updated values and a count of the number of
|
||||
// records updated. c is not changed.
|
||||
//
|
||||
// c must contain a valid PublicId. Only c.Name and c.Description can be
|
||||
// updated. If c.Name is set to a non-empty string, it must be unique
|
||||
// within c.ScopeID.
|
||||
//
|
||||
// An attribute of c will be set to NULL in the database if the attribute
|
||||
// in c is the zero value and it is included in fieldMask.
|
||||
func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version uint32, fieldMask []string, opt ...Option) (*HostCatalog, int, error) {
|
||||
if c == nil {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.HostCatalog == nil {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: embedded HostCatalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.PublicId == "" {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if len(fieldMask) == 0 {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %w", db.ErrEmptyFieldMask)
|
||||
}
|
||||
|
||||
var dbMask, nullFields []string
|
||||
for _, f := range fieldMask {
|
||||
switch {
|
||||
case strings.EqualFold("name", f) && c.Name == "":
|
||||
nullFields = append(nullFields, "name")
|
||||
case strings.EqualFold("name", f) && c.Name != "":
|
||||
dbMask = append(dbMask, "name")
|
||||
case strings.EqualFold("description", f) && c.Description == "":
|
||||
nullFields = append(nullFields, "description")
|
||||
case strings.EqualFold("description", f) && c.Description != "":
|
||||
dbMask = append(dbMask, "description")
|
||||
|
||||
default:
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: field: %s: %w", f, db.ErrInvalidFieldMask)
|
||||
}
|
||||
}
|
||||
c = c.clone()
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_UPDATE)
|
||||
|
||||
var rowsUpdated int
|
||||
var returnedCatalog *HostCatalog
|
||||
_, err := r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
returnedCatalog = c.clone()
|
||||
var err error
|
||||
rowsUpdated, err = w.Update(
|
||||
ctx,
|
||||
returnedCatalog,
|
||||
dbMask,
|
||||
nullFields,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
db.WithVersion(&version),
|
||||
)
|
||||
if err == nil && rowsUpdated > 1 {
|
||||
return db.ErrMultipleRecords
|
||||
}
|
||||
return err
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if db.IsUniqueError(err) {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %s: name %s already exists: %w",
|
||||
c.PublicId, c.Name, db.ErrNotUnique)
|
||||
}
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %s: %w", c.PublicId, err)
|
||||
}
|
||||
|
||||
return returnedCatalog, rowsUpdated, nil
|
||||
}
|
||||
|
||||
// LookupCatalog returns the HostCatalog for id. Returns nil, nil if no
|
||||
// HostCatalog is found for id.
|
||||
func (r *Repository) LookupCatalog(ctx context.Context, id string, opt ...Option) (*HostCatalog, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("lookup: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
c := allocCatalog()
|
||||
c.PublicId = id
|
||||
if err := r.reader.LookupByPublicId(ctx, c); err != nil {
|
||||
if err == db.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("lookup: static host catalog: %s: %w", id, err)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// DeleteCatalog deletes id from the repository returning a count of the
|
||||
// number of records deleted.
|
||||
func (r *Repository) DeleteCatalog(ctx context.Context, id string, opt ...Option) (int, error) {
|
||||
if id == "" {
|
||||
return db.NoRowsAffected, fmt.Errorf("delete: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
c := allocCatalog()
|
||||
c.PublicId = id
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_DELETE)
|
||||
|
||||
var rowsDeleted int
|
||||
var deleteCatalog *HostCatalog
|
||||
_, err := r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
deleteCatalog = c.clone()
|
||||
var err error
|
||||
rowsDeleted, err = w.Delete(
|
||||
ctx,
|
||||
deleteCatalog,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
)
|
||||
if err == nil && rowsDeleted > 1 {
|
||||
return db.ErrMultipleRecords
|
||||
}
|
||||
return err
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, fmt.Errorf("delete: static host catalog: %s: %w", c.PublicId, err)
|
||||
}
|
||||
|
||||
return rowsDeleted, nil
|
||||
}
|
||||
|
||||
func allocCatalog() *HostCatalog {
|
||||
fresh := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
}
|
||||
return fresh
|
||||
}
|
||||
|
||||
func newCatalogMetadata(c *HostCatalog, op oplog.OpType) oplog.Metadata {
|
||||
metadata := oplog.Metadata{
|
||||
"resource-public-id": []string{c.GetPublicId()},
|
||||
"resource-type": []string{"static host catalog"},
|
||||
"op-type": []string{op.String()},
|
||||
}
|
||||
if c.ScopeId != "" {
|
||||
metadata["scope-id"] = []string{c.ScopeId}
|
||||
}
|
||||
return metadata
|
||||
}
|
||||
@@ -0,0 +1,204 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
)
|
||||
|
||||
// CreateCatalog inserts c into the repository and returns a new
|
||||
// HostCatalog containing the catalog's PublicId. c is not changed. c must
|
||||
// contain a valid ScopeID. c must not contain a PublicId. The PublicId is
|
||||
// generated and assigned by the this method. opt is ignored.
|
||||
//
|
||||
// Both c.Name and c.Description are optional. If c.Name is set, it must be
|
||||
// unique within c.ScopeID.
|
||||
//
|
||||
// Both c.CreateTime and c.UpdateTime are ignored.
|
||||
func (r *Repository) CreateCatalog(ctx context.Context, c *HostCatalog, opt ...Option) (*HostCatalog, error) {
|
||||
if c == nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.HostCatalog == nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: embedded HostCatalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.ScopeId == "" {
|
||||
return nil, fmt.Errorf("create: static host catalog: no scope id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if c.PublicId != "" {
|
||||
return nil, fmt.Errorf("create: static host catalog: public id not empty: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
c = c.clone()
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("create: static host catalog: %w", err)
|
||||
}
|
||||
c.PublicId = id
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_CREATE)
|
||||
|
||||
var newHostCatalog *HostCatalog
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
newHostCatalog = c.clone()
|
||||
return w.Create(
|
||||
ctx,
|
||||
newHostCatalog,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if db.IsUniqueError(err) {
|
||||
return nil, fmt.Errorf("create: static host catalog: in scope: %s: name %s already exists: %w",
|
||||
c.ScopeId, c.Name, db.ErrNotUnique)
|
||||
}
|
||||
return nil, fmt.Errorf("create: static host catalog: in scope: %s: %w", c.ScopeId, err)
|
||||
}
|
||||
return newHostCatalog, nil
|
||||
}
|
||||
|
||||
// UpdateCatalog updates the repository entry for c.PublicId with the
|
||||
// values in c for the fields listed in fieldMask. It returns a new
|
||||
// HostCatalog containing the updated values and a count of the number of
|
||||
// records updated. c is not changed.
|
||||
//
|
||||
// c must contain a valid PublicId. Only c.Name and c.Description can be
|
||||
// updated. If c.Name is set to a non-empty string, it must be unique
|
||||
// within c.ScopeID.
|
||||
//
|
||||
// An attribute of c will be set to NULL in the database if the attribute
|
||||
// in c is the zero value and it is included in fieldMask.
|
||||
func (r *Repository) UpdateCatalog(ctx context.Context, c *HostCatalog, version uint32, fieldMask []string, opt ...Option) (*HostCatalog, int, error) {
|
||||
if c == nil {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.HostCatalog == nil {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: embedded HostCatalog: %w", db.ErrNilParameter)
|
||||
}
|
||||
if c.PublicId == "" {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if len(fieldMask) == 0 {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %w", db.ErrEmptyFieldMask)
|
||||
}
|
||||
|
||||
var dbMask, nullFields []string
|
||||
for _, f := range fieldMask {
|
||||
switch {
|
||||
case strings.EqualFold("name", f) && c.Name == "":
|
||||
nullFields = append(nullFields, "name")
|
||||
case strings.EqualFold("name", f) && c.Name != "":
|
||||
dbMask = append(dbMask, "name")
|
||||
case strings.EqualFold("description", f) && c.Description == "":
|
||||
nullFields = append(nullFields, "description")
|
||||
case strings.EqualFold("description", f) && c.Description != "":
|
||||
dbMask = append(dbMask, "description")
|
||||
|
||||
default:
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: field: %s: %w", f, db.ErrInvalidFieldMask)
|
||||
}
|
||||
}
|
||||
c = c.clone()
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_UPDATE)
|
||||
|
||||
var rowsUpdated int
|
||||
var returnedCatalog *HostCatalog
|
||||
_, err := r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
returnedCatalog = c.clone()
|
||||
var err error
|
||||
rowsUpdated, err = w.Update(
|
||||
ctx,
|
||||
returnedCatalog,
|
||||
dbMask,
|
||||
nullFields,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
db.WithVersion(&version),
|
||||
)
|
||||
if err == nil && rowsUpdated > 1 {
|
||||
return db.ErrMultipleRecords
|
||||
}
|
||||
return err
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if db.IsUniqueError(err) {
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %s: name %s already exists: %w",
|
||||
c.PublicId, c.Name, db.ErrNotUnique)
|
||||
}
|
||||
return nil, db.NoRowsAffected, fmt.Errorf("update: static host catalog: %s: %w", c.PublicId, err)
|
||||
}
|
||||
|
||||
return returnedCatalog, rowsUpdated, nil
|
||||
}
|
||||
|
||||
// LookupCatalog returns the HostCatalog for id. Returns nil, nil if no
|
||||
// HostCatalog is found for id.
|
||||
func (r *Repository) LookupCatalog(ctx context.Context, id string, opt ...Option) (*HostCatalog, error) {
|
||||
if id == "" {
|
||||
return nil, fmt.Errorf("lookup: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
c := allocCatalog()
|
||||
c.PublicId = id
|
||||
if err := r.reader.LookupByPublicId(ctx, c); err != nil {
|
||||
if err == db.ErrRecordNotFound {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, fmt.Errorf("lookup: static host catalog: %s: %w", id, err)
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// DeleteCatalog deletes id from the repository returning a count of the
|
||||
// number of records deleted.
|
||||
func (r *Repository) DeleteCatalog(ctx context.Context, id string, opt ...Option) (int, error) {
|
||||
if id == "" {
|
||||
return db.NoRowsAffected, fmt.Errorf("delete: static host catalog: missing public id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
c := allocCatalog()
|
||||
c.PublicId = id
|
||||
|
||||
metadata := newCatalogMetadata(c, oplog.OpType_OP_TYPE_DELETE)
|
||||
|
||||
var rowsDeleted int
|
||||
var deleteCatalog *HostCatalog
|
||||
_, err := r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(_ db.Reader, w db.Writer) error {
|
||||
deleteCatalog = c.clone()
|
||||
var err error
|
||||
rowsDeleted, err = w.Delete(
|
||||
ctx,
|
||||
deleteCatalog,
|
||||
db.WithOplog(r.wrapper, metadata),
|
||||
)
|
||||
if err == nil && rowsDeleted > 1 {
|
||||
return db.ErrMultipleRecords
|
||||
}
|
||||
return err
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return db.NoRowsAffected, fmt.Errorf("delete: static host catalog: %s: %w", c.PublicId, err)
|
||||
}
|
||||
|
||||
return rowsDeleted, nil
|
||||
}
|
||||
@@ -0,0 +1,670 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
dbassert "github.com/hashicorp/boundary/internal/db/assert"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_CreateCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
in *HostCatalog
|
||||
opts []Option
|
||||
want *HostCatalog
|
||||
wantIsErr error
|
||||
}{
|
||||
{
|
||||
name: "nil-catalog",
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-catalog",
|
||||
in: &HostCatalog{},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: ("test-description-repo"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: ("test-description-repo"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
if tt.in != nil && tt.in.HostCatalog != nil {
|
||||
tt.in.ScopeId = prj.GetPublicId()
|
||||
assert.Empty(tt.in.PublicId)
|
||||
}
|
||||
got, err := repo.CreateCatalog(context.Background(), tt.in, tt.opts...)
|
||||
if tt.wantIsErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantIsErr), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.in.PublicId)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(tt.in, got)
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("invalid-duplicate-names", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
got2, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.Truef(errors.Is(err, db.ErrNotUnique), "want err: %v got: %v", db.ErrNotUnique, err)
|
||||
assert.Nil(got2)
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-scopes", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
in2 := in.clone()
|
||||
|
||||
in.ScopeId = prj.GetPublicId()
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
in2.ScopeId = org.GetPublicId()
|
||||
got2, err := repo.CreateCatalog(context.Background(), in2)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got2)
|
||||
assertPublicId(t, "sthc", got2.PublicId)
|
||||
assert.NotSame(in2, got2)
|
||||
assert.Equal(in2.Name, got2.Name)
|
||||
assert.Equal(in2.Description, got2.Description)
|
||||
assert.Equal(got2.CreateTime, got2.UpdateTime)
|
||||
})
|
||||
}
|
||||
|
||||
func assertPublicId(t *testing.T, prefix, actual string) {
|
||||
t.Helper()
|
||||
assert.NotEmpty(t, actual)
|
||||
parts := strings.Split(actual, "_")
|
||||
assert.Equalf(t, 2, len(parts), "want one '_' in PublicId, got multiple in %q", actual)
|
||||
assert.Equalf(t, prefix, parts[0], "PublicId want prefix: %q, got: %q in %q", prefix, parts[0], actual)
|
||||
}
|
||||
|
||||
func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
changeName := func(s string) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.Name = s
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
changeDescription := func(s string) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.Description = s
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
makeNil := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
makeEmbeddedNil := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
return &HostCatalog{}
|
||||
}
|
||||
}
|
||||
|
||||
deletePublicId := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.PublicId = ""
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
nonExistentPublicId := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.PublicId = "sthc_OOOOOOOOOO"
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
combine := func(fns ...func(c *HostCatalog) *HostCatalog) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
for _, fn := range fns {
|
||||
c = fn(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
orig *HostCatalog
|
||||
chgFn func(*HostCatalog) *HostCatalog
|
||||
masks []string
|
||||
want *HostCatalog
|
||||
wantCount int
|
||||
wantIsErr error
|
||||
}{
|
||||
{
|
||||
name: "nil-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: makeNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: makeEmbeddedNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "no-public-id",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: deletePublicId(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrInvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "updating-non-existent-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(nonExistentPublicId(), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name"},
|
||||
wantIsErr: db.ErrRecordNotFound,
|
||||
},
|
||||
{
|
||||
name: "empty-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
wantIsErr: db.ErrEmptyFieldMask,
|
||||
},
|
||||
{
|
||||
name: "read-only-fields-in-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"PublicId", "CreateTime", "UpdateTime", "ScopeId"},
|
||||
wantIsErr: db.ErrInvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "unknown-field-in-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Bilbo"},
|
||||
wantIsErr: db.ErrInvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "change-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Name"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeDescription("test-update-description-repo"),
|
||||
masks: []string{"Description"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-name-and-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name", "Description"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
tt.orig.ScopeId = prj.GetPublicId()
|
||||
orig, err := repo.CreateCatalog(context.Background(), tt.orig)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, orig)
|
||||
|
||||
if tt.chgFn != nil {
|
||||
orig = tt.chgFn(orig)
|
||||
}
|
||||
got, gotCount, err := repo.UpdateCatalog(context.Background(), orig, 1, tt.masks)
|
||||
if tt.wantIsErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantIsErr), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.orig.PublicId)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.NotSame(tt.orig, got)
|
||||
assert.Equal(tt.orig.ScopeId, got.ScopeId)
|
||||
dbassert := dbassert.New(t, rw)
|
||||
if tt.want.Name == "" {
|
||||
dbassert.IsNull(got, "name")
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
if tt.want.Description == "" {
|
||||
dbassert.IsNull(got, "description")
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("invalid-duplicate-names", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
name := "test-dup-name"
|
||||
cats := testCatalogs(t, conn, 2)
|
||||
c1 := cats[0]
|
||||
c1.Name = name
|
||||
got1, gotCount1, err := repo.UpdateCatalog(context.Background(), c1, 1, []string{"name"})
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got1)
|
||||
assert.Equal(name, got1.Name)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
|
||||
c2 := cats[1]
|
||||
c2.Name = name
|
||||
got2, gotCount2, err := repo.UpdateCatalog(context.Background(), c2, 1, []string{"name"})
|
||||
assert.Truef(errors.Is(err, db.ErrNotUnique), "want err: %v got: %v", db.ErrNotUnique, err)
|
||||
assert.Nil(got2)
|
||||
assert.Equal(db.NoRowsAffected, gotCount2, "row count")
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-scopes", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
in2 := in.clone()
|
||||
|
||||
in.ScopeId = prj.GetPublicId()
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
|
||||
in2.ScopeId = org.GetPublicId()
|
||||
in2.Name = "first-name"
|
||||
got2, err := repo.CreateCatalog(context.Background(), in2)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got2)
|
||||
got2.Name = got.Name
|
||||
got3, gotCount3, err := repo.UpdateCatalog(context.Background(), got2, 1, []string{"name"})
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got3)
|
||||
assert.NotSame(got2, got3)
|
||||
assert.Equal(got.Name, got3.Name)
|
||||
assert.Equal(got2.Description, got3.Description)
|
||||
assert.Equal(1, gotCount3, "row count")
|
||||
})
|
||||
|
||||
t.Run("change-scope-id", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
c1, c2 := testCatalog(t, conn), testCatalog(t, conn)
|
||||
assert.NotEqual(c1.ScopeId, c2.ScopeId)
|
||||
orig := c1.clone()
|
||||
|
||||
c1.ScopeId = c2.ScopeId
|
||||
assert.Equal(c1.ScopeId, c2.ScopeId)
|
||||
|
||||
got1, gotCount1, err := repo.UpdateCatalog(context.Background(), c1, 1, []string{"name"})
|
||||
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got1)
|
||||
assert.Equal(orig.ScopeId, got1.ScopeId)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepository_LookupCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
badId, err := newHostCatalogId()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, badId)
|
||||
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
id string
|
||||
want *HostCatalog
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "found",
|
||||
id: cat.GetPublicId(),
|
||||
want: cat,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: badId,
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "bad-public-id",
|
||||
id: "",
|
||||
want: nil,
|
||||
wantErr: db.ErrInvalidParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
got, err := repo.LookupCatalog(context.Background(), tt.id)
|
||||
if tt.wantErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantErr), "want err: %q got: %q", tt.wantErr, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
|
||||
switch {
|
||||
case tt.want == nil:
|
||||
assert.Nil(got)
|
||||
case tt.want != nil:
|
||||
assert.NotNil(got)
|
||||
assert.Equal(got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_DeleteCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
badId, err := newHostCatalogId()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, badId)
|
||||
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
id string
|
||||
want int
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "found",
|
||||
id: cat.GetPublicId(),
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: badId,
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "bad-public-id",
|
||||
id: "",
|
||||
want: 0,
|
||||
wantErr: db.ErrInvalidParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
got, err := repo.DeleteCatalog(context.Background(), tt.id)
|
||||
if tt.wantErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantErr), "want err: %q got: %q", tt.wantErr, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.want, got, "row count")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,20 +1,13 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
wrapping "github.com/hashicorp/go-kms-wrapping"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
dbassert "github.com/hashicorp/boundary/internal/db/assert"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
)
|
||||
|
||||
func TestRepository_New(t *testing.T) {
|
||||
@@ -104,658 +97,3 @@ func TestRepository_New(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_CreateCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
in *HostCatalog
|
||||
opts []Option
|
||||
want *HostCatalog
|
||||
wantIsErr error
|
||||
}{
|
||||
{
|
||||
name: "nil-catalog",
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-catalog",
|
||||
in: &HostCatalog{},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
in: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: ("test-description-repo"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: ("test-description-repo"),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
if tt.in != nil && tt.in.HostCatalog != nil {
|
||||
tt.in.ScopeId = prj.GetPublicId()
|
||||
assert.Empty(tt.in.PublicId)
|
||||
}
|
||||
got, err := repo.CreateCatalog(context.Background(), tt.in, tt.opts...)
|
||||
if tt.wantIsErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantIsErr), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.in.PublicId)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(tt.in, got)
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("invalid-duplicate-names", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
got2, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.Truef(errors.Is(err, db.ErrNotUnique), "want err: %v got: %v", db.ErrNotUnique, err)
|
||||
assert.Nil(got2)
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-scopes", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
in2 := in.clone()
|
||||
|
||||
in.ScopeId = prj.GetPublicId()
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
assert.Equal(got.CreateTime, got.UpdateTime)
|
||||
|
||||
in2.ScopeId = org.GetPublicId()
|
||||
got2, err := repo.CreateCatalog(context.Background(), in2)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got2)
|
||||
assertPublicId(t, "sthc", got2.PublicId)
|
||||
assert.NotSame(in2, got2)
|
||||
assert.Equal(in2.Name, got2.Name)
|
||||
assert.Equal(in2.Description, got2.Description)
|
||||
assert.Equal(got2.CreateTime, got2.UpdateTime)
|
||||
})
|
||||
}
|
||||
|
||||
func assertPublicId(t *testing.T, prefix, actual string) {
|
||||
t.Helper()
|
||||
assert.NotEmpty(t, actual)
|
||||
parts := strings.Split(actual, "_")
|
||||
assert.Equalf(t, 2, len(parts), "want one '_' in PublicId, got multiple in %q", actual)
|
||||
assert.Equalf(t, prefix, parts[0], "PublicId want prefix: %q, got: %q in %q", prefix, parts[0], actual)
|
||||
}
|
||||
|
||||
func TestRepository_UpdateCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
changeName := func(s string) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.Name = s
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
changeDescription := func(s string) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.Description = s
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
makeNil := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
makeEmbeddedNil := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
return &HostCatalog{}
|
||||
}
|
||||
}
|
||||
|
||||
deletePublicId := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.PublicId = ""
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
nonExistentPublicId := func() func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
c.PublicId = "sthc_OOOOOOOOOO"
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
combine := func(fns ...func(c *HostCatalog) *HostCatalog) func(*HostCatalog) *HostCatalog {
|
||||
return func(c *HostCatalog) *HostCatalog {
|
||||
for _, fn := range fns {
|
||||
c = fn(c)
|
||||
}
|
||||
return c
|
||||
}
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
orig *HostCatalog
|
||||
chgFn func(*HostCatalog) *HostCatalog
|
||||
masks []string
|
||||
want *HostCatalog
|
||||
wantCount int
|
||||
wantIsErr error
|
||||
}{
|
||||
{
|
||||
name: "nil-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: makeNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-embedded-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: makeEmbeddedNil(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrNilParameter,
|
||||
},
|
||||
{
|
||||
name: "no-public-id",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{},
|
||||
},
|
||||
chgFn: deletePublicId(),
|
||||
masks: []string{"Name", "Description"},
|
||||
wantIsErr: db.ErrInvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "updating-non-existent-catalog",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(nonExistentPublicId(), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name"},
|
||||
wantIsErr: db.ErrRecordNotFound,
|
||||
},
|
||||
{
|
||||
name: "empty-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
wantIsErr: db.ErrEmptyFieldMask,
|
||||
},
|
||||
{
|
||||
name: "read-only-fields-in-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"PublicId", "CreateTime", "UpdateTime", "ScopeId"},
|
||||
wantIsErr: db.ErrInvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "unknown-field-in-field-mask",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Bilbo"},
|
||||
wantIsErr: db.ErrInvalidFieldMask,
|
||||
},
|
||||
{
|
||||
name: "change-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeName("test-update-name-repo"),
|
||||
masks: []string{"Name"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: changeDescription("test-update-description-repo"),
|
||||
masks: []string{"Description"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "change-name-and-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("test-update-name-repo")),
|
||||
masks: []string{"Name", "Description"},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "delete-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-name",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Description"},
|
||||
chgFn: combine(changeDescription("test-update-description-repo"), changeName("")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-update-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
{
|
||||
name: "do-not-delete-description",
|
||||
orig: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
masks: []string{"Name"},
|
||||
chgFn: combine(changeDescription(""), changeName("test-update-name-repo")),
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-update-name-repo",
|
||||
Description: "test-description-repo",
|
||||
},
|
||||
},
|
||||
wantCount: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
tt.orig.ScopeId = prj.GetPublicId()
|
||||
orig, err := repo.CreateCatalog(context.Background(), tt.orig)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, orig)
|
||||
|
||||
if tt.chgFn != nil {
|
||||
orig = tt.chgFn(orig)
|
||||
}
|
||||
got, gotCount, err := repo.UpdateCatalog(context.Background(), orig, 1, tt.masks)
|
||||
if tt.wantIsErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantIsErr), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Empty(tt.orig.PublicId)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.Equal(tt.wantCount, gotCount, "row count")
|
||||
assert.NotSame(tt.orig, got)
|
||||
assert.Equal(tt.orig.ScopeId, got.ScopeId)
|
||||
dbassert := dbassert.New(t, rw)
|
||||
if tt.want.Name == "" {
|
||||
dbassert.IsNull(got, "name")
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want.Name, got.Name)
|
||||
if tt.want.Description == "" {
|
||||
dbassert.IsNull(got, "description")
|
||||
return
|
||||
}
|
||||
assert.Equal(tt.want.Description, got.Description)
|
||||
})
|
||||
}
|
||||
|
||||
t.Run("invalid-duplicate-names", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
name := "test-dup-name"
|
||||
cats := testCatalogs(t, conn, 2)
|
||||
c1 := cats[0]
|
||||
c1.Name = name
|
||||
got1, gotCount1, err := repo.UpdateCatalog(context.Background(), c1, 1, []string{"name"})
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got1)
|
||||
assert.Equal(name, got1.Name)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
|
||||
c2 := cats[1]
|
||||
c2.Name = name
|
||||
got2, gotCount2, err := repo.UpdateCatalog(context.Background(), c2, 1, []string{"name"})
|
||||
assert.Truef(errors.Is(err, db.ErrNotUnique), "want err: %v got: %v", db.ErrNotUnique, err)
|
||||
assert.Nil(got2)
|
||||
assert.Equal(db.NoRowsAffected, gotCount2, "row count")
|
||||
})
|
||||
|
||||
t.Run("valid-duplicate-names-diff-scopes", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
org, prj := iam.TestScopes(t, conn)
|
||||
in := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
Name: "test-name-repo",
|
||||
},
|
||||
}
|
||||
in2 := in.clone()
|
||||
|
||||
in.ScopeId = prj.GetPublicId()
|
||||
got, err := repo.CreateCatalog(context.Background(), in)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got)
|
||||
assertPublicId(t, "sthc", got.PublicId)
|
||||
assert.NotSame(in, got)
|
||||
assert.Equal(in.Name, got.Name)
|
||||
assert.Equal(in.Description, got.Description)
|
||||
|
||||
in2.ScopeId = org.GetPublicId()
|
||||
in2.Name = "first-name"
|
||||
got2, err := repo.CreateCatalog(context.Background(), in2)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got2)
|
||||
got2.Name = got.Name
|
||||
got3, gotCount3, err := repo.UpdateCatalog(context.Background(), got2, 1, []string{"name"})
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got3)
|
||||
assert.NotSame(got2, got3)
|
||||
assert.Equal(got.Name, got3.Name)
|
||||
assert.Equal(got2.Description, got3.Description)
|
||||
assert.Equal(1, gotCount3, "row count")
|
||||
})
|
||||
|
||||
t.Run("change-scope-id", func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
c1, c2 := testCatalog(t, conn), testCatalog(t, conn)
|
||||
assert.NotEqual(c1.ScopeId, c2.ScopeId)
|
||||
orig := c1.clone()
|
||||
|
||||
c1.ScopeId = c2.ScopeId
|
||||
assert.Equal(c1.ScopeId, c2.ScopeId)
|
||||
|
||||
got1, gotCount1, err := repo.UpdateCatalog(context.Background(), c1, 1, []string{"name"})
|
||||
|
||||
assert.NoError(err)
|
||||
assert.NotNil(got1)
|
||||
assert.Equal(orig.ScopeId, got1.ScopeId)
|
||||
assert.Equal(1, gotCount1, "row count")
|
||||
})
|
||||
}
|
||||
|
||||
func TestRepository_LookupCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
badId, err := newHostCatalogId()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, badId)
|
||||
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
id string
|
||||
want *HostCatalog
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "found",
|
||||
id: cat.GetPublicId(),
|
||||
want: cat,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: badId,
|
||||
want: nil,
|
||||
},
|
||||
{
|
||||
name: "bad-public-id",
|
||||
id: "",
|
||||
want: nil,
|
||||
wantErr: db.ErrInvalidParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
got, err := repo.LookupCatalog(context.Background(), tt.id)
|
||||
if tt.wantErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantErr), "want err: %q got: %q", tt.wantErr, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
|
||||
switch {
|
||||
case tt.want == nil:
|
||||
assert.Nil(got)
|
||||
case tt.want != nil:
|
||||
assert.NotNil(got)
|
||||
assert.Equal(got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRepository_DeleteCatalog(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
badId, err := newHostCatalogId()
|
||||
assert.NoError(t, err)
|
||||
assert.NotNil(t, badId)
|
||||
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
id string
|
||||
want int
|
||||
wantErr error
|
||||
}{
|
||||
{
|
||||
name: "found",
|
||||
id: cat.GetPublicId(),
|
||||
want: 1,
|
||||
},
|
||||
{
|
||||
name: "not-found",
|
||||
id: badId,
|
||||
want: 0,
|
||||
},
|
||||
{
|
||||
name: "bad-public-id",
|
||||
id: "",
|
||||
want: 0,
|
||||
wantErr: db.ErrInvalidParameter,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
repo, err := NewRepository(rw, rw, wrapper)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(repo)
|
||||
|
||||
got, err := repo.DeleteCatalog(context.Background(), tt.id)
|
||||
if tt.wantErr != nil {
|
||||
assert.Truef(errors.Is(err, tt.wantErr), "want err: %q got: %q", tt.wantErr, err)
|
||||
return
|
||||
}
|
||||
assert.NoError(err)
|
||||
assert.Equal(tt.want, got, "row count")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// A HostCatalog contains static hosts and static host sets. It is owned by
|
||||
// a scope.
|
||||
type HostCatalog struct {
|
||||
*store.HostCatalog
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostCatalog creates a new in memory HostCatalog assigned to scopeId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHostCatalog(scopeId string, opt ...Option) (*HostCatalog, error) {
|
||||
if scopeId == "" {
|
||||
return nil, fmt.Errorf("new: static host catalog: no scope id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
hc := &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: scopeId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return hc, nil
|
||||
}
|
||||
|
||||
func (c *HostCatalog) clone() *HostCatalog {
|
||||
cp := proto.Clone(c.HostCatalog)
|
||||
return &HostCatalog{
|
||||
HostCatalog: cp.(*store.HostCatalog),
|
||||
}
|
||||
}
|
||||
|
||||
// A Host contains a static address.
|
||||
type Host struct {
|
||||
*store.Host
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHost creates a new in memory Host for address assigned to catalogId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHost(catalogId, address string, opt ...Option) (*Host, error) {
|
||||
if catalogId == "" {
|
||||
return nil, fmt.Errorf("new: static host: no catalog id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if address == "" {
|
||||
return nil, fmt.Errorf("new: static host: no address: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
host := &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: catalogId,
|
||||
Address: address,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// A HostSet is a collection of hosts from the set's catalog.
|
||||
type HostSet struct {
|
||||
*store.HostSet
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostSet creates a new in memory HostSet assigned to catalogId.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func NewHostSet(catalogId string, opt ...Option) (*HostSet, error) {
|
||||
if catalogId == "" {
|
||||
return nil, fmt.Errorf("new: static host set: no catalog id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
|
||||
opts := getOpts(opt...)
|
||||
set := &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: catalogId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
},
|
||||
}
|
||||
return set, nil
|
||||
}
|
||||
|
||||
// A HostSetMember represents the membership of a host in a host set.
|
||||
type HostSetMember struct {
|
||||
*store.HostSetMember
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// NewHostSetMember creates a new in memory HostSetMember representing the
|
||||
// membership of hostId in hostSetId.
|
||||
func NewHostSetMember(hostSetId, hostId string, opt ...Option) (*HostSetMember, error) {
|
||||
if hostSetId == "" {
|
||||
return nil, fmt.Errorf("new: static host set member: no host set id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
if hostId == "" {
|
||||
return nil, fmt.Errorf("new: static host set member: no host id: %w", db.ErrInvalidParameter)
|
||||
}
|
||||
member := &HostSetMember{
|
||||
HostSetMember: &store.HostSetMember{
|
||||
StaticHostSetId: hostSetId,
|
||||
StaticHostId: hostId,
|
||||
},
|
||||
}
|
||||
return member, nil
|
||||
}
|
||||
|
||||
// PublicId prefixes for the resources in the static package.
|
||||
const (
|
||||
HostCatalogPrefix = "sthc"
|
||||
HostSetPrefix = "sths"
|
||||
HostPrefix = "sth"
|
||||
)
|
||||
|
||||
func newHostCatalogId() (string, error) {
|
||||
id, err := db.NewPublicId(HostCatalogPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host catalog id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
func newHostId() (string, error) {
|
||||
id, err := db.NewPublicId(HostPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
|
||||
func newHostSetId() (string, error) {
|
||||
id, err := db.NewPublicId(HostSetPrefix)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("new host set id: %w", err)
|
||||
}
|
||||
return id, err
|
||||
}
|
||||
@@ -1,474 +0,0 @@
|
||||
package static
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/static/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/jinzhu/gorm"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestHostCatalog_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
|
||||
type args struct {
|
||||
scopeId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *HostCatalog
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-scopeId",
|
||||
args: args{
|
||||
scopeId: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
scopeId: prj.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &HostCatalog{
|
||||
HostCatalog: &store.HostCatalog{
|
||||
ScopeId: prj.GetPublicId(),
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostCatalog(tt.args.scopeId, tt.args.opts...)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testCatalogs(t *testing.T, conn *gorm.DB, count int) []*HostCatalog {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
_, prj := iam.TestScopes(t, conn)
|
||||
var cats []*HostCatalog
|
||||
for i := 0; i < count; i++ {
|
||||
cat, err := NewHostCatalog(prj.GetPublicId())
|
||||
assert.NoError(err)
|
||||
assert.NotNil(cat)
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
cat.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), cat)
|
||||
assert.NoError(err2)
|
||||
cats = append(cats, cat)
|
||||
}
|
||||
return cats
|
||||
}
|
||||
|
||||
func testCatalog(t *testing.T, conn *gorm.DB) *HostCatalog {
|
||||
t.Helper()
|
||||
cats := testCatalogs(t, conn, 1)
|
||||
return cats[0]
|
||||
}
|
||||
|
||||
func TestHost_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
|
||||
conn.LogMode(false)
|
||||
type args struct {
|
||||
catalogId string
|
||||
address string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *Host
|
||||
wantCreateErr bool
|
||||
wantWriteErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-catalogId",
|
||||
args: args{
|
||||
catalogId: "",
|
||||
address: "127.0.0.1",
|
||||
},
|
||||
want: nil,
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-address",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "",
|
||||
},
|
||||
want: nil,
|
||||
wantCreateErr: true,
|
||||
},
|
||||
{
|
||||
name: "address-to-short",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "1234567",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "1234567",
|
||||
},
|
||||
},
|
||||
wantWriteErr: true,
|
||||
},
|
||||
{
|
||||
name: "minimum-address",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "12345678",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "12345678",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "127.0.0.1",
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Address: "127.0.0.1",
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHost(tt.args.catalogId, tt.args.address, tt.args.opts...)
|
||||
if tt.wantCreateErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
if tt.wantWriteErr {
|
||||
assert.Error(err2)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostSet_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
cat := testCatalog(t, conn)
|
||||
|
||||
conn.LogMode(false)
|
||||
type args struct {
|
||||
catalogId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
args args
|
||||
want *HostSet
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-catalogId",
|
||||
args: args{
|
||||
catalogId: "",
|
||||
},
|
||||
want: nil,
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
},
|
||||
want: &HostSet{
|
||||
HostSet: &store.HostSet{
|
||||
StaticHostCatalogId: cat.GetPublicId(),
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostSet(tt.args.catalogId, tt.args.opts...)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
assert.Emptyf(got.PublicId, "PublicId set")
|
||||
assert.Equal(tt.want, got)
|
||||
|
||||
id, err := newHostSetId()
|
||||
assert.NoError(err)
|
||||
|
||||
tt.want.PublicId = id
|
||||
got.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testHosts(t *testing.T, conn *gorm.DB, catalogId string, count int) []*Host {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
var hosts []*Host
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
host, err := NewHost(catalogId, fmt.Sprintf("%s-%d", catalogId, i))
|
||||
assert.NoError(err)
|
||||
assert.NotNil(host)
|
||||
|
||||
id, err := newHostCatalogId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
host.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), host)
|
||||
assert.NoError(err2)
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
return hosts
|
||||
}
|
||||
|
||||
func testSets(t *testing.T, conn *gorm.DB, catalogId string, count int) []*HostSet {
|
||||
t.Helper()
|
||||
assert := assert.New(t)
|
||||
var sets []*HostSet
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
set, err := NewHostSet(catalogId)
|
||||
assert.NoError(err)
|
||||
assert.NotNil(set)
|
||||
id, err := newHostSetId()
|
||||
assert.NoError(err)
|
||||
assert.NotEmpty(id)
|
||||
set.PublicId = id
|
||||
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), set)
|
||||
assert.NoError(err2)
|
||||
sets = append(sets, set)
|
||||
}
|
||||
return sets
|
||||
}
|
||||
|
||||
func TestHostSetMember_New(t *testing.T) {
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
conn.LogMode(false)
|
||||
|
||||
cats := testCatalogs(t, conn, 2)
|
||||
|
||||
blueCat := cats[0]
|
||||
blueSets := testSets(t, conn, blueCat.GetPublicId(), 2)
|
||||
blueHosts := testHosts(t, conn, blueCat.GetPublicId(), 2)
|
||||
|
||||
// TODO(mgaffney) 05/2020:
|
||||
// these will be needed when the repository code is done
|
||||
// greenCat := cats[1]
|
||||
// greenSets := testSets(t, conn, greenCat.GetPublicId(), 2)
|
||||
// greenHosts := testHosts(t, conn, greenCat.GetPublicId(), 2)
|
||||
|
||||
var tests = []struct {
|
||||
name string
|
||||
set *HostSet
|
||||
host *Host
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid-host-in-set",
|
||||
set: blueSets[0],
|
||||
host: blueHosts[0],
|
||||
},
|
||||
// {
|
||||
// name: "invalid-diff-catalogs",
|
||||
// set: greenSets[0],
|
||||
// host: blueHosts[0],
|
||||
// wantErr: true,
|
||||
// },
|
||||
}
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
got, err := NewHostSetMember(tt.set.PublicId, tt.host.PublicId)
|
||||
if tt.wantErr {
|
||||
assert.Error(err)
|
||||
assert.Nil(got)
|
||||
} else {
|
||||
assert.NoError(err)
|
||||
if assert.NotNil(got) {
|
||||
w := db.New(conn)
|
||||
err2 := w.Create(context.Background(), got)
|
||||
assert.NoError(err2)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user