Files
threshold-plugin-gcp/plugin/service/host/attributes_test.go
T

225 lines
5.8 KiB
Go
Raw Normal View History

// Copyright IBM Corp. 2024, 2025
2024-04-02 15:47:49 -04:00
// SPDX-License-Identifier: MPL-2.0
2024-09-16 14:28:54 -04:00
package host
2024-04-02 15:47:49 -04:00
import (
"testing"
2024-11-06 12:43:06 -05:00
computepb "cloud.google.com/go/compute/apiv1/computepb"
2024-09-16 12:20:08 -04:00
cred "github.com/hashicorp/boundary-plugin-gcp/internal/credential"
2024-04-02 15:47:49 -04:00
"github.com/stretchr/testify/require"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/structpb"
)
func TestGetCatalogAttributes(t *testing.T) {
cases := []struct {
name string
in *structpb.Struct
expected *CatalogAttributes
expectedErrContains string
}{
{
2024-09-17 10:50:10 -04:00
name: "missing project_id and zone",
2024-04-02 15:47:49 -04:00
in: &structpb.Struct{
Fields: make(map[string]*structpb.Value),
},
2024-09-17 10:50:10 -04:00
expectedErrContains: "attributes.project_id: missing required value \"project_id\", attributes.zone: missing required value \"zone\"",
2024-04-02 15:47:49 -04:00
},
{
name: "unknown fields",
in: &structpb.Struct{
Fields: map[string]*structpb.Value{
2024-09-17 10:50:10 -04:00
"project_id": structpb.NewStringValue("test-12345"),
"zone": structpb.NewStringValue("us-central-1a"),
"foo": structpb.NewBoolValue(true),
"bar": structpb.NewBoolValue(true),
2024-04-02 15:47:49 -04:00
},
},
expectedErrContains: "attributes.bar: unrecognized field, attributes.foo: unrecognized field",
},
2024-08-06 11:51:00 -04:00
{
name: "valid project and zone",
in: &structpb.Struct{
Fields: map[string]*structpb.Value{
2024-09-17 10:50:10 -04:00
"project_id": structpb.NewStringValue("test-12345"),
"zone": structpb.NewStringValue("us-central-1a"),
2024-08-06 11:51:00 -04:00
},
},
expected: &CatalogAttributes{&cred.CredentialAttributes{
2024-09-17 10:50:10 -04:00
ProjectId: "test-12345",
Zone: "us-central-1a",
2024-08-06 11:51:00 -04:00
}},
},
2024-04-02 15:47:49 -04:00
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
require := require.New(t)
actual, err := getCatalogAttributes(tc.in)
if tc.expectedErrContains != "" {
require.Error(err)
require.Contains(err.Error(), tc.expectedErrContains)
require.Equal(status.Code(err), codes.InvalidArgument)
return
}
require.NoError(err)
require.Equal(tc.expected, actual)
})
}
}
func TestGetSetAttributes(t *testing.T) {
cases := []struct {
name string
in map[string]any
normalized map[string]any
expected *SetAttributes
expectedErrContains string
}{
{
name: "missing",
in: map[string]any{},
expected: &SetAttributes{},
},
{
2024-08-06 11:51:00 -04:00
name: "valid example filter",
2024-04-02 15:47:49 -04:00
in: map[string]any{
ConstListInstancesFilter: "tags.items=my-tag AND -tags.items=my-other-tag) OR tags.items=alternative-tag",
},
expected: &SetAttributes{
2024-10-18 10:35:05 -04:00
Filters: []string{"tags.items=my-tag AND -tags.items=my-other-tag) OR tags.items=alternative-tag"},
2024-04-02 15:47:49 -04:00
},
},
{
name: "unknown fields",
in: map[string]any{
"foo": true,
"bar": true,
},
expectedErrContains: "attributes.bar: unrecognized field, attributes.foo: unrecognized field",
},
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
require := require.New(t)
input, err := structpb.NewStruct(tc.in)
require.NoError(err)
actual, err := getSetAttributes(input)
if tc.expectedErrContains != "" {
require.Error(err)
require.Contains(err.Error(), tc.expectedErrContains)
require.Equal(status.Code(err), codes.InvalidArgument)
return
}
require.NoError(err)
require.Equal(tc.expected, actual)
})
}
}
2024-11-06 12:43:06 -05:00
func TestBuildListInstancesRequest(t *testing.T) {
cases := []struct {
name string
attributes *SetAttributes
catalog *CatalogAttributes
expected *computepb.ListInstancesRequest
expectedErrContains string
}{
{
name: "valid request with single filter",
attributes: &SetAttributes{
Filters: []string{"tags.items=my-tag"},
},
catalog: &CatalogAttributes{
CredentialAttributes: &cred.CredentialAttributes{
ProjectId: "test-12345",
Zone: "us-central-1a",
},
},
expected: &computepb.ListInstancesRequest{
Project: "test-12345",
Zone: "us-central-1a",
Filter: stringPtr("tags.items=my-tag AND status = running"),
},
},
{
name: "valid request with multiple filters",
attributes: &SetAttributes{
Filters: []string{"tags.items=my-tag", "tags.items=my-other-tag"},
},
catalog: &CatalogAttributes{
CredentialAttributes: &cred.CredentialAttributes{
ProjectId: "test-12345",
Zone: "us-central-1a",
},
},
expected: &computepb.ListInstancesRequest{
Project: "test-12345",
Zone: "us-central-1a",
Filter: stringPtr("tags.items=my-tag AND tags.items=my-other-tag AND status = running"),
},
},
{
name: "error building filters",
attributes: &SetAttributes{
Filters: []string{"invalid-filter"},
},
catalog: &CatalogAttributes{
CredentialAttributes: &cred.CredentialAttributes{
ProjectId: "test-12345",
Zone: "us-central-1a",
},
},
expectedErrContains: "error building filters",
},
{
name: "valid request with no filters",
attributes: &SetAttributes{
Filters: []string{},
},
catalog: &CatalogAttributes{
CredentialAttributes: &cred.CredentialAttributes{
ProjectId: "test-12345",
Zone: "us-central-1a",
},
},
expected: &computepb.ListInstancesRequest{
Project: "test-12345",
Zone: "us-central-1a",
Filter: stringPtr("status = running"),
},
},
2024-11-06 12:43:06 -05:00
}
for _, tc := range cases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
require := require.New(t)
actual, err := buildListInstancesRequest(tc.attributes, tc.catalog)
if tc.expectedErrContains != "" {
require.Error(err)
require.Contains(err.Error(), tc.expectedErrContains)
return
}
require.NoError(err)
require.Equal(tc.expected, actual)
})
}
}
func stringPtr(s string) *string {
return &s
}