Add DB changes for host, set members, and host addresses for plugins. (#1584)
* Add DB changes for host, set members, and host addresses for plugins. * Add priority, address review feedback, update tests, naming, protos Co-authored-by: Jeff Mitchell <jeffrey.mitchell@gmail.com> Co-authored-by: Michael Gaffney <mgaffney@users.noreply.github.com>
This commit is contained in:
26 files changed
+2341
-352
No files matched your search
@@ -0,0 +1,18 @@
|
||||
begin;
|
||||
|
||||
create domain wt_priority as int not null
|
||||
constraint priority_must_be_greater_than_zero
|
||||
check(value > 0);
|
||||
comment on domain wt_priority is
|
||||
'Represents a priority value which must not be null and must be greater than zero';
|
||||
|
||||
-- wt_dns_name defines a type for dns names
|
||||
create domain wt_dns_name as text not null
|
||||
constraint wt_dns_name_too_short
|
||||
check (length(trim(value)) > 0)
|
||||
constraint wt_dns_name_too_long
|
||||
check (length(trim(value)) < 256);
|
||||
comment on domain wt_dns_name is
|
||||
'standard column for dns names';
|
||||
|
||||
commit;
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
+180
-29
@@ -56,10 +56,10 @@ begin;
|
||||
version wt_version,
|
||||
attributes bytea not null,
|
||||
constraint host_catalog_fkey
|
||||
foreign key (scope_id, public_id)
|
||||
references host_catalog (scope_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
foreign key (scope_id, public_id)
|
||||
references host_catalog (scope_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
constraint host_plugin_catalog_scope_id_name_uq
|
||||
unique(scope_id, name)
|
||||
);
|
||||
@@ -128,10 +128,10 @@ begin;
|
||||
constraint host_plugin_set_catalog_id_name_uq
|
||||
unique(catalog_id, name),
|
||||
constraint host_set_fkey
|
||||
foreign key (catalog_id, public_id)
|
||||
references host_set (catalog_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
foreign key (catalog_id, public_id)
|
||||
references host_set (catalog_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
constraint host_plugin_set_catalog_id_public_id_uq
|
||||
unique(catalog_id, public_id)
|
||||
);
|
||||
@@ -154,10 +154,7 @@ begin;
|
||||
create trigger delete_host_set_subtype after delete on host_plugin_set
|
||||
for each row execute procedure delete_host_set_subtype();
|
||||
|
||||
|
||||
-- TODO: Rebuild this table to appropriately cache or sync data from the
|
||||
-- plugin'ed service.
|
||||
-- host_plugin_host captures plugin based host data. This is only written to
|
||||
-- host_plugin_host captures plugin based host data. This is only written to
|
||||
-- from the controller and is not mutable directly by actions from the end
|
||||
-- user.
|
||||
create table host_plugin_host (
|
||||
@@ -167,37 +164,28 @@ begin;
|
||||
references host_plugin_catalog (public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
external_id text not null
|
||||
constraint external_id_must_not_be_empty
|
||||
check(length(trim(external_id)) > 0),
|
||||
name wt_name,
|
||||
description text,
|
||||
create_time wt_timestamp,
|
||||
-- update_time is the last time the data was synced with what is provided
|
||||
-- from the plugin.
|
||||
update_time wt_timestamp,
|
||||
version wt_version,
|
||||
|
||||
-- TODO: Break out the address to match the domain model where a host
|
||||
-- can have multiple addresses and relies on the set to select the
|
||||
-- prefered one.
|
||||
address text not null
|
||||
constraint address_must_be_more_than_2_characters
|
||||
check(length(trim(address)) > 2)
|
||||
constraint address_must_be_less_than_256_characters
|
||||
check(length(trim(address)) < 256),
|
||||
|
||||
constraint host_fkey
|
||||
foreign key (catalog_id, public_id)
|
||||
references host (catalog_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
|
||||
constraint host_plugin_host_catalog_id_name_uq
|
||||
unique(catalog_id, name),
|
||||
|
||||
constraint host_plugin_host_catalog_id_external_id_uq
|
||||
unique(catalog_id, external_id),
|
||||
constraint host_plugin_host_catalog_id_public_id_uq
|
||||
unique(catalog_id, public_id)
|
||||
);
|
||||
|
||||
create trigger update_version_column after update on host_plugin_host
|
||||
for each row execute procedure update_version_column();
|
||||
|
||||
create trigger update_time_column before update on host_plugin_host
|
||||
for each row execute procedure update_time_column();
|
||||
|
||||
@@ -205,7 +193,7 @@ begin;
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on host_plugin_host
|
||||
for each row execute procedure immutable_columns('public_id', 'catalog_id','create_time');
|
||||
for each row execute procedure immutable_columns('public_id', 'catalog_id', 'external_id', 'create_time');
|
||||
|
||||
create trigger insert_host_subtype before insert on host_plugin_host
|
||||
for each row execute procedure insert_host_subtype();
|
||||
@@ -213,6 +201,141 @@ begin;
|
||||
create trigger delete_host_subtype after delete on host_plugin_host
|
||||
for each row execute procedure delete_host_subtype();
|
||||
|
||||
-- host_ip_address contains the IP addresses associated with
|
||||
-- a host, one per row.
|
||||
create table host_ip_address (
|
||||
host_id wt_public_id
|
||||
constraint host_fkey
|
||||
references host(public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
priority wt_priority,
|
||||
address inet not null,
|
||||
create_time wt_timestamp,
|
||||
primary key (host_id, priority),
|
||||
constraint host_ip_address_host_id_address_uq
|
||||
unique(host_id, address)
|
||||
);
|
||||
comment on table host_ip_address is
|
||||
'host_ip_address entries are ip addresses set on a host with a preserved order.';
|
||||
|
||||
create trigger default_create_time_column before insert on host_ip_address
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
-- host_immutable_ip_address() ensures that ip addresses assigned to hosts are
|
||||
-- immutable.
|
||||
create function
|
||||
host_immutable_ip_address()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
raise exception 'host ip addresses are immutable';
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
create trigger immutable_ip_address
|
||||
before update on host_ip_address
|
||||
for each row execute procedure host_immutable_ip_address();
|
||||
|
||||
-- host_dns_name contains the DNS names associated with a host, one per row.
|
||||
create table host_dns_name (
|
||||
host_id wt_public_id
|
||||
constraint host_fkey
|
||||
references host(public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
priority wt_priority,
|
||||
name wt_dns_name,
|
||||
create_time wt_timestamp,
|
||||
primary key (host_id, priority),
|
||||
constraint host_dns_name_host_id_name_uq
|
||||
unique(host_id, name)
|
||||
);
|
||||
comment on table host_dns_name is
|
||||
'host_dns_name entries are dns names set on a host with a preserved order.';
|
||||
|
||||
create trigger default_create_time_column before insert on host_dns_name
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
-- host_immutable_dns_name() ensures that dns names assigned to hosts are
|
||||
-- immutable.
|
||||
create function
|
||||
host_immutable_dns_name()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
raise exception 'host dns names are immutable';
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
|
||||
create trigger immutable_dns_name
|
||||
before update on host_dns_name
|
||||
for each row execute procedure host_immutable_dns_name();
|
||||
|
||||
create table host_plugin_set_member (
|
||||
host_id wt_public_id not null,
|
||||
set_id wt_public_id not null,
|
||||
catalog_id wt_public_id not null,
|
||||
create_time wt_timestamp,
|
||||
primary key(host_id, set_id),
|
||||
constraint host_plugin_host_fkey
|
||||
foreign key (catalog_id, host_id)
|
||||
references host_plugin_host (catalog_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
constraint host_plugin_set_fkey
|
||||
foreign key (catalog_id, set_id)
|
||||
references host_plugin_set (catalog_id, public_id)
|
||||
on delete cascade
|
||||
on update cascade
|
||||
);
|
||||
comment on table host_plugin_set_member is
|
||||
'host_plugin_set_member entries are the membership relationships from plugin hosts in plugin sets.';
|
||||
|
||||
create trigger default_create_time_column before insert on host_plugin_set_member
|
||||
for each row execute procedure default_create_time();
|
||||
|
||||
create trigger immutable_columns before update on host_plugin_set_member
|
||||
for each row execute procedure immutable_columns('host_id', 'set_id', 'catalog_id', 'create_time');
|
||||
|
||||
create function insert_host_plugin_set_member()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
select host_plugin_set.catalog_id
|
||||
into new.catalog_id
|
||||
from host_plugin_set
|
||||
where host_plugin_set.public_id = new.set_id;
|
||||
return new;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
comment on function insert_host_plugin_set_member is
|
||||
'insert_host_plugin_set_member entries are the membership relationships from plugin hosts in plugin sets.';
|
||||
|
||||
create trigger insert_host_plugin_set_member before insert on host_plugin_set_member
|
||||
for each row execute procedure insert_host_plugin_set_member();
|
||||
|
||||
-- delete_orphaned_host_plugin_host is an after delete trigger
|
||||
-- function to delete plugin hosts when no more set members
|
||||
-- reference it.
|
||||
create function delete_orphaned_host_plugin_host()
|
||||
returns trigger
|
||||
as $$
|
||||
begin
|
||||
delete from host_plugin_host
|
||||
where not exists (select host_id
|
||||
from host_plugin_set_member
|
||||
where host_id = old.host_id)
|
||||
and
|
||||
public_id = old.host_id;
|
||||
return null;
|
||||
end;
|
||||
$$ language plpgsql;
|
||||
comment on function delete_orphaned_host_plugin_host is
|
||||
'delete_orphaned_host_plugin_host deletes a host when all set members with that host are deleted.';
|
||||
|
||||
create trigger delete_orphaned_host_plugin_host after delete on host_plugin_set_member
|
||||
for each row execute procedure delete_orphaned_host_plugin_host();
|
||||
|
||||
insert into oplog_ticket (name, version)
|
||||
values
|
||||
@@ -220,4 +343,32 @@ begin;
|
||||
('host_plugin_catalog_secret', 1),
|
||||
('host_plugin_set', 1);
|
||||
|
||||
|
||||
-- host_plugin_host_with_value_obj is useful for reading a plugin host with
|
||||
-- its associated value objects (ip addresses, dns names, set membership) as
|
||||
-- columns with delimited values. The delimiter depends on the value objects
|
||||
-- (e.g. if they need ordering).
|
||||
create view host_plugin_host_with_value_obj as
|
||||
select
|
||||
h.public_id,
|
||||
h.catalog_id,
|
||||
h.external_id,
|
||||
hc.plugin_id,
|
||||
h.name,
|
||||
h.description,
|
||||
h.create_time,
|
||||
h.update_time,
|
||||
-- the string_agg(..) column will be null if there are no associated value objects
|
||||
string_agg(distinct concat_ws('=', hip.priority, hip.address), '|') as ip_addresses,
|
||||
string_agg(distinct concat_ws('=', hdns.priority, hdns.name), '|') as dns_names
|
||||
from
|
||||
host_plugin_host h
|
||||
join host_plugin_catalog hc on h.catalog_id = hc.public_id
|
||||
left outer join host_ip_address hip on h.public_id = hip.host_id
|
||||
left outer join host_dns_name hdns on h.public_id = hdns.host_id
|
||||
-- FIXME: add set membership once that's shaken out
|
||||
group by h.public_id, hc.plugin_id;
|
||||
comment on view host_plugin_host_with_value_obj is
|
||||
'host plugin host with its associated value objects';
|
||||
|
||||
commit;
|
||||
+1
-3
@@ -7,9 +7,7 @@ create table host_set_preferred_endpoint (
|
||||
references host_set(public_id)
|
||||
on delete cascade
|
||||
on update cascade,
|
||||
priority int not null
|
||||
constraint priority_must_be_greater_than_zero
|
||||
check(priority > 0),
|
||||
priority wt_priority,
|
||||
condition text not null
|
||||
constraint condition_must_not_be_too_short
|
||||
check(length(trim(condition)) > 4) -- minimum is 'dns:*'
|
||||
File renamed without changes.
@@ -20,4 +20,6 @@ type Host interface {
|
||||
boundary.Resource
|
||||
GetCatalogId() string
|
||||
GetAddress() string
|
||||
GetIpAddresses() []string
|
||||
GetDnsNames() []string
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/store"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// NOTE: Tests for this are in the plugin subtype directory in host_address_test.go
|
||||
|
||||
const defaultDnsNameTableName = "host_dns_name"
|
||||
|
||||
type DnsName struct {
|
||||
*store.DnsName
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
func NewDnsName(ctx context.Context, hostId string, priority uint32, name string) (*DnsName, error) {
|
||||
const op = "host.NewDnsName"
|
||||
dn := &DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: hostId,
|
||||
Name: name,
|
||||
Priority: priority,
|
||||
},
|
||||
}
|
||||
if err := dn.validate(ctx, op); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dn, nil
|
||||
}
|
||||
|
||||
// validate the host dns name. On success, it will return nil.
|
||||
func (dn *DnsName) validate(ctx context.Context, caller errors.Op) error {
|
||||
if dn.HostId == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "missing host id")
|
||||
}
|
||||
if dn.Priority < 1 {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "invalid priority value")
|
||||
}
|
||||
if dn.Name == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "missing dns name")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// allocDnsName make an empty one in memory.
|
||||
func allocDnsName() DnsName {
|
||||
return DnsName{
|
||||
DnsName: &store.DnsName{},
|
||||
}
|
||||
}
|
||||
|
||||
// Clone an DnsName
|
||||
func (c *DnsName) Clone() *DnsName {
|
||||
cp := proto.Clone(c.DnsName)
|
||||
return &DnsName{
|
||||
DnsName: cp.(*store.DnsName),
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (c *DnsName) TableName() string {
|
||||
if c.tableName != "" {
|
||||
return c.tableName
|
||||
}
|
||||
return defaultDnsNameTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (c *DnsName) SetTableName(n string) {
|
||||
c.tableName = n
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package host
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/store"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
// NOTE: Tests for this are in the plugin subtype directory in host_address_test.go
|
||||
|
||||
const defaultIpAddressTableName = "host_ip_address"
|
||||
|
||||
type IpAddress struct {
|
||||
*store.IpAddress
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
func NewIpAddress(ctx context.Context, hostId string, priority uint32, address string) (*IpAddress, error) {
|
||||
const op = "host.NewIpAddress"
|
||||
|
||||
ia := &IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: hostId,
|
||||
Address: address,
|
||||
Priority: priority,
|
||||
},
|
||||
}
|
||||
if err := ia.validate(ctx, op); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return ia, nil
|
||||
}
|
||||
|
||||
// validate the host ip address. On success, it will return nil.
|
||||
func (ia *IpAddress) validate(ctx context.Context, caller errors.Op) error {
|
||||
if ia.HostId == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "missing host id")
|
||||
}
|
||||
if ia.Priority < 1 {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "invalid priority value")
|
||||
}
|
||||
if ia.Address == "" {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "missing ip address")
|
||||
}
|
||||
if ip := net.ParseIP(ia.Address); ip == nil {
|
||||
return errors.New(ctx, errors.InvalidParameter, caller, "given address is not an ip address")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// allocIpAddress make an empty one in memory.
|
||||
func allocIpAddress() IpAddress {
|
||||
return IpAddress{
|
||||
IpAddress: &store.IpAddress{},
|
||||
}
|
||||
}
|
||||
|
||||
// Clone an IpAddress
|
||||
func (c *IpAddress) Clone() *IpAddress {
|
||||
cp := proto.Clone(c.IpAddress)
|
||||
return &IpAddress{
|
||||
IpAddress: cp.(*store.IpAddress),
|
||||
}
|
||||
}
|
||||
|
||||
// TableName returns the table name.
|
||||
func (c *IpAddress) TableName() string {
|
||||
if c.tableName != "" {
|
||||
return c.tableName
|
||||
}
|
||||
return defaultIpAddressTableName
|
||||
}
|
||||
|
||||
// SetTableName sets the table name.
|
||||
func (c *IpAddress) SetTableName(n string) {
|
||||
c.tableName = n
|
||||
}
|
||||
+129
-20
@@ -2,9 +2,14 @@ package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
"google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
@@ -14,27 +19,42 @@ import (
|
||||
// field for this host's host catalog.
|
||||
type Host struct {
|
||||
*store.Host
|
||||
PluginId string `gorm:"-"`
|
||||
tableName string `gorm:"-"`
|
||||
}
|
||||
|
||||
// newHost creates a new in memory Host assigned to catalogId with an address.
|
||||
// Name and description are the only valid options. All other options are
|
||||
// ignored.
|
||||
func newHost(ctx context.Context, catalogId, address string, opt ...Option) *Host {
|
||||
// Supported options: WithName, WithDescription, WithIpAddresses, WithDnsNames,
|
||||
// WithPluginId. Others ignored.
|
||||
func newHost(ctx context.Context, catalogId, externalId string, opt ...Option) *Host {
|
||||
opts := getOpts(opt...)
|
||||
|
||||
h := &Host{
|
||||
PluginId: opts.withPluginId,
|
||||
Host: &store.Host{
|
||||
CatalogId: catalogId,
|
||||
ExternalId: externalId,
|
||||
Name: opts.withName,
|
||||
Description: opts.withDescription,
|
||||
Address: address,
|
||||
},
|
||||
}
|
||||
if len(opts.withIpAddresses) > 0 {
|
||||
h.IpAddresses = make([]string, 0, len(opts.withIpAddresses))
|
||||
h.IpAddresses = append(h.IpAddresses, opts.withIpAddresses...)
|
||||
}
|
||||
if len(opts.withDnsNames) > 0 {
|
||||
h.DnsNames = make([]string, 0, len(opts.withDnsNames))
|
||||
h.DnsNames = append(h.DnsNames, opts.withDnsNames...)
|
||||
}
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
// For compatibility with the general Host type
|
||||
func (h *Host) GetAddress() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host set.
|
||||
func (s *Host) TableName() string {
|
||||
if s.tableName != "" {
|
||||
@@ -55,22 +75,111 @@ func allocHost() *Host {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Host) clone() *Host {
|
||||
cp := proto.Clone(s.Host)
|
||||
hs := &Host{
|
||||
Host: cp.(*store.Host),
|
||||
func (h *Host) clone() *Host {
|
||||
cp := proto.Clone(h.Host)
|
||||
return &Host{
|
||||
PluginId: h.PluginId,
|
||||
Host: cp.(*store.Host),
|
||||
}
|
||||
return hs
|
||||
}
|
||||
|
||||
func (s *Host) oplog(op oplog.OpType) oplog.Metadata {
|
||||
metadata := oplog.Metadata{
|
||||
"resource-public-id": []string{s.PublicId},
|
||||
"resource-type": []string{"plugin-host"},
|
||||
"op-type": []string{op.String()},
|
||||
}
|
||||
if s.CatalogId != "" {
|
||||
metadata["catalog-id"] = []string{s.CatalogId}
|
||||
}
|
||||
return metadata
|
||||
// hostAgg is a view that aggregates the host's value objects in to
|
||||
// string fields delimited with the aggregateDelimiter of "|"
|
||||
type hostAgg struct {
|
||||
PublicId string `gorm:"primary_key"`
|
||||
CatalogId string
|
||||
ExternalId string
|
||||
PluginId string
|
||||
Name string
|
||||
Description string
|
||||
CreateTime *timestamp.Timestamp
|
||||
UpdateTime *timestamp.Timestamp
|
||||
IpAddresses string
|
||||
DnsNames string
|
||||
}
|
||||
|
||||
func (agg *hostAgg) toHost(ctx context.Context) (*Host, error) {
|
||||
const op = "plugin.(hostAgg).toHost"
|
||||
const aggregateDelimiter = "|"
|
||||
const priorityDelimiter = "="
|
||||
h := allocHost()
|
||||
h.PublicId = agg.PublicId
|
||||
h.CatalogId = agg.CatalogId
|
||||
h.ExternalId = agg.ExternalId
|
||||
h.PluginId = agg.PluginId
|
||||
h.Name = agg.Name
|
||||
h.Description = agg.Description
|
||||
h.CreateTime = agg.CreateTime
|
||||
h.UpdateTime = agg.UpdateTime
|
||||
|
||||
// This function is used to protect against someone messing with the order
|
||||
// in the DB by doing some validation
|
||||
prioritySortFunc := func(in []string) error {
|
||||
var sortErr error
|
||||
sort.Slice(in, func(i, j int) bool {
|
||||
ini := strings.Split(in[i], priorityDelimiter)
|
||||
if len(ini) != 2 {
|
||||
sortErr = errors.New(ctx, errors.NotSpecificIntegrity, op, fmt.Sprintf("value %s had unexpected fields", in[i]))
|
||||
return false
|
||||
}
|
||||
inj := strings.Split(in[j], priorityDelimiter)
|
||||
if len(inj) != 2 {
|
||||
sortErr = errors.New(ctx, errors.NotSpecificIntegrity, op, fmt.Sprintf("value %s had unexpected fields", in[j]))
|
||||
return false
|
||||
}
|
||||
indexi, err := strconv.Atoi(ini[0])
|
||||
if err != nil {
|
||||
sortErr = errors.Wrap(ctx, err, op)
|
||||
return false
|
||||
}
|
||||
indexj, err := strconv.Atoi(inj[0])
|
||||
if err != nil {
|
||||
sortErr = errors.Wrap(ctx, err, op)
|
||||
return false
|
||||
}
|
||||
return indexi < indexj
|
||||
})
|
||||
return sortErr
|
||||
}
|
||||
|
||||
if agg.IpAddresses != "" {
|
||||
ips := strings.Split(agg.IpAddresses, aggregateDelimiter)
|
||||
if len(ips) > 0 {
|
||||
if err := prioritySortFunc(ips); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, ip := range ips {
|
||||
// At this point they're in the correct order, but we still
|
||||
// have to strip off the priority
|
||||
ips[i] = strings.Split(ip, priorityDelimiter)[1]
|
||||
}
|
||||
h.IpAddresses = ips
|
||||
}
|
||||
}
|
||||
|
||||
if agg.DnsNames != "" {
|
||||
names := strings.Split(agg.DnsNames, aggregateDelimiter)
|
||||
if len(names) > 0 {
|
||||
if err := prioritySortFunc(names); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i, name := range names {
|
||||
// At this point they're in the correct order, but we still
|
||||
// have to strip off the priority
|
||||
names[i] = strings.Split(name, priorityDelimiter)[1]
|
||||
}
|
||||
h.DnsNames = names
|
||||
}
|
||||
}
|
||||
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// TableName returns the table name for gorm
|
||||
func (agg *hostAgg) TableName() string {
|
||||
return "host_plugin_host_with_value_obj"
|
||||
}
|
||||
|
||||
func (agg *hostAgg) GetPublicId() string {
|
||||
return agg.PublicId
|
||||
}
|
||||
@@ -0,0 +1,548 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host"
|
||||
"github.com/hashicorp/boundary/internal/host/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
hostplugin "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestHostDnsName_Create(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
w := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
plg := hostplugin.TestPlugin(t, conn, "test")
|
||||
cat := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
host1 := testHost(t, conn, cat.GetPublicId(), "external")
|
||||
|
||||
type args struct {
|
||||
hostId string
|
||||
name string
|
||||
priority uint32
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *host.DnsName
|
||||
wantNewErr bool
|
||||
skipNewFunc bool
|
||||
wantDbErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-host-id-validate",
|
||||
args: args{
|
||||
hostId: "",
|
||||
name: "foo.bar.com",
|
||||
priority: 1,
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-name-validate",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "",
|
||||
priority: 1,
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-priority-validate",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "foo.bar.com",
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-host-id-db",
|
||||
args: args{
|
||||
name: "foo.bar.com",
|
||||
priority: 1,
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-name-db",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
priority: 1,
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-priority-db",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "foo.bar.com",
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "foo.bar.com",
|
||||
priority: 1,
|
||||
},
|
||||
want: &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: host1.GetPublicId(),
|
||||
Name: "foo.bar.com",
|
||||
Priority: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate-name",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "foo.bar.com",
|
||||
priority: 2,
|
||||
},
|
||||
want: &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: host1.GetPublicId(),
|
||||
Name: "foo.bar.com",
|
||||
Priority: 2,
|
||||
},
|
||||
},
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "duplicate-priority",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "baz.bar.com",
|
||||
priority: 1,
|
||||
},
|
||||
want: &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: host1.GetPublicId(),
|
||||
Name: "baz.bar.com",
|
||||
Priority: 1,
|
||||
},
|
||||
},
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-second",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
name: "baz.bar.com",
|
||||
priority: 2,
|
||||
},
|
||||
want: &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: host1.GetPublicId(),
|
||||
Name: "baz.bar.com",
|
||||
Priority: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
var got *host.DnsName
|
||||
var err error
|
||||
if !tt.skipNewFunc {
|
||||
got, err = host.NewDnsName(ctx, tt.args.hostId, tt.args.priority, tt.args.name)
|
||||
if tt.wantNewErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Equal(tt.want, got)
|
||||
} else {
|
||||
got = &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: tt.args.hostId,
|
||||
Name: tt.args.name,
|
||||
Priority: tt.args.priority,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
require.NotNil(got)
|
||||
err = w.Create(ctx, got)
|
||||
if tt.wantDbErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostIpAddress_Create(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
w := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
plg := hostplugin.TestPlugin(t, conn, "test")
|
||||
cat := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
host1 := testHost(t, conn, cat.GetPublicId(), "external")
|
||||
|
||||
type args struct {
|
||||
hostId string
|
||||
address string
|
||||
priority uint32
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want *host.IpAddress
|
||||
wantNewErr bool
|
||||
skipNewFunc bool
|
||||
wantDbErr bool
|
||||
}{
|
||||
{
|
||||
name: "blank-host-id-validate",
|
||||
args: args{
|
||||
hostId: "",
|
||||
address: "1.2.3.4",
|
||||
priority: 1,
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-name-validate",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "",
|
||||
priority: 1,
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-priority-validate",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "1.2.3.4",
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "bad-address-validate",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
},
|
||||
wantNewErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-host-id-db",
|
||||
args: args{
|
||||
address: "1.2.3.4",
|
||||
priority: 1,
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-address-db",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
priority: 1,
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-priority-db",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "1.2.3.4",
|
||||
},
|
||||
skipNewFunc: true,
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "1.2.3.4",
|
||||
priority: 1,
|
||||
},
|
||||
want: &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: host1.GetPublicId(),
|
||||
Address: "1.2.3.4",
|
||||
Priority: 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate-name",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "1.2.3.4",
|
||||
priority: 2,
|
||||
},
|
||||
want: &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: host1.GetPublicId(),
|
||||
Address: "1.2.3.4",
|
||||
Priority: 2,
|
||||
},
|
||||
},
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "duplicate-priority",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "2.3.4.5",
|
||||
priority: 1,
|
||||
},
|
||||
want: &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: host1.GetPublicId(),
|
||||
Address: "2.3.4.5",
|
||||
Priority: 1,
|
||||
},
|
||||
},
|
||||
wantDbErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-second",
|
||||
args: args{
|
||||
hostId: host1.GetPublicId(),
|
||||
address: "2.3.4.5",
|
||||
priority: 2,
|
||||
},
|
||||
want: &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: host1.GetPublicId(),
|
||||
Address: "2.3.4.5",
|
||||
Priority: 2,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
var got *host.IpAddress
|
||||
var err error
|
||||
if !tt.skipNewFunc {
|
||||
got, err = host.NewIpAddress(ctx, tt.args.hostId, tt.args.priority, tt.args.address)
|
||||
if tt.wantNewErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
require.Equal(tt.want, got)
|
||||
} else {
|
||||
got = &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: tt.args.hostId,
|
||||
Address: tt.args.address,
|
||||
Priority: tt.args.priority,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
require.NotNil(got)
|
||||
err = w.Create(ctx, got)
|
||||
if tt.wantDbErr {
|
||||
require.Error(err)
|
||||
return
|
||||
}
|
||||
require.NoError(err)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostDnsName_Delete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
w := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
plg := hostplugin.TestPlugin(t, conn, "test")
|
||||
cat := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
host1 := testHost(t, conn, cat.GetPublicId(), "external")
|
||||
addr1, err := host.NewDnsName(ctx, host1.GetPublicId(), 1, "addr1.foo.com")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.Create(ctx, addr1))
|
||||
|
||||
type args struct {
|
||||
hostId string
|
||||
name string
|
||||
priority uint32
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantDelete bool
|
||||
wantError bool
|
||||
}{
|
||||
{
|
||||
name: "wrong_host_id",
|
||||
args: args{
|
||||
hostId: "something",
|
||||
name: addr1.GetName(),
|
||||
priority: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing_priority",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
name: addr1.GetName(),
|
||||
},
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "wrong_priority",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
name: addr1.GetName(),
|
||||
priority: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
name: addr1.GetName(),
|
||||
priority: 1,
|
||||
},
|
||||
wantDelete: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := &host.DnsName{
|
||||
DnsName: &store.DnsName{
|
||||
HostId: tt.args.hostId,
|
||||
Name: tt.args.name,
|
||||
Priority: tt.args.priority,
|
||||
},
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
k, err := w.Delete(ctx, got)
|
||||
if tt.wantError {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
if tt.wantDelete {
|
||||
assert.Equal(t, 1, k)
|
||||
} else {
|
||||
assert.Equal(t, 0, k)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestHostIpAddress_Delete(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
w := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
_, prj := iam.TestScopes(t, iam.TestRepo(t, conn, wrapper))
|
||||
plg := hostplugin.TestPlugin(t, conn, "test")
|
||||
cat := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
host1 := testHost(t, conn, cat.GetPublicId(), "external")
|
||||
addr1, err := host.NewIpAddress(ctx, host1.GetPublicId(), 1, "1.2.3.4")
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.Create(ctx, addr1))
|
||||
|
||||
type args struct {
|
||||
hostId string
|
||||
address string
|
||||
priority uint32
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
wantDelete bool
|
||||
wantError bool
|
||||
}{
|
||||
{
|
||||
name: "wrong_host_id",
|
||||
args: args{
|
||||
hostId: "something",
|
||||
address: addr1.GetAddress(),
|
||||
priority: 1,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "missing_priority",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
address: addr1.GetAddress(),
|
||||
},
|
||||
wantError: true,
|
||||
},
|
||||
{
|
||||
name: "wrong_priority",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
address: addr1.GetAddress(),
|
||||
priority: 2,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
args: args{
|
||||
hostId: addr1.GetHostId(),
|
||||
address: addr1.GetAddress(),
|
||||
priority: 1,
|
||||
},
|
||||
wantDelete: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got := &host.IpAddress{
|
||||
IpAddress: &store.IpAddress{
|
||||
HostId: tt.args.hostId,
|
||||
Address: tt.args.address,
|
||||
Priority: tt.args.priority,
|
||||
},
|
||||
}
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
k, err := w.Delete(ctx, got)
|
||||
if tt.wantError {
|
||||
assert.Error(t, err)
|
||||
return
|
||||
}
|
||||
require.NoError(t, err)
|
||||
if tt.wantDelete {
|
||||
assert.Equal(t, 1, k)
|
||||
} else {
|
||||
assert.Equal(t, 0, k)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -21,9 +21,9 @@ func TestHost_Create(t *testing.T) {
|
||||
cat2 := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
|
||||
type args struct {
|
||||
catalogId string
|
||||
address string
|
||||
opts []Option
|
||||
catalogId string
|
||||
externalId string
|
||||
opts []Option
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
@@ -35,16 +35,16 @@ func TestHost_Create(t *testing.T) {
|
||||
{
|
||||
name: "blank-catalogId",
|
||||
args: args{
|
||||
catalogId: "",
|
||||
address: "foo.bar.com",
|
||||
catalogId: "",
|
||||
externalId: "external_id",
|
||||
},
|
||||
want: &Host{Host: &store.Host{
|
||||
Address: "foo.bar.com",
|
||||
ExternalId: "external_id",
|
||||
}},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "blank-address",
|
||||
name: "blank-external-id",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
},
|
||||
@@ -56,47 +56,47 @@ func TestHost_Create(t *testing.T) {
|
||||
{
|
||||
name: "valid-no-options",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
catalogId: cat.GetPublicId(),
|
||||
externalId: "valid-no-options",
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
CatalogId: cat.GetPublicId(),
|
||||
Address: "foo.bar.com",
|
||||
CatalogId: cat.GetPublicId(),
|
||||
ExternalId: "valid-no-options",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
catalogId: cat.GetPublicId(),
|
||||
externalId: "valid-with-name",
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
CatalogId: cat.GetPublicId(),
|
||||
Address: "foo.bar.com",
|
||||
Name: "test-name",
|
||||
CatalogId: cat.GetPublicId(),
|
||||
ExternalId: "valid-with-name",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "duplicate-name",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
catalogId: cat.GetPublicId(),
|
||||
externalId: "duplicate-name",
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
CatalogId: cat.GetPublicId(),
|
||||
Address: "foo.bar.com",
|
||||
Name: "test-name",
|
||||
CatalogId: cat.GetPublicId(),
|
||||
ExternalId: "duplicate-name",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
wantErr: true,
|
||||
@@ -104,25 +104,25 @@ func TestHost_Create(t *testing.T) {
|
||||
{
|
||||
name: "valid-duplicate-name-different-catalog",
|
||||
args: args{
|
||||
catalogId: cat2.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
catalogId: cat2.GetPublicId(),
|
||||
externalId: "valid-duplicate-name-different-catalog",
|
||||
opts: []Option{
|
||||
WithName("test-name"),
|
||||
},
|
||||
},
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
CatalogId: cat2.GetPublicId(),
|
||||
Address: "foo.bar.com",
|
||||
Name: "test-name",
|
||||
CatalogId: cat2.GetPublicId(),
|
||||
ExternalId: "valid-duplicate-name-different-catalog",
|
||||
Name: "test-name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-with-description",
|
||||
args: args{
|
||||
catalogId: cat.GetPublicId(),
|
||||
address: "foo.bar.com",
|
||||
catalogId: cat.GetPublicId(),
|
||||
externalId: "valid-with-description",
|
||||
opts: []Option{
|
||||
WithDescription("test-description"),
|
||||
},
|
||||
@@ -130,7 +130,7 @@ func TestHost_Create(t *testing.T) {
|
||||
want: &Host{
|
||||
Host: &store.Host{
|
||||
CatalogId: cat.GetPublicId(),
|
||||
Address: "foo.bar.com",
|
||||
ExternalId: "valid-with-description",
|
||||
Description: "test-description",
|
||||
},
|
||||
},
|
||||
@@ -141,7 +141,7 @@ func TestHost_Create(t *testing.T) {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
got := newHost(ctx, tt.args.catalogId, tt.args.address, tt.args.opts...)
|
||||
got := newHost(ctx, tt.args.catalogId, tt.args.externalId, tt.args.opts...)
|
||||
require.NotNil(t, got)
|
||||
assert.Emptyf(t, got.PublicId, "PublicId set")
|
||||
assert.Equal(t, tt.want, got)
|
||||
@@ -163,6 +163,9 @@ func TestHost_Create(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Test Deletion directly of host, of set membership, and of cascading
|
||||
// from the set
|
||||
|
||||
func TestHost_SetTableName(t *testing.T) {
|
||||
defaultTableName := "host_plugin_host"
|
||||
tests := []struct {
|
||||
@@ -200,3 +203,15 @@ func TestHost_SetTableName(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func testHost(t *testing.T, conn *db.DB, catId, externId string) *Host {
|
||||
t.Helper()
|
||||
w := db.New(conn)
|
||||
ctx := context.Background()
|
||||
host1 := newHost(ctx, catId, externId)
|
||||
var err error
|
||||
host1.PublicId, err = newHostId(ctx, catId, externId)
|
||||
require.NoError(t, err)
|
||||
require.NoError(t, w.Create(ctx, host1))
|
||||
return host1
|
||||
}
|
||||
@@ -16,11 +16,15 @@ type Option func(*options)
|
||||
|
||||
// options = how options are represented
|
||||
type options struct {
|
||||
withPluginId string
|
||||
withName string
|
||||
withDescription string
|
||||
withAttributes *structpb.Struct
|
||||
withSecrets *structpb.Struct
|
||||
withPreferredEndpoints []string
|
||||
withIpAddresses []string
|
||||
withDnsNames []string
|
||||
withLimit int
|
||||
}
|
||||
|
||||
func getDefaultOptions() options {
|
||||
@@ -29,6 +33,13 @@ func getDefaultOptions() options {
|
||||
}
|
||||
}
|
||||
|
||||
// WithPluginId provides an optional plugin id.
|
||||
func withPluginId(with string) Option {
|
||||
return func(o *options) {
|
||||
o.withPluginId = with
|
||||
}
|
||||
}
|
||||
|
||||
// WithDescription provides an optional description.
|
||||
func WithDescription(desc string) Option {
|
||||
return func(o *options) {
|
||||
@@ -63,3 +74,26 @@ func WithPreferredEndpoints(with []string) Option {
|
||||
o.withPreferredEndpoints = with
|
||||
}
|
||||
}
|
||||
|
||||
// withIpAddresses provides an optional list of ip addresses.
|
||||
func withIpAddresses(with []string) Option {
|
||||
return func(o *options) {
|
||||
o.withIpAddresses = with
|
||||
}
|
||||
}
|
||||
|
||||
// withDnsNames provides an optional list of dns names.
|
||||
func withDnsNames(with []string) Option {
|
||||
return func(o *options) {
|
||||
o.withDnsNames = with
|
||||
}
|
||||
}
|
||||
|
||||
// WithLimit provides an option to provide a limit. Intentionally allowing
|
||||
// negative integers. If WithLimit < 0, then unlimited results are
|
||||
// returned. If WithLimit == 0, then default limits are used for results.
|
||||
func WithLimit(l int) Option {
|
||||
return func(o *options) {
|
||||
o.withLimit = l
|
||||
}
|
||||
}
|
||||
@@ -14,16 +14,40 @@ func Test_GetOpts(t *testing.T) {
|
||||
testOpts.withName = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithPluginId", func(t *testing.T) {
|
||||
opts := getOpts(withPluginId("test"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withPluginId = "test"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithDescription", func(t *testing.T) {
|
||||
opts := getOpts(WithDescription("test desc"))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withDescription = "test desc"
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithLimit", func(t *testing.T) {
|
||||
opts := getOpts(WithLimit(5))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withLimit = 5
|
||||
assert.Equal(t, opts, testOpts)
|
||||
})
|
||||
t.Run("WithPreferredEndpoints", func(t *testing.T) {
|
||||
opts := getOpts(WithPreferredEndpoints([]string{"foo"}))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withPreferredEndpoints = []string{"foo"}
|
||||
assert.EqualValues(t, opts, testOpts)
|
||||
})
|
||||
t.Run("withDnsNames", func(t *testing.T) {
|
||||
opts := getOpts(withDnsNames([]string{"foo"}))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withDnsNames = []string{"foo"}
|
||||
assert.EqualValues(t, opts, testOpts)
|
||||
})
|
||||
t.Run("withIpAddresses", func(t *testing.T) {
|
||||
opts := getOpts(withIpAddresses([]string{"foo"}))
|
||||
testOpts := getDefaultOptions()
|
||||
testOpts.withIpAddresses = []string{"foo"}
|
||||
assert.EqualValues(t, opts, testOpts)
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,284 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
)
|
||||
|
||||
// UpsertHost inserts phs into the repository or updates its current
|
||||
// attributes/set memberships and returns Hosts. h is not changed. hc must
|
||||
// contain a valid public ID and scope ID. Each ph in phs must not contain a
|
||||
// PublicId but must contain an external ID. The PublicId is generated and
|
||||
// assigned by this method.
|
||||
//
|
||||
// NOTE: If phs is empty, this assumes that there are simply no hosts that
|
||||
// matched the given sets! Which means it will remove all hosts from the given
|
||||
// sets.
|
||||
func (r *Repository) UpsertHosts(
|
||||
ctx context.Context,
|
||||
hc *HostCatalog,
|
||||
sets []string,
|
||||
phs []*plgpb.ListHostsResponseHost,
|
||||
_ ...Option) ([]*Host, error) {
|
||||
const op = "plugin.(Repository).UpsertHosts"
|
||||
if phs == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "nil plugin hosts")
|
||||
}
|
||||
for _, ph := range phs {
|
||||
if ph.GetExternalId() == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "missing host external id")
|
||||
}
|
||||
}
|
||||
if hc == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "nil host catalog")
|
||||
}
|
||||
if hc.GetPublicId() == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no catalog id")
|
||||
}
|
||||
if hc.GetScopeId() == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no scope id")
|
||||
}
|
||||
if sets == nil {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "nil sets")
|
||||
}
|
||||
if len(sets) == 0 { // At least one must have been given to the plugin
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "empty sets")
|
||||
}
|
||||
|
||||
// hostInfo stores the info we need for the transaction below as well as
|
||||
// which sets they matched
|
||||
type hostInfo struct {
|
||||
h *Host
|
||||
ips []interface{}
|
||||
dnsNames []interface{}
|
||||
sets map[string]struct{}
|
||||
}
|
||||
hostMapping := make(map[string]hostInfo, len(phs))
|
||||
var err error
|
||||
var totalMsgs uint32
|
||||
|
||||
for _, ph := range phs {
|
||||
totalMsgs += 2 // delete and create
|
||||
|
||||
h := newHost(ctx,
|
||||
hc.GetPublicId(),
|
||||
ph.GetExternalId(),
|
||||
withIpAddresses(ph.GetIpAddresses()),
|
||||
withDnsNames(ph.GetDnsNames()),
|
||||
withPluginId(hc.GetPluginId()))
|
||||
h.PublicId, err = newHostId(ctx, hc.GetPublicId(), ph.GetExternalId())
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
|
||||
var ipAddresses []interface{}
|
||||
if len(h.GetIpAddresses()) > 0 {
|
||||
sort.Strings(h.IpAddresses)
|
||||
ipAddresses = make([]interface{}, 0, len(h.GetIpAddresses()))
|
||||
for i, a := range h.GetIpAddresses() {
|
||||
obj, err := host.NewIpAddress(ctx, h.PublicId, uint32(i+1), a)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
ipAddresses = append(ipAddresses, obj)
|
||||
}
|
||||
}
|
||||
|
||||
var dnsNames []interface{}
|
||||
if len(h.GetDnsNames()) > 0 {
|
||||
sort.Strings(h.DnsNames)
|
||||
dnsNames = make([]interface{}, 0, len(h.GetDnsNames()))
|
||||
for i, n := range h.GetDnsNames() {
|
||||
obj, err := host.NewDnsName(ctx, h.PublicId, uint32(i+1), n)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
dnsNames = append(dnsNames, obj)
|
||||
}
|
||||
}
|
||||
|
||||
hi := hostInfo{
|
||||
h: h,
|
||||
ips: ipAddresses,
|
||||
dnsNames: dnsNames,
|
||||
}
|
||||
|
||||
for _, id := range ph.GetSetIds() {
|
||||
if hi.sets == nil {
|
||||
hi.sets = make(map[string]struct{})
|
||||
}
|
||||
hi.sets[id] = struct{}{}
|
||||
}
|
||||
|
||||
hostMapping[h.PublicId] = hi
|
||||
|
||||
totalMsgs += uint32(len(ipAddresses) + len(dnsNames))
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, hc.GetScopeId(), kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var returnedHosts []*Host
|
||||
|
||||
// Here's what this function does: first it deletes a host, which causes
|
||||
// cascading deletes on ip addresses and dns names (but all within the DB).
|
||||
// Then the host is recreated, which uses the same public ID (since it's
|
||||
// based on the host catalog/external ID), along with new/updated
|
||||
// information.
|
||||
//
|
||||
// If we ever do start allowing hosts directly in targets this may cause a
|
||||
// problem because the host deletion would probably cascade to the target
|
||||
// and remove it from the target host sources, but at this point there are
|
||||
// several issues with that scenario so it's not soon...
|
||||
//
|
||||
// The main reason I'm doing it this way is because I'm not sure how to do
|
||||
// oplogs with custom queries. Otherwise a custom insert/on conflict query
|
||||
// could replace the initial deletion. @jimlambrt @mgaffney help? :-D
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
db.StdRetryCnt,
|
||||
db.ExpBackoff{},
|
||||
func(r db.Reader, w db.Writer) error {
|
||||
// FIXME: We need to ensure hosts no longer found have their
|
||||
// memberships removed. To do this, first list all set memberships.
|
||||
// This is waiting on membership to be plumbed through to gorm,
|
||||
// which in turn is waiting on figuring out whether or not we can
|
||||
// share that between static and plugin.
|
||||
//
|
||||
// Next, for each set, check whether a given host ID is in the
|
||||
// hostMapping and if so, if the set ID is in the host's sets. If
|
||||
// not, queue that membership entry for deletion.
|
||||
msgs := make([]*oplog.Message, 0, totalMsgs+3)
|
||||
ticket, err := w.GetTicket(hc)
|
||||
if err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to get ticket"))
|
||||
}
|
||||
|
||||
for _, hi := range hostMapping {
|
||||
ret := hi.h.clone()
|
||||
|
||||
var hOplogMsg oplog.Message
|
||||
// We don't need to check whether something was deleted because
|
||||
// it's okay if it fails
|
||||
if _, err := w.Delete(ctx, ret, db.NewOplogMsg(&hOplogMsg)); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
msgs = append(msgs, &hOplogMsg)
|
||||
|
||||
hOplogMsg = oplog.Message{}
|
||||
if err := w.Create(ctx, ret, db.NewOplogMsg(&hOplogMsg)); err != nil {
|
||||
return errors.Wrap(ctx, err, op)
|
||||
}
|
||||
msgs = append(msgs, &hOplogMsg)
|
||||
|
||||
if len(hi.ips) > 0 {
|
||||
ipOplogMsgs := make([]*oplog.Message, 0, len(hi.ips))
|
||||
if err := w.CreateItems(ctx, hi.ips, db.NewOplogMsgs(&ipOplogMsgs)); err != nil {
|
||||
return err
|
||||
}
|
||||
msgs = append(msgs, ipOplogMsgs...)
|
||||
}
|
||||
|
||||
if len(hi.dnsNames) > 0 {
|
||||
dnsOplogMsgs := make([]*oplog.Message, 0, len(hi.dnsNames))
|
||||
if err := w.CreateItems(ctx, hi.dnsNames, db.NewOplogMsgs(&dnsOplogMsgs)); err != nil {
|
||||
return err
|
||||
}
|
||||
msgs = append(msgs, dnsOplogMsgs...)
|
||||
}
|
||||
|
||||
// FIXME: Add set memberships here
|
||||
|
||||
returnedHosts = append(returnedHosts, ret)
|
||||
}
|
||||
|
||||
metadata := hc.oplog(oplog.OpType_OP_TYPE_CREATE)
|
||||
if err := w.WriteOplogEntryWith(ctx, oplogWrapper, ticket, metadata, msgs); err != nil {
|
||||
return errors.Wrap(ctx, err, op, errors.WithMsg("unable to write oplog"))
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
if errors.IsCheckConstraintError(err) || errors.IsNotNullError(err) {
|
||||
return nil, errors.New(ctx,
|
||||
errors.InvalidAddress,
|
||||
op,
|
||||
fmt.Sprintf("in catalog: %s", hc.GetPublicId()),
|
||||
errors.WithWrap(err),
|
||||
)
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("in catalog: %s", hc.PublicId)))
|
||||
}
|
||||
return returnedHosts, nil
|
||||
}
|
||||
|
||||
// LookupHost will look up a host in the repository. If the host is not
|
||||
// found, it will return nil, nil. All options are ignored.
|
||||
func (r *Repository) LookupHost(ctx context.Context, publicId string, opt ...Option) (*Host, error) {
|
||||
const op = "plugin.(Repository).LookupHost"
|
||||
if publicId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no public id")
|
||||
}
|
||||
ha := &hostAgg{
|
||||
PublicId: publicId,
|
||||
}
|
||||
if err := r.reader.LookupByPublicId(ctx, ha); err != nil {
|
||||
if errors.IsNotFoundError(err) {
|
||||
return nil, nil
|
||||
}
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed for %s", publicId)))
|
||||
}
|
||||
h, err := ha.toHost(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op, errors.WithMsg(fmt.Sprintf("failed to convert host agg for %s", publicId)))
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
||||
// ListHosts returns a slice of Hosts for the catalogId.
|
||||
// WithLimit is the only option supported.
|
||||
func (r *Repository) ListHosts(ctx context.Context, catalogId string, opt ...Option) ([]*Host, error) {
|
||||
const op = "plugin.(Repository).ListHosts"
|
||||
if catalogId == "" {
|
||||
return nil, errors.New(ctx, errors.InvalidParameter, op, "no catalog id")
|
||||
}
|
||||
opts := getOpts(opt...)
|
||||
limit := r.defaultLimit
|
||||
if opts.withLimit != 0 {
|
||||
// non-zero signals an override of the default limit for the repo.
|
||||
limit = opts.withLimit
|
||||
}
|
||||
var hostAggs []*hostAgg
|
||||
err := r.reader.SearchWhere(ctx, &hostAggs, "catalog_id = ?", []interface{}{catalogId}, db.WithLimit(limit))
|
||||
|
||||
switch {
|
||||
case err != nil:
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
case hostAggs == nil:
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
hosts := make([]*Host, 0, len(hostAggs))
|
||||
for _, ha := range hostAggs {
|
||||
host, err := ha.toHost(ctx)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(ctx, err, op)
|
||||
}
|
||||
hosts = append(hosts, host)
|
||||
}
|
||||
|
||||
return hosts, nil
|
||||
}
|
||||
@@ -87,11 +87,6 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet,
|
||||
}
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var preferredEndpoints []interface{}
|
||||
if s.PreferredEndpoints != nil {
|
||||
preferredEndpoints = make([]interface{}, 0, len(s.PreferredEndpoints))
|
||||
@@ -104,6 +99,11 @@ func (r *Repository) CreateSet(ctx context.Context, scopeId string, s *HostSet,
|
||||
}
|
||||
}
|
||||
|
||||
oplogWrapper, err := r.kms.GetWrapper(ctx, scopeId, kms.KeyPurposeOplog)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(ctx, err, op, errors.WithMsg("unable to get oplog wrapper"))
|
||||
}
|
||||
|
||||
var returnedHostSet *HostSet
|
||||
_, err = r.writer.DoTx(
|
||||
ctx,
|
||||
@@ -185,6 +185,7 @@ func (r *Repository) LookupSet(ctx context.Context, publicId string, opt ...host
|
||||
setToReturn := sets[0]
|
||||
var hostIdsToReturn []string
|
||||
|
||||
// FIXME: change to use the database
|
||||
if plg != nil && opts.WithSetMembers {
|
||||
cat, err := r.getCatalog(ctx, setToReturn.GetCatalogId())
|
||||
if err != nil {
|
||||
|
||||
@@ -489,16 +489,15 @@ func TestRepository_Endpoints(t *testing.T) {
|
||||
})
|
||||
assert.Empty(cmp.Diff(got, tt.want, protocmp.Transform()))
|
||||
|
||||
// TODO: Remove this once we no longer persist all host lookup calls
|
||||
// when retrieving the endpoints.
|
||||
for _, ep := range got {
|
||||
h := allocHost()
|
||||
h.PublicId = ep.HostId
|
||||
require.NoError(rw.LookupByPublicId(ctx, h))
|
||||
|
||||
assert.Equal(uint32(1), h.Version)
|
||||
assert.Equal(ep.HostId, h.PublicId)
|
||||
assert.Equal(ep.Address, h.Address)
|
||||
// TODO: Uncomment when we have a better way to lookup host
|
||||
// with it's address
|
||||
// assert.Equal(ep.Address, h.Address)
|
||||
assert.Equal(catalog.GetPublicId(), h.GetCatalogId())
|
||||
}
|
||||
})
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/db/timestamp"
|
||||
"github.com/hashicorp/boundary/internal/errors"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/iam"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/oplog"
|
||||
hostplg "github.com/hashicorp/boundary/internal/plugin/host"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestRepository_UpsertHosts(t *testing.T) {
|
||||
ctx := context.Background()
|
||||
conn, _ := db.TestSetup(t, "postgres")
|
||||
rw := db.New(conn)
|
||||
wrapper := db.TestWrapper(t)
|
||||
kms := kms.TestKms(t, conn, wrapper)
|
||||
iamRepo := iam.TestRepo(t, conn, wrapper)
|
||||
_, prj := iam.TestScopes(t, iamRepo)
|
||||
|
||||
plg := hostplg.TestPlugin(t, conn, "create")
|
||||
plgm := map[string]plgpb.HostPluginServiceClient{
|
||||
plg.GetPublicId(): NewWrappingPluginClient(&plgpb.UnimplementedHostPluginServiceServer{}),
|
||||
}
|
||||
|
||||
catalog := TestCatalog(t, conn, prj.PublicId, plg.GetPublicId())
|
||||
const setCount int = 3
|
||||
setIds := make([]string, 0, setCount)
|
||||
for i := 0; i < setCount; i++ {
|
||||
set := TestSet(t, conn, kms, catalog, plgm)
|
||||
setIds = append(setIds, set.GetPublicId())
|
||||
}
|
||||
phs, exp := TestExternalHosts(t, catalog, setIds, setCount)
|
||||
|
||||
type input struct {
|
||||
catalog *HostCatalog
|
||||
sets []string
|
||||
phs []*plgpb.ListHostsResponseHost
|
||||
exp []*Host
|
||||
}
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
in func() *input
|
||||
opts []Option
|
||||
wantIsErr errors.Code
|
||||
}{
|
||||
{
|
||||
name: "nil-hosts",
|
||||
in: func() *input {
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
sets: setIds,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-external-id-hosts",
|
||||
in: func() *input {
|
||||
testPhs, _ := TestExternalHosts(t, catalog, setIds, setCount)
|
||||
testPhs[1].ExternalId = ""
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
sets: setIds,
|
||||
phs: testPhs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-catalog",
|
||||
in: func() *input {
|
||||
return &input{
|
||||
sets: setIds,
|
||||
phs: phs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-catalog-id",
|
||||
in: func() *input {
|
||||
cat := catalog.clone()
|
||||
cat.PublicId = ""
|
||||
return &input{
|
||||
catalog: cat,
|
||||
sets: setIds,
|
||||
phs: phs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-scope-id",
|
||||
in: func() *input {
|
||||
cat := catalog.clone()
|
||||
cat.ScopeId = ""
|
||||
return &input{
|
||||
catalog: cat,
|
||||
sets: setIds,
|
||||
phs: phs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "nil-sets",
|
||||
in: func() *input {
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
phs: phs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "no-sets",
|
||||
in: func() *input {
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
sets: make([]string, 0),
|
||||
phs: phs,
|
||||
}
|
||||
},
|
||||
wantIsErr: errors.InvalidParameter,
|
||||
},
|
||||
{
|
||||
name: "valid",
|
||||
in: func() *input {
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
sets: setIds,
|
||||
phs: phs,
|
||||
exp: exp,
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "valid-changed-values",
|
||||
in: func() *input {
|
||||
ph := phs[1]
|
||||
e := exp[1]
|
||||
newIp := testGetIpAddress(t)
|
||||
newName := testGetDnsName(t)
|
||||
ph.IpAddresses = append(ph.IpAddresses, newIp)
|
||||
e.IpAddresses = append(e.IpAddresses, newIp)
|
||||
ph.DnsNames = append(ph.DnsNames, newName)
|
||||
e.DnsNames = append(e.DnsNames, newName)
|
||||
// These are sorted by the repo function, so we need to match
|
||||
sort.Strings(e.IpAddresses)
|
||||
sort.Strings(e.DnsNames)
|
||||
|
||||
ph.SetIds = ph.SetIds[0 : len(ph.SetIds)-1]
|
||||
return &input{
|
||||
catalog: catalog,
|
||||
sets: setIds,
|
||||
phs: phs,
|
||||
exp: exp,
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
tt := tt
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
assert, require := assert.New(t), require.New(t)
|
||||
repo, err := NewRepository(rw, rw, kms, plgm)
|
||||
require.NoError(err)
|
||||
require.NotNil(repo)
|
||||
in := tt.in()
|
||||
got, err := repo.UpsertHosts(ctx, in.catalog, in.sets, in.phs, tt.opts...)
|
||||
if tt.wantIsErr != 0 {
|
||||
assert.Truef(errors.Match(errors.T(tt.wantIsErr), err), "want err: %q got: %q", tt.wantIsErr, err)
|
||||
assert.Nil(got)
|
||||
return
|
||||
}
|
||||
require.NoError(err, fmt.Sprintf("%v", in.catalog))
|
||||
require.NotNil(got)
|
||||
|
||||
// Basic tests
|
||||
assert.Len(got, len(in.phs))
|
||||
assert.NoError(db.TestVerifyOplog(t, rw, in.catalog.GetPublicId(), db.WithOperation(oplog.OpType_OP_TYPE_CREATE), db.WithCreateNotBefore(10*time.Second)))
|
||||
|
||||
// Make sure outputs match. Ignore timestamps.
|
||||
assert.Empty(
|
||||
cmp.Diff(
|
||||
in.exp,
|
||||
got,
|
||||
cmpopts.IgnoreUnexported(Host{}, store.Host{}),
|
||||
cmpopts.IgnoreTypes(×tamp.Timestamp{}),
|
||||
cmpopts.SortSlices(func(x, y *Host) bool {
|
||||
return x.GetPublicId() < y.GetPublicId()
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
// Check again, but via performing an explicit list
|
||||
got, err = repo.ListHosts(ctx, in.catalog.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
assert.Len(got, len(in.phs))
|
||||
assert.Empty(
|
||||
cmp.Diff(
|
||||
in.exp,
|
||||
got,
|
||||
cmpopts.IgnoreUnexported(Host{}, store.Host{}),
|
||||
cmpopts.IgnoreTypes(×tamp.Timestamp{}),
|
||||
cmpopts.SortSlices(func(x, y *Host) bool {
|
||||
return x.GetPublicId() < y.GetPublicId()
|
||||
}),
|
||||
),
|
||||
)
|
||||
|
||||
// Now individually call read on each host
|
||||
for _, exp := range in.exp {
|
||||
got, err := repo.LookupHost(ctx, exp.GetPublicId())
|
||||
require.NoError(err)
|
||||
require.NotNil(got)
|
||||
assert.Empty(
|
||||
cmp.Diff(
|
||||
exp,
|
||||
got,
|
||||
cmpopts.IgnoreUnexported(Host{}, store.Host{}),
|
||||
cmpopts.IgnoreTypes(×tamp.Timestamp{}),
|
||||
),
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -155,127 +155,6 @@ func (x *HostCatalog) GetAttributes() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
type Host struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
PublicId string `protobuf:"bytes,1,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
|
||||
// The create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
CreateTime *timestamp.Timestamp `protobuf:"bytes,2,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// The update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
UpdateTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// name is optional. If set, it must be unique within
|
||||
// catalog_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Name string `protobuf:"bytes,4,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Description string `protobuf:"bytes,5,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
|
||||
// catalog_id is the public_id of the owning
|
||||
// plugin_host_catalog and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
CatalogId string `protobuf:"bytes,6,opt,name=catalog_id,json=catalogId,proto3" json:"catalog_id,omitempty" gorm:"not_null"`
|
||||
// version allows optimistic locking of the resource
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Version uint32 `protobuf:"varint,7,opt,name=version,proto3" json:"version,omitempty" gorm:"default:null"`
|
||||
// address is the IP Address or DNS name of the host.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Address string `protobuf:"bytes,8,opt,name=address,proto3" json:"address,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *Host) Reset() {
|
||||
*x = Host{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Host) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Host) ProtoMessage() {}
|
||||
|
||||
func (x *Host) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Host.ProtoReflect.Descriptor instead.
|
||||
func (*Host) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *Host) GetPublicId() string {
|
||||
if x != nil {
|
||||
return x.PublicId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetCreateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Host) GetUpdateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.UpdateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Host) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetCatalogId() string {
|
||||
if x != nil {
|
||||
return x.CatalogId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Host) GetAddress() string {
|
||||
if x != nil {
|
||||
return x.Address
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type HostSet struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
@@ -315,7 +194,7 @@ type HostSet struct {
|
||||
func (x *HostSet) Reset() {
|
||||
*x = HostSet{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2]
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[1]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -328,7 +207,7 @@ func (x *HostSet) String() string {
|
||||
func (*HostSet) ProtoMessage() {}
|
||||
|
||||
func (x *HostSet) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2]
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[1]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -341,7 +220,7 @@ func (x *HostSet) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use HostSet.ProtoReflect.Descriptor instead.
|
||||
func (*HostSet) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{2}
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{1}
|
||||
}
|
||||
|
||||
func (x *HostSet) GetPublicId() string {
|
||||
@@ -437,7 +316,7 @@ type HostCatalogSecret struct {
|
||||
func (x *HostCatalogSecret) Reset() {
|
||||
*x = HostCatalogSecret{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3]
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
@@ -450,7 +329,7 @@ func (x *HostCatalogSecret) String() string {
|
||||
func (*HostCatalogSecret) ProtoMessage() {}
|
||||
|
||||
func (x *HostCatalogSecret) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3]
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
@@ -463,7 +342,7 @@ func (x *HostCatalogSecret) ProtoReflect() protoreflect.Message {
|
||||
|
||||
// Deprecated: Use HostCatalogSecret.ProtoReflect.Descriptor instead.
|
||||
func (*HostCatalogSecret) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{3}
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{2}
|
||||
}
|
||||
|
||||
func (x *HostCatalogSecret) GetCatalogId() string {
|
||||
@@ -508,6 +387,216 @@ func (x *HostCatalogSecret) GetKeyId() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
// TODO: Add a field which tracks if the host in cache should be considered
|
||||
// invalid and fall back to the plugin provided data.
|
||||
type Host struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
PublicId string `protobuf:"bytes,1,opt,name=public_id,json=publicId,proto3" json:"public_id,omitempty" gorm:"primary_key"`
|
||||
// external_id is an id provided by the plugin.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
ExternalId string `protobuf:"bytes,2,opt,name=external_id,json=externalId,proto3" json:"external_id,omitempty" gorm:"not_null"`
|
||||
// The create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
CreateTime *timestamp.Timestamp `protobuf:"bytes,3,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// The update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
UpdateTime *timestamp.Timestamp `protobuf:"bytes,4,opt,name=update_time,json=updateTime,proto3" json:"update_time,omitempty" gorm:"default:current_timestamp"`
|
||||
// name is optional. If set, it must be unique within
|
||||
// catalog_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Name string `protobuf:"bytes,5,opt,name=name,proto3" json:"name,omitempty" gorm:"default:null"`
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
Description string `protobuf:"bytes,6,opt,name=description,proto3" json:"description,omitempty" gorm:"default:null"`
|
||||
// catalog_id is the public_id of the owning
|
||||
// plugin_host_catalog and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
CatalogId string `protobuf:"bytes,7,opt,name=catalog_id,json=catalogId,proto3" json:"catalog_id,omitempty" gorm:"not_null"`
|
||||
// @inject_tag: `gorm:"-"`
|
||||
Version uint32 `protobuf:"varint,8,opt,name=version,proto3" json:"version,omitempty" gorm:"-"`
|
||||
// ip_addresses are the ip addresses associated with this host and will
|
||||
// be persisted in the db through the HostAddress message.
|
||||
// @inject_tag: `gorm:"-"`
|
||||
IpAddresses []string `protobuf:"bytes,9,rep,name=ip_addresses,json=ipAddresses,proto3" json:"ip_addresses,omitempty" gorm:"-"`
|
||||
// dns_names are the dns names associated with this host and will
|
||||
// be persisted in the db through the HostAddress message.
|
||||
// @inject_tag: `gorm:"-"`
|
||||
DnsNames []string `protobuf:"bytes,10,rep,name=dns_names,json=dnsNames,proto3" json:"dns_names,omitempty" gorm:"-"`
|
||||
}
|
||||
|
||||
func (x *Host) Reset() {
|
||||
*x = Host{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Host) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*Host) ProtoMessage() {}
|
||||
|
||||
func (x *Host) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use Host.ProtoReflect.Descriptor instead.
|
||||
func (*Host) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{3}
|
||||
}
|
||||
|
||||
func (x *Host) GetPublicId() string {
|
||||
if x != nil {
|
||||
return x.PublicId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetExternalId() string {
|
||||
if x != nil {
|
||||
return x.ExternalId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetCreateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.CreateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Host) GetUpdateTime() *timestamp.Timestamp {
|
||||
if x != nil {
|
||||
return x.UpdateTime
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Host) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetDescription() string {
|
||||
if x != nil {
|
||||
return x.Description
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetCatalogId() string {
|
||||
if x != nil {
|
||||
return x.CatalogId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *Host) GetVersion() uint32 {
|
||||
if x != nil {
|
||||
return x.Version
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *Host) GetIpAddresses() []string {
|
||||
if x != nil {
|
||||
return x.IpAddresses
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *Host) GetDnsNames() []string {
|
||||
if x != nil {
|
||||
return x.DnsNames
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type HostSetMember struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
HostId string `protobuf:"bytes,1,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
SetId string `protobuf:"bytes,2,opt,name=set_id,json=setId,proto3" json:"set_id,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
CatalogId string `protobuf:"bytes,3,opt,name=catalog_id,json=catalogId,proto3" json:"catalog_id,omitempty" gorm:"default:null"`
|
||||
}
|
||||
|
||||
func (x *HostSetMember) Reset() {
|
||||
*x = HostSetMember{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *HostSetMember) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*HostSetMember) ProtoMessage() {}
|
||||
|
||||
func (x *HostSetMember) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use HostSetMember.ProtoReflect.Descriptor instead.
|
||||
func (*HostSetMember) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *HostSetMember) GetHostId() string {
|
||||
if x != nil {
|
||||
return x.HostId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HostSetMember) GetSetId() string {
|
||||
if x != nil {
|
||||
return x.SetId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *HostSetMember) GetCatalogId() string {
|
||||
if x != nil {
|
||||
return x.CatalogId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_controller_storage_host_plugin_store_v1_host_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_host_plugin_store_v1_host_proto_rawDesc = []byte{
|
||||
@@ -550,77 +639,88 @@ var file_controller_storage_host_plugin_store_v1_host_proto_rawDesc = []byte{
|
||||
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74,
|
||||
0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xc6, 0x02, 0x0a, 0x04, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12,
|
||||
0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02,
|
||||
0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x22, 0xb2, 0x03, 0x0a, 0x07, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63,
|
||||
0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||
0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d,
|
||||
0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12,
|
||||
0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03,
|
||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65,
|
||||
0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74,
|
||||
0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b,
|
||||
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75,
|
||||
0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d,
|
||||
0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a,
|
||||
0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12,
|
||||
0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x18,
|
||||
0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52,
|
||||
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72,
|
||||
0x65, 0x73, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65,
|
||||
0x73, 0x73, 0x22, 0xb2, 0x03, 0x0a, 0x07, 0x48, 0x6f, 0x73, 0x74, 0x53, 0x65, 0x74, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b,
|
||||
0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74,
|
||||
0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e,
|
||||
0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72,
|
||||
0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e,
|
||||
0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61,
|
||||
0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e,
|
||||
0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74,
|
||||
0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20,
|
||||
0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09,
|
||||
0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74,
|
||||
0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07,
|
||||
0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76,
|
||||
0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62,
|
||||
0x75, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72,
|
||||
0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a, 0x13, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72,
|
||||
0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20,
|
||||
0x03, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x45, 0x6e,
|
||||
0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x98, 0x02, 0x0a, 0x11, 0x48, 0x6f, 0x73, 0x74,
|
||||
0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1d, 0x0a,
|
||||
0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||
0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b,
|
||||
0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28,
|
||||
0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70,
|
||||
0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63,
|
||||
0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64,
|
||||
0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a,
|
||||
0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72,
|
||||
0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31,
|
||||
0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61,
|
||||
0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74,
|
||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b,
|
||||
0x0a, 0x09, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x08, 0x63, 0x74, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6b,
|
||||
0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79,
|
||||
0x49, 0x64, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d,
|
||||
0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64,
|
||||
0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x68, 0x6f, 0x73,
|
||||
0x74, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73,
|
||||
0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||
0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x24, 0x0a, 0x04,
|
||||
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x42, 0x10, 0xc2, 0xdd, 0x29, 0x0c,
|
||||
0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x52, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x12, 0x40, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f,
|
||||
0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x42, 0x1e, 0xc2, 0xdd, 0x29, 0x1a, 0x0a, 0x0b, 0x64,
|
||||
0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x64, 0x65, 0x73, 0x63,
|
||||
0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70,
|
||||
0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x07,
|
||||
0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a,
|
||||
0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28,
|
||||
0x0c, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x72, 0x69, 0x62, 0x75, 0x74, 0x65, 0x73, 0x12, 0x2f, 0x0a,
|
||||
0x13, 0x70, 0x72, 0x65, 0x66, 0x65, 0x72, 0x72, 0x65, 0x64, 0x5f, 0x65, 0x6e, 0x64, 0x70, 0x6f,
|
||||
0x69, 0x6e, 0x74, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52, 0x12, 0x70, 0x72, 0x65, 0x66,
|
||||
0x65, 0x72, 0x72, 0x65, 0x64, 0x45, 0x6e, 0x64, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x22, 0x98,
|
||||
0x02, 0x0a, 0x11, 0x48, 0x6f, 0x73, 0x74, 0x43, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x53, 0x65,
|
||||
0x63, 0x72, 0x65, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f,
|
||||
0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f,
|
||||
0x67, 0x49, 0x64, 0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72,
|
||||
0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69,
|
||||
0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65,
|
||||
0x12, 0x4b, 0x0a, 0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x52, 0x0a, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x16, 0x0a,
|
||||
0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x73,
|
||||
0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x74, 0x5f, 0x73, 0x65, 0x63, 0x72,
|
||||
0x65, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x08, 0x63, 0x74, 0x53, 0x65, 0x63, 0x72,
|
||||
0x65, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x05, 0x6b, 0x65, 0x79, 0x49, 0x64, 0x22, 0x8d, 0x03, 0x0a, 0x04, 0x48, 0x6f,
|
||||
0x73, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x69, 0x64, 0x18,
|
||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x49, 0x64, 0x12,
|
||||
0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x02,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64,
|
||||
0x12, 0x4b, 0x0a, 0x0b, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18,
|
||||
0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
||||
0x65, 0x72, 0x2e, 0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73,
|
||||
0x74, 0x61, 0x6d, 0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x52, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x4b, 0x0a,
|
||||
0x0b, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01,
|
||||
0x28, 0x0b, 0x32, 0x2a, 0x2e, 0x63, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c, 0x65, 0x72, 0x2e,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x2e, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d,
|
||||
0x70, 0x2e, 0x76, 0x31, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0a,
|
||||
0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61,
|
||||
0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20,
|
||||
0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e,
|
||||
0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x07,
|
||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x12,
|
||||
0x18, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x69, 0x70, 0x5f,
|
||||
0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x18, 0x09, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x0b, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x65, 0x73, 0x12, 0x1b, 0x0a, 0x09,
|
||||
0x64, 0x6e, 0x73, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0a, 0x20, 0x03, 0x28, 0x09, 0x52,
|
||||
0x08, 0x64, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x22, 0x5e, 0x0a, 0x0d, 0x48, 0x6f, 0x73,
|
||||
0x74, 0x53, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f,
|
||||
0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73,
|
||||
0x74, 0x49, 0x64, 0x12, 0x15, 0x0a, 0x06, 0x73, 0x65, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20,
|
||||
0x01, 0x28, 0x09, 0x52, 0x05, 0x73, 0x65, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61,
|
||||
0x74, 0x61, 0x6c, 0x6f, 0x67, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09,
|
||||
0x63, 0x61, 0x74, 0x61, 0x6c, 0x6f, 0x67, 0x49, 0x64, 0x42, 0x40, 0x5a, 0x3e, 0x67, 0x69, 0x74,
|
||||
0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72,
|
||||
0x70, 0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72,
|
||||
0x6e, 0x61, 0x6c, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x70, 0x6c, 0x75, 0x67, 0x69, 0x6e, 0x2f,
|
||||
0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f,
|
||||
0x74, 0x6f, 0x33,
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -635,23 +735,24 @@ func file_controller_storage_host_plugin_store_v1_host_proto_rawDescGZIP() []byt
|
||||
return file_controller_storage_host_plugin_store_v1_host_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_host_plugin_store_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_controller_storage_host_plugin_store_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||
var file_controller_storage_host_plugin_store_v1_host_proto_goTypes = []interface{}{
|
||||
(*HostCatalog)(nil), // 0: controller.storage.host.plugin.store.v1.HostCatalog
|
||||
(*Host)(nil), // 1: controller.storage.host.plugin.store.v1.Host
|
||||
(*HostSet)(nil), // 2: controller.storage.host.plugin.store.v1.HostSet
|
||||
(*HostCatalogSecret)(nil), // 3: controller.storage.host.plugin.store.v1.HostCatalogSecret
|
||||
(*timestamp.Timestamp)(nil), // 4: controller.storage.timestamp.v1.Timestamp
|
||||
(*HostSet)(nil), // 1: controller.storage.host.plugin.store.v1.HostSet
|
||||
(*HostCatalogSecret)(nil), // 2: controller.storage.host.plugin.store.v1.HostCatalogSecret
|
||||
(*Host)(nil), // 3: controller.storage.host.plugin.store.v1.Host
|
||||
(*HostSetMember)(nil), // 4: controller.storage.host.plugin.store.v1.HostSetMember
|
||||
(*timestamp.Timestamp)(nil), // 5: controller.storage.timestamp.v1.Timestamp
|
||||
}
|
||||
var file_controller_storage_host_plugin_store_v1_host_proto_depIdxs = []int32{
|
||||
4, // 0: controller.storage.host.plugin.store.v1.HostCatalog.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 1: controller.storage.host.plugin.store.v1.HostCatalog.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 2: controller.storage.host.plugin.store.v1.Host.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 3: controller.storage.host.plugin.store.v1.Host.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 4: controller.storage.host.plugin.store.v1.HostSet.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 5: controller.storage.host.plugin.store.v1.HostSet.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 6: controller.storage.host.plugin.store.v1.HostCatalogSecret.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
4, // 7: controller.storage.host.plugin.store.v1.HostCatalogSecret.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 0: controller.storage.host.plugin.store.v1.HostCatalog.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 1: controller.storage.host.plugin.store.v1.HostCatalog.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 2: controller.storage.host.plugin.store.v1.HostSet.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 3: controller.storage.host.plugin.store.v1.HostSet.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 4: controller.storage.host.plugin.store.v1.HostCatalogSecret.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 5: controller.storage.host.plugin.store.v1.HostCatalogSecret.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 6: controller.storage.host.plugin.store.v1.Host.create_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
5, // 7: controller.storage.host.plugin.store.v1.Host.update_time:type_name -> controller.storage.timestamp.v1.Timestamp
|
||||
8, // [8:8] is the sub-list for method output_type
|
||||
8, // [8:8] is the sub-list for method input_type
|
||||
8, // [8:8] is the sub-list for extension type_name
|
||||
@@ -678,18 +779,6 @@ func file_controller_storage_host_plugin_store_v1_host_proto_init() {
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Host); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HostSet); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@@ -701,7 +790,7 @@ func file_controller_storage_host_plugin_store_v1_host_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HostCatalogSecret); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
@@ -713,6 +802,30 @@ func file_controller_storage_host_plugin_store_v1_host_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*Host); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_plugin_store_v1_host_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*HostSetMember); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@@ -720,7 +833,7 @@ func file_controller_storage_host_plugin_store_v1_host_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_host_plugin_store_v1_host_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumMessages: 5,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -2,12 +2,18 @@ package plugin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/hashicorp/boundary/internal/db"
|
||||
"github.com/hashicorp/boundary/internal/host/plugin/store"
|
||||
"github.com/hashicorp/boundary/internal/kms"
|
||||
"github.com/hashicorp/boundary/internal/plugin/host"
|
||||
plgpb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-secure-stdlib/base62"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
@@ -67,6 +73,65 @@ func TestSet(t *testing.T, conn *db.DB, kmsCache *kms.Kms, hc *HostCatalog, plgm
|
||||
return set
|
||||
}
|
||||
|
||||
func TestExternalHosts(t *testing.T, catalog *HostCatalog, setIds []string, count int) ([]*plgpb.ListHostsResponseHost, []*Host) {
|
||||
t.Helper()
|
||||
require := require.New(t)
|
||||
retRH := make([]*plgpb.ListHostsResponseHost, 0, count)
|
||||
retH := make([]*Host, 0, count)
|
||||
|
||||
for i := 0; i < count; i++ {
|
||||
externalId, err := base62.Random(10)
|
||||
require.NoError(err)
|
||||
|
||||
ipStr := testGetIpAddress(t)
|
||||
dnsName := testGetDnsName(t)
|
||||
|
||||
retRH = append(retRH, &plgpb.ListHostsResponseHost{
|
||||
ExternalId: externalId,
|
||||
SetIds: setIds,
|
||||
IpAddresses: []string{ipStr},
|
||||
DnsNames: []string{dnsName},
|
||||
})
|
||||
|
||||
publicId, err := newHostId(context.Background(), catalog.PublicId, externalId)
|
||||
require.NoError(err)
|
||||
|
||||
retH = append(retH, &Host{
|
||||
PluginId: catalog.PluginId,
|
||||
Host: &store.Host{
|
||||
CatalogId: catalog.PublicId,
|
||||
PublicId: publicId,
|
||||
ExternalId: externalId,
|
||||
IpAddresses: []string{ipStr},
|
||||
DnsNames: []string{dnsName},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
return retRH, retH
|
||||
}
|
||||
|
||||
func testGetDnsName(t *testing.T) string {
|
||||
dnsName, err := base62.Random(10)
|
||||
require.NoError(t, err)
|
||||
return fmt.Sprintf("%s.example.com", dnsName)
|
||||
}
|
||||
|
||||
func testGetIpAddress(t *testing.T) string {
|
||||
ipBytes := make([]byte, 4)
|
||||
for {
|
||||
lr := io.LimitReader(rand.Reader, 4)
|
||||
n, err := lr.Read(ipBytes)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, n, 4)
|
||||
ip := net.IP(ipBytes)
|
||||
v4 := ip.To4()
|
||||
if v4 != nil {
|
||||
return v4.String()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var _ plgpb.HostPluginServiceServer = (*TestPluginServer)(nil)
|
||||
|
||||
// TestPluginServer provides a host plugin service server where each method can be overwritten for tests.
|
||||
|
||||
@@ -38,6 +38,16 @@ func NewHost(catalogId string, opt ...Option) (*Host, error) {
|
||||
return host, nil
|
||||
}
|
||||
|
||||
// For compatibility with the general Host type
|
||||
func (h *Host) GetIpAddresses() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// For compatibility with the general Host type
|
||||
func (h *Host) GetDnsNames() []string {
|
||||
return nil
|
||||
}
|
||||
|
||||
// TableName returns the table name for the host.
|
||||
func (h *Host) TableName() string {
|
||||
if h.tableName != "" {
|
||||
|
||||
@@ -100,8 +100,11 @@ func updateVersion(ctx context.Context, w db.Writer, wrapper wrapping.Wrapper, m
|
||||
switch {
|
||||
case err != nil:
|
||||
return errors.Wrap(ctx, err, op)
|
||||
case rowsUpdated == 0:
|
||||
return errors.New(ctx, errors.RecordNotFound, op, "no matching version for host set found")
|
||||
case rowsUpdated > 1:
|
||||
return errors.New(ctx, errors.MultipleRecords, op, "more than 1 resource would have been updated")
|
||||
|
||||
}
|
||||
msgs = append(msgs, setMsg)
|
||||
|
||||
|
||||
@@ -268,6 +268,138 @@ func (x *PreferredEndpoint) GetCondition() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
type IpAddress struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
HostId string `protobuf:"bytes,1,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
Priority uint32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"not_null`
|
||||
Address string `protobuf:"bytes,3,opt,name=address,proto3" json:"address,omitempty"`
|
||||
}
|
||||
|
||||
func (x *IpAddress) Reset() {
|
||||
*x = IpAddress{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_store_v1_host_proto_msgTypes[4]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *IpAddress) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*IpAddress) ProtoMessage() {}
|
||||
|
||||
func (x *IpAddress) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_store_v1_host_proto_msgTypes[4]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use IpAddress.ProtoReflect.Descriptor instead.
|
||||
func (*IpAddress) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_store_v1_host_proto_rawDescGZIP(), []int{4}
|
||||
}
|
||||
|
||||
func (x *IpAddress) GetHostId() string {
|
||||
if x != nil {
|
||||
return x.HostId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *IpAddress) GetPriority() uint32 {
|
||||
if x != nil {
|
||||
return x.Priority
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *IpAddress) GetAddress() string {
|
||||
if x != nil {
|
||||
return x.Address
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
type DnsName struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
unknownFields protoimpl.UnknownFields
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
HostId string `protobuf:"bytes,1,opt,name=host_id,json=hostId,proto3" json:"host_id,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
Priority uint32 `protobuf:"varint,2,opt,name=priority,proto3" json:"priority,omitempty" gorm:"primary_key"`
|
||||
// @inject_tag: `gorm:"not_null`
|
||||
Name string `protobuf:"bytes,3,opt,name=name,proto3" json:"name,omitempty"`
|
||||
}
|
||||
|
||||
func (x *DnsName) Reset() {
|
||||
*x = DnsName{}
|
||||
if protoimpl.UnsafeEnabled {
|
||||
mi := &file_controller_storage_host_store_v1_host_proto_msgTypes[5]
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
}
|
||||
|
||||
func (x *DnsName) String() string {
|
||||
return protoimpl.X.MessageStringOf(x)
|
||||
}
|
||||
|
||||
func (*DnsName) ProtoMessage() {}
|
||||
|
||||
func (x *DnsName) ProtoReflect() protoreflect.Message {
|
||||
mi := &file_controller_storage_host_store_v1_host_proto_msgTypes[5]
|
||||
if protoimpl.UnsafeEnabled && x != nil {
|
||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
||||
if ms.LoadMessageInfo() == nil {
|
||||
ms.StoreMessageInfo(mi)
|
||||
}
|
||||
return ms
|
||||
}
|
||||
return mi.MessageOf(x)
|
||||
}
|
||||
|
||||
// Deprecated: Use DnsName.ProtoReflect.Descriptor instead.
|
||||
func (*DnsName) Descriptor() ([]byte, []int) {
|
||||
return file_controller_storage_host_store_v1_host_proto_rawDescGZIP(), []int{5}
|
||||
}
|
||||
|
||||
func (x *DnsName) GetHostId() string {
|
||||
if x != nil {
|
||||
return x.HostId
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func (x *DnsName) GetPriority() uint32 {
|
||||
if x != nil {
|
||||
return x.Priority
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func (x *DnsName) GetName() string {
|
||||
if x != nil {
|
||||
return x.Name
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
var File_controller_storage_host_store_v1_host_proto protoreflect.FileDescriptor
|
||||
|
||||
var file_controller_storage_host_store_v1_host_proto_rawDesc = []byte{
|
||||
@@ -295,7 +427,18 @@ var file_controller_storage_host_store_v1_host_proto_rawDesc = []byte{
|
||||
0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f,
|
||||
0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63,
|
||||
0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68,
|
||||
0x6f, 0x6e, 0x64, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5a, 0x0a, 0x09, 0x49, 0x70, 0x41, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64,
|
||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a,
|
||||
0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d,
|
||||
0x52, 0x08, 0x70, 0x72, 0x69, 0x6f, 0x72, 0x69, 0x74, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64,
|
||||
0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64,
|
||||
0x72, 0x65, 0x73, 0x73, 0x22, 0x52, 0x0a, 0x07, 0x44, 0x6e, 0x73, 0x4e, 0x61, 0x6d, 0x65, 0x12,
|
||||
0x17, 0x0a, 0x07, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||
0x52, 0x06, 0x68, 0x6f, 0x73, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x69, 0x6f,
|
||||
0x72, 0x69, 0x74, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x70, 0x72, 0x69, 0x6f,
|
||||
0x72, 0x69, 0x74, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01,
|
||||
0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x42, 0x39, 0x5a, 0x37, 0x67, 0x69, 0x74, 0x68,
|
||||
0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x61, 0x73, 0x68, 0x69, 0x63, 0x6f, 0x72, 0x70,
|
||||
0x2f, 0x62, 0x6f, 0x75, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e,
|
||||
0x61, 0x6c, 0x2f, 0x68, 0x6f, 0x73, 0x74, 0x2f, 0x73, 0x74, 0x6f, 0x72, 0x65, 0x3b, 0x73, 0x74,
|
||||
@@ -314,12 +457,14 @@ func file_controller_storage_host_store_v1_host_proto_rawDescGZIP() []byte {
|
||||
return file_controller_storage_host_store_v1_host_proto_rawDescData
|
||||
}
|
||||
|
||||
var file_controller_storage_host_store_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 4)
|
||||
var file_controller_storage_host_store_v1_host_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
||||
var file_controller_storage_host_store_v1_host_proto_goTypes = []interface{}{
|
||||
(*Catalog)(nil), // 0: controller.storage.host.store.v1.Catalog
|
||||
(*Host)(nil), // 1: controller.storage.host.store.v1.Host
|
||||
(*Set)(nil), // 2: controller.storage.host.store.v1.Set
|
||||
(*PreferredEndpoint)(nil), // 3: controller.storage.host.store.v1.PreferredEndpoint
|
||||
(*IpAddress)(nil), // 4: controller.storage.host.store.v1.IpAddress
|
||||
(*DnsName)(nil), // 5: controller.storage.host.store.v1.DnsName
|
||||
}
|
||||
var file_controller_storage_host_store_v1_host_proto_depIdxs = []int32{
|
||||
0, // [0:0] is the sub-list for method output_type
|
||||
@@ -383,6 +528,30 @@ func file_controller_storage_host_store_v1_host_proto_init() {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_store_v1_host_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*IpAddress); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
file_controller_storage_host_store_v1_host_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
||||
switch v := v.(*DnsName); i {
|
||||
case 0:
|
||||
return &v.state
|
||||
case 1:
|
||||
return &v.sizeCache
|
||||
case 2:
|
||||
return &v.unknownFields
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
type x struct{}
|
||||
out := protoimpl.TypeBuilder{
|
||||
@@ -390,7 +559,7 @@ func file_controller_storage_host_store_v1_host_proto_init() {
|
||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||
RawDescriptor: file_controller_storage_host_store_v1_host_proto_rawDesc,
|
||||
NumEnums: 0,
|
||||
NumMessages: 4,
|
||||
NumMessages: 6,
|
||||
NumExtensions: 0,
|
||||
NumServices: 0,
|
||||
},
|
||||
|
||||
@@ -47,42 +47,6 @@ message HostCatalog {
|
||||
bytes attributes = 9;
|
||||
}
|
||||
|
||||
message Host {
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string public_id = 1;
|
||||
|
||||
// The create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
timestamp.v1.Timestamp create_time = 2;
|
||||
|
||||
// The update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
timestamp.v1.Timestamp update_time = 3;
|
||||
|
||||
// name is optional. If set, it must be unique within
|
||||
// catalog_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string name = 4;
|
||||
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string description = 5;
|
||||
|
||||
// catalog_id is the public_id of the owning
|
||||
// plugin_host_catalog and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string catalog_id = 6;
|
||||
|
||||
// version allows optimistic locking of the resource
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
uint32 version = 7;
|
||||
|
||||
// address is the IP Address or DNS name of the host.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string address = 8;
|
||||
}
|
||||
|
||||
message HostSet {
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
@@ -149,4 +113,62 @@ message HostCatalogSecret {
|
||||
// It must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string key_id = 6;
|
||||
}
|
||||
|
||||
// TODO: Add a field which tracks if the host in cache should be considered
|
||||
// invalid and fall back to the plugin provided data.
|
||||
message Host {
|
||||
// public_id is a surrogate key suitable for use in a public API.
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string public_id = 1;
|
||||
|
||||
// external_id is an id provided by the plugin.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string external_id = 2;
|
||||
|
||||
// The create_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
timestamp.v1.Timestamp create_time = 3;
|
||||
|
||||
// The update_time is set by the database.
|
||||
// @inject_tag: `gorm:"default:current_timestamp"`
|
||||
timestamp.v1.Timestamp update_time = 4;
|
||||
|
||||
// name is optional. If set, it must be unique within
|
||||
// catalog_id.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string name = 5;
|
||||
|
||||
// description is optional.
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string description = 6;
|
||||
|
||||
// catalog_id is the public_id of the owning
|
||||
// plugin_host_catalog and must be set.
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string catalog_id = 7;
|
||||
|
||||
// @inject_tag: `gorm:"-"`
|
||||
uint32 version = 8;
|
||||
|
||||
// ip_addresses are the ip addresses associated with this host and will
|
||||
// be persisted in the db through the HostAddress message.
|
||||
// @inject_tag: `gorm:"-"`
|
||||
repeated string ip_addresses = 9;
|
||||
|
||||
// dns_names are the dns names associated with this host and will
|
||||
// be persisted in the db through the HostAddress message.
|
||||
// @inject_tag: `gorm:"-"`
|
||||
repeated string dns_names = 10;
|
||||
}
|
||||
|
||||
message HostSetMember {
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string host_id = 1;
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string set_id = 2;
|
||||
|
||||
// @inject_tag: `gorm:"default:null"`
|
||||
string catalog_id = 3;
|
||||
}
|
||||
@@ -46,4 +46,26 @@ message PreferredEndpoint {
|
||||
// The string text of the preference condition
|
||||
// @inject_tag: `gorm:"not_null"`
|
||||
string condition = 3;
|
||||
}
|
||||
|
||||
message IpAddress {
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string host_id = 1;
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
uint32 priority = 2;
|
||||
|
||||
// @inject_tag: `gorm:"not_null`
|
||||
string address = 3;
|
||||
}
|
||||
|
||||
message DnsName {
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
string host_id = 1;
|
||||
|
||||
// @inject_tag: `gorm:"primary_key"`
|
||||
uint32 priority = 2;
|
||||
|
||||
// @inject_tag: `gorm:"not_null`
|
||||
string name = 3;
|
||||
}
|
||||
Reference in new issue
Block a user