Add more tests and comments for Godoc
This commit is contained in:
12 files changed
+345
-23
No files matched your search
@@ -16,6 +16,7 @@ import (
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
// CatalogAttributes defines a set of attributes for the host catalog
|
||||
type CatalogAttributes struct {
|
||||
*cred.CredentialAttributes
|
||||
}
|
||||
@@ -51,6 +52,7 @@ func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SetAttributes defines attributes fro the host set
|
||||
type SetAttributes struct {
|
||||
Filter string `mapstructure:"filter"`
|
||||
InstanceGroup string `mapstructure:"instance_group"`
|
||||
@@ -62,6 +64,12 @@ func getSetAttributes(in *structpb.Struct) (*SetAttributes, error) {
|
||||
badFields := make(map[string]string)
|
||||
unknownFields := values.StructFields(in)
|
||||
|
||||
if _, filter := unknownFields[ConstListInstancesFilter]; filter {
|
||||
if _, ig := unknownFields[ConstInstanceGroup]; ig {
|
||||
return nil, errors.InvalidArgumentError("Error in the attributes provided, cannot define both filter and instance group", nil)
|
||||
}
|
||||
}
|
||||
|
||||
delete(unknownFields, ConstListInstancesFilter)
|
||||
delete(unknownFields, ConstInstanceGroup)
|
||||
|
||||
@@ -82,6 +90,7 @@ func getSetAttributes(in *structpb.Struct) (*SetAttributes, error) {
|
||||
inMap[ConstListInstancesFilter] = string(filterVal)
|
||||
}
|
||||
}
|
||||
|
||||
if instanceGroupRaw, ok := inMap[ConstInstanceGroup]; ok {
|
||||
switch instanceGroupValue := instanceGroupRaw.(type) {
|
||||
case string:
|
||||
|
||||
@@ -6,6 +6,7 @@ package plugin
|
||||
import (
|
||||
"testing"
|
||||
|
||||
cred "github.com/hashicorp/boundary-plugin-google/internal/credential"
|
||||
"github.com/stretchr/testify/require"
|
||||
"google.golang.org/grpc/codes"
|
||||
"google.golang.org/grpc/status"
|
||||
@@ -38,6 +39,19 @@ func TestGetCatalogAttributes(t *testing.T) {
|
||||
},
|
||||
expectedErrContains: "attributes.bar: unrecognized field, attributes.foo: unrecognized field",
|
||||
},
|
||||
{
|
||||
name: "valid project and zone",
|
||||
in: &structpb.Struct{
|
||||
Fields: map[string]*structpb.Value{
|
||||
"project": structpb.NewStringValue("test-12345"),
|
||||
"zone": structpb.NewStringValue("us-central-1a"),
|
||||
},
|
||||
},
|
||||
expected: &CatalogAttributes{&cred.CredentialAttributes{
|
||||
Project: "test-12345",
|
||||
Zone: "us-central-1a",
|
||||
}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
@@ -73,7 +87,7 @@ func TestGetSetAttributes(t *testing.T) {
|
||||
expected: &SetAttributes{},
|
||||
},
|
||||
{
|
||||
name: "example filter",
|
||||
name: "valid example filter",
|
||||
in: map[string]any{
|
||||
ConstListInstancesFilter: "tags.items=my-tag AND -tags.items=my-other-tag) OR tags.items=alternative-tag",
|
||||
},
|
||||
@@ -82,7 +96,7 @@ func TestGetSetAttributes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "example instance group",
|
||||
name: "valid example instance group",
|
||||
in: map[string]any{
|
||||
ConstInstanceGroup: "test",
|
||||
},
|
||||
@@ -98,6 +112,14 @@ func TestGetSetAttributes(t *testing.T) {
|
||||
},
|
||||
expectedErrContains: "attributes.bar: unrecognized field, attributes.foo: unrecognized field",
|
||||
},
|
||||
{
|
||||
name: "invalid, cannot have both instance filter and group defined",
|
||||
in: map[string]any{
|
||||
ConstListInstancesFilter: "test",
|
||||
ConstInstanceGroup: "test",
|
||||
},
|
||||
expectedErrContains: "Error in the attributes provided, cannot define both filter and instance group",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: MPL-2.0
|
||||
|
||||
package plugin
|
||||
@@ -20,6 +20,8 @@ const (
|
||||
NumberMaxResults = uint32(100)
|
||||
)
|
||||
|
||||
// GoogleClient contains clients and attributes for authenticating to Google Cloud
|
||||
// and finding instances
|
||||
type GoogleClient struct {
|
||||
InstancesClient *compute.InstancesClient
|
||||
InstanceGroupClient *compute.InstanceGroupsClient
|
||||
@@ -76,6 +78,10 @@ func instanceToHost(instance *computepb.Instance) (*pb.ListHostsResponseHost, er
|
||||
return nil, errors.New("response integrity error: missing instance self-link")
|
||||
}
|
||||
|
||||
if instance.GetName() == "" {
|
||||
return nil, errors.New("response integrity error: missing instance name")
|
||||
}
|
||||
|
||||
result := new(pb.ListHostsResponseHost)
|
||||
|
||||
result.ExternalId = instance.GetSelfLink()
|
||||
|
||||
+28
-10
@@ -18,6 +18,7 @@ func TestInstanceToHost(t *testing.T) {
|
||||
examplePublicIp := "1.1.1.1"
|
||||
examplePublicIp2 := "1.1.1.2"
|
||||
exampleIPv6 := "some::fake::address"
|
||||
exampleName := "test-instance"
|
||||
|
||||
cases := []struct {
|
||||
name string
|
||||
@@ -26,14 +27,24 @@ func TestInstanceToHost(t *testing.T) {
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "missing instance self-link",
|
||||
instance: &computepb.Instance{},
|
||||
name: "missing instance self-link",
|
||||
instance: &computepb.Instance{
|
||||
Name: &exampleName,
|
||||
},
|
||||
expectedErr: "response integrity error: missing instance self-link",
|
||||
},
|
||||
{
|
||||
name: "missing instance name",
|
||||
instance: &computepb.Instance{
|
||||
SelfLink: &exampleId,
|
||||
},
|
||||
expectedErr: "response integrity error: missing instance name",
|
||||
},
|
||||
{
|
||||
name: "good, single private IP with public IP address",
|
||||
instance: &computepb.Instance{
|
||||
SelfLink: &exampleId,
|
||||
Name: &exampleName,
|
||||
NetworkInterfaces: []*computepb.NetworkInterface{
|
||||
{
|
||||
NetworkIP: &examplePrivateIp,
|
||||
@@ -46,14 +57,16 @@ func TestInstanceToHost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &pb.ListHostsResponseHost{
|
||||
ExternalId: exampleId,
|
||||
IpAddresses: []string{examplePrivateIp, examplePublicIp},
|
||||
ExternalId: exampleId,
|
||||
ExternalName: exampleName,
|
||||
IpAddresses: []string{examplePrivateIp, examplePublicIp},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "good, single private IP address",
|
||||
instance: &computepb.Instance{
|
||||
SelfLink: &exampleId,
|
||||
Name: &exampleName,
|
||||
NetworkInterfaces: []*computepb.NetworkInterface{
|
||||
{
|
||||
NetworkIP: &examplePrivateIp,
|
||||
@@ -62,14 +75,16 @@ func TestInstanceToHost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &pb.ListHostsResponseHost{
|
||||
ExternalId: exampleId,
|
||||
IpAddresses: []string{examplePrivateIp},
|
||||
ExternalId: exampleId,
|
||||
ExternalName: exampleName,
|
||||
IpAddresses: []string{examplePrivateIp},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "good, multiple interfaces",
|
||||
instance: &computepb.Instance{
|
||||
SelfLink: &exampleId,
|
||||
Name: &exampleName,
|
||||
NetworkInterfaces: []*computepb.NetworkInterface{
|
||||
{
|
||||
NetworkIP: &examplePrivateIp,
|
||||
@@ -90,14 +105,16 @@ func TestInstanceToHost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &pb.ListHostsResponseHost{
|
||||
ExternalId: exampleId,
|
||||
IpAddresses: []string{examplePrivateIp, examplePublicIp, examplePrivateIp2, examplePublicIp2},
|
||||
ExternalId: exampleId,
|
||||
ExternalName: exampleName,
|
||||
IpAddresses: []string{examplePrivateIp, examplePublicIp, examplePrivateIp2, examplePublicIp2},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "good, single private IP address with IPv6",
|
||||
instance: &computepb.Instance{
|
||||
SelfLink: &exampleId,
|
||||
Name: &exampleName,
|
||||
NetworkInterfaces: []*computepb.NetworkInterface{
|
||||
{
|
||||
NetworkIP: &examplePrivateIp,
|
||||
@@ -107,8 +124,9 @@ func TestInstanceToHost(t *testing.T) {
|
||||
},
|
||||
},
|
||||
expected: &pb.ListHostsResponseHost{
|
||||
ExternalId: exampleId,
|
||||
IpAddresses: []string{examplePrivateIp, exampleIPv6},
|
||||
ExternalId: exampleId,
|
||||
ExternalName: exampleName,
|
||||
IpAddresses: []string{examplePrivateIp, exampleIPv6},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
+4
-1
@@ -4,8 +4,11 @@
|
||||
package plugin
|
||||
|
||||
const (
|
||||
// ConstListInstancesFilter refers to a Google Cloud SDK filter to search for instances
|
||||
ConstListInstancesFilter = "filter"
|
||||
ConstInstanceGroup = "instance_group"
|
||||
|
||||
// ConstInstanceGroup refers to the name of a Google Cloud instance group
|
||||
ConstInstanceGroup = "instance_group"
|
||||
)
|
||||
|
||||
var allowedSetFields = map[string]struct{}{
|
||||
|
||||
@@ -17,6 +17,8 @@ import (
|
||||
"google.golang.org/grpc/status"
|
||||
)
|
||||
|
||||
// GooglePlugin implements the GooglePluginServiceServer interface for the
|
||||
// Google host service plugin.
|
||||
type GooglePlugin struct {
|
||||
pb.UnimplementedHostPluginServiceServer
|
||||
}
|
||||
@@ -25,6 +27,7 @@ var (
|
||||
_ pb.HostPluginServiceServer = (*GooglePlugin)(nil)
|
||||
)
|
||||
|
||||
// OnCreateCatalog is called when a dynamic host catalog is created.
|
||||
func (p *GooglePlugin) OnCreateCatalog(_ context.Context, req *pb.OnCreateCatalogRequest) (*pb.OnCreateCatalogResponse, error) {
|
||||
catalog := req.GetCatalog()
|
||||
if catalog == nil {
|
||||
@@ -47,6 +50,7 @@ func (p *GooglePlugin) OnCreateCatalog(_ context.Context, req *pb.OnCreateCatalo
|
||||
}, nil
|
||||
}
|
||||
|
||||
// OnUpdateCatalog is called when a dynamic host catalog is updated.
|
||||
func (p *GooglePlugin) OnUpdateCatalog(_ context.Context, req *pb.OnUpdateCatalogRequest) (*pb.OnUpdateCatalogResponse, error) {
|
||||
currentCatalog := req.GetCurrentCatalog()
|
||||
if currentCatalog == nil {
|
||||
@@ -67,6 +71,7 @@ func (p *GooglePlugin) OnUpdateCatalog(_ context.Context, req *pb.OnUpdateCatalo
|
||||
}, nil
|
||||
}
|
||||
|
||||
// OnDeleteCatalog is called when a dynamic host catalog is deleted.
|
||||
func (p *GooglePlugin) OnDeleteCatalog(ctx context.Context, req *pb.OnDeleteCatalogRequest) (*pb.OnDeleteCatalogResponse, error) {
|
||||
catalog := req.GetCatalog()
|
||||
if catalog == nil {
|
||||
@@ -85,6 +90,7 @@ func (p *GooglePlugin) OnDeleteCatalog(ctx context.Context, req *pb.OnDeleteCata
|
||||
return &pb.OnDeleteCatalogResponse{}, nil
|
||||
}
|
||||
|
||||
// OnCreateSet is called when a dynamic host set is created.
|
||||
func (p *GooglePlugin) OnCreateSet(_ context.Context, req *pb.OnCreateSetRequest) (*pb.OnCreateSetResponse, error) {
|
||||
if err := validateSet(req.GetSet()); err != nil {
|
||||
return nil, err
|
||||
@@ -92,6 +98,7 @@ func (p *GooglePlugin) OnCreateSet(_ context.Context, req *pb.OnCreateSetRequest
|
||||
return &pb.OnCreateSetResponse{}, nil
|
||||
}
|
||||
|
||||
// OnUpdateSet is called when a dynamic host set is updated.
|
||||
func (p *GooglePlugin) OnUpdateSet(_ context.Context, req *pb.OnUpdateSetRequest) (*pb.OnUpdateSetResponse, error) {
|
||||
if err := validateSet(req.GetNewSet()); err != nil {
|
||||
return nil, err
|
||||
@@ -104,6 +111,7 @@ func (p *GooglePlugin) OnDeleteSet(ctx context.Context, req *pb.OnDeleteSetReque
|
||||
return &pb.OnDeleteSetResponse{}, nil
|
||||
}
|
||||
|
||||
// ListHosts returns the list of instances based on filter or instance group name.
|
||||
func (p *GooglePlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*pb.ListHostsResponse, error) {
|
||||
catalog := req.GetCatalog()
|
||||
if catalog == nil {
|
||||
|
||||
Reference in new issue
Block a user