Add more tests and comments for Godoc

This commit is contained in:
Rosemary Wang committed 2024-08-06 11:51:00 -04:00
1 parent 714c26721d
commit 9e63aea3ec
12 files changed
+345 -23

No files matched your search

+9
View File
@@ -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:
+24 -2
View File
@@ -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 {
-4
View File
@@ -1,4 +0,0 @@
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package plugin
+6
View File
@@ -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
View File
@@ -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
View File
@@ -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{}{
+8
View File
@@ -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 {