* database: add wt_public_id domain type * static-hosts: add migrations * Rename migrations * migrations: add description column and fix foreign keys * Add protobuf for static host * Add HostCatalog and HostSet * Add Options * Add foreign key constraint * Add package doc * Add copied scanner code * Add NewHostCatalog with tests * Override default table name for static host catalog * WIP: save static host catalog to database * WIP: Print db url for debugging * Add iam test helper function * Make gorm default to null for names and descriptions * Add foreign key constraint from host catalog to scope * Names are not needed for the test org and project * Avoid an ordering dependency in down migrations * Use wt_timestamp * Add check constraint on host address column * Add Host * Add HostSet * Add HostSetMember * Test a HostSetMember can be written to the database * Move the getters and setters for table name to a new file The TableName methods are needed by gorm and the SetTableName methods are for oplog. Moving them to a new file so related functionality is in the same file. * Add repository * Add NewRepository * Close connection before cleanup of database * Add comments to protobuf file and regenerate * Define repository methods for HostCatalog * Assign PublicId when resource is inserted into the database * Wrap a nil parameter error * Add oplog tickets for static host types * WIP: first cut at CreateCatalog * CreateHostCatalog: more tests * Detect unique constraint violation * Use const for PublicId prefixes * Use PostgreSQL error name instead of error code * Add TODO comments * Fix comments * Use PublicId not PublicID * Refactor: move error variables from host/static to db The error variables defined in host/static are generic and can be reused by other packages. * Create a new repository for each test * Validate CreateCatalog returns a new HostCatalog * Do not modify the HostCatalog passed in * Implement UpdateCatalog * Minor cleanup to make folds work * Implement LookupCatalog * Refactor: extract allocCatalog function * Add comment * Refactor: extract newCatalogMetadata function * Make error strings more consistent * Move database specific error check to internal/db package * Change signature of DeleteCatalog and update docs * Implement DeleteCatalog * Make error strings more consistent * Add examples * Update docs * Add package level doc and example for repository * No need for using reflect.DeepEqual * Remove redundant comment * Clarify ErrMultipleRecords results in the transaction being rolled back * Remove redundant error checks * Remove unnecessary check * Return early instead of using nested 'else' statements * Update and Delete must return a row count * catch err on defers (#82) Co-authored-by: Jim Lambert <jimlambrt@Jims-MBP-3.home> * Remove 'if assert' pattern * Use assert package in test helper function * Add test for updating a non existent catalog * Use a single assert when a specific error is expected * Use assert package when it clarifies the check * Catch errors in cleanup functions * Update comments in protobuf file * Update doc for UpdateCatalog to reflect the new behavior * Add common error values for field mask errors * Require a field mask when calling update methods * Add TODO for removing direct call to gorm * Export Public ID prefixes * Add db timestamp guards * Remove unused option Co-authored-by: Jim <jlambert@hashicorp.com> Co-authored-by: Jim Lambert <jimlambrt@Jims-MBP-3.home>
152 lines
3.9 KiB
Go
152 lines
3.9 KiB
Go
package static
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/watchtower/internal/db"
|
|
"github.com/hashicorp/watchtower/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
|
|
}
|