more error coverage
This commit is contained in:
3 files changed
+830
-14
No files matched your search
@@ -11,6 +11,8 @@ import (
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
)
|
||||
|
||||
const testDescribeInstancesError = "DescribeInstances error"
|
||||
|
||||
type testMockIAMState struct {
|
||||
DeleteAccessKeyCalled bool
|
||||
}
|
||||
@@ -100,8 +102,10 @@ func newTestMockEC2(state *testMockEC2State, opts ...testMockEC2Option) ec2APIFu
|
||||
}
|
||||
|
||||
func (m *testMockEC2) DescribeInstances(input *ec2.DescribeInstancesInput) (*ec2.DescribeInstancesOutput, error) {
|
||||
m.State.DescribeInstancesCalled = true
|
||||
m.State.DescribeInstancesInputParams = input
|
||||
if m.State != nil {
|
||||
m.State.DescribeInstancesCalled = true
|
||||
m.State.DescribeInstancesInputParams = input
|
||||
}
|
||||
|
||||
if m.DescribeInstancesError != nil {
|
||||
return nil, m.DescribeInstancesError
|
||||
|
||||
+12
-12
@@ -198,9 +198,9 @@ func (p *AwsPlugin) OnDeleteCatalog(ctx context.Context, req *pb.OnDeleteCatalog
|
||||
// integrity. May need to be changed at later time if there are
|
||||
// scenarios where we might be deleting things and any secret state
|
||||
// may be corrupt/and or legitimately missing.
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted())
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted(), p.testStateOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error loading persisted state: %w", err)
|
||||
}
|
||||
|
||||
if !state.CredsLastRotatedTime.IsZero() {
|
||||
@@ -208,7 +208,7 @@ func (p *AwsPlugin) OnDeleteCatalog(ctx context.Context, req *pb.OnDeleteCatalog
|
||||
// credentials to ensure that it has the proper permissions to do
|
||||
// it.
|
||||
if err := state.DeleteCreds(); err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error removing rotated credentials during catalog deletion: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -226,15 +226,15 @@ func (p *AwsPlugin) OnCreateSet(ctx context.Context, req *pb.OnCreateSetRequest)
|
||||
return nil, errors.New("catalog missing attributes")
|
||||
}
|
||||
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted())
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted(), p.testStateOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error loading persisted state: %w", err)
|
||||
}
|
||||
|
||||
// Get/validate the region.
|
||||
region, err := getValidateRegionValue(catalogAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("catalog validation error: %s", err)
|
||||
}
|
||||
|
||||
set := req.GetSet()
|
||||
@@ -281,15 +281,15 @@ func (p *AwsPlugin) OnUpdateSet(ctx context.Context, req *pb.OnUpdateSetRequest)
|
||||
return nil, errors.New("catalog missing attributes")
|
||||
}
|
||||
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted())
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted(), p.testStateOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error loading persisted state: %w", err)
|
||||
}
|
||||
|
||||
// Get/validate the region.
|
||||
region, err := getValidateRegionValue(catalogAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("catalog validation error: %s", err)
|
||||
}
|
||||
|
||||
// As with catalog, we don't need to really look at the old host
|
||||
@@ -344,15 +344,15 @@ func (p *AwsPlugin) ListHosts(ctx context.Context, req *pb.ListHostsRequest) (*p
|
||||
return nil, errors.New("catalog missing attributes")
|
||||
}
|
||||
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted())
|
||||
state, err := awsCatalogPersistedStateFromProto(req.GetPersisted(), p.testStateOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("error loading persisted state: %w", err)
|
||||
}
|
||||
|
||||
// Get/validate the region.
|
||||
region, err := getValidateRegionValue(catalogAttrs)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, fmt.Errorf("catalog validation error: %w", err)
|
||||
}
|
||||
|
||||
sets := req.GetSets()
|
||||
|
||||
@@ -6,7 +6,9 @@ import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/service/ec2"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostcatalogs"
|
||||
"github.com/hashicorp/boundary/sdk/pbs/controller/api/resources/hostsets"
|
||||
pb "github.com/hashicorp/boundary/sdk/pbs/plugin"
|
||||
"github.com/hashicorp/go-secure-stdlib/awsutil"
|
||||
"github.com/stretchr/testify/require"
|
||||
@@ -384,3 +386,813 @@ func TestOnUpdateCatalogErr(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnDeleteCatalogErr(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pb.OnDeleteCatalogRequest
|
||||
opts []awsCatalogPersistedStateOption
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "persisted state setup error",
|
||||
req: &pb.OnDeleteCatalogRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
func(s *awsCatalogPersistedState) error {
|
||||
return errors.New(testOptionErr)
|
||||
},
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error loading persisted state: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "delete error",
|
||||
req: &pb.OnDeleteCatalogRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withStateTestOpts([]awsutil.Option{
|
||||
awsutil.WithIAMAPIFunc(
|
||||
awsutil.NewMockIAM(
|
||||
awsutil.WithDeleteAccessKeyError(errors.New(testDeleteAccessKeyErr)),
|
||||
),
|
||||
),
|
||||
}),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error removing rotated credentials during catalog deletion: error deleting old access key: %s", testDeleteAccessKeyErr),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
p := &AwsPlugin{
|
||||
testStateOpts: tc.opts,
|
||||
}
|
||||
_, err := p.OnDeleteCatalog(context.Background(), tc.req)
|
||||
require.EqualError(err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnCreateSetErr(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pb.OnCreateSetRequest
|
||||
opts []awsCatalogPersistedStateOption
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "nil catalog",
|
||||
req: &pb.OnCreateSetRequest{},
|
||||
expectedErr: "catalog is nil",
|
||||
},
|
||||
{
|
||||
name: "nil catalog attributes",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Secrets: new(structpb.Struct),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog missing attributes",
|
||||
},
|
||||
{
|
||||
name: "persisted state setup error",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
func(s *awsCatalogPersistedState) error {
|
||||
return errors.New(testOptionErr)
|
||||
},
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error loading persisted state: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "invalid region",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "foobar",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog validation error: not a valid region: foobar",
|
||||
},
|
||||
{
|
||||
name: "nil set",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "set is nil",
|
||||
},
|
||||
{
|
||||
name: "nil attributes in set",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Set: &hostsets.HostSet{},
|
||||
},
|
||||
expectedErr: "set missing attributes",
|
||||
},
|
||||
{
|
||||
name: "client load error",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Set: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error getting EC2 client: error getting AWS session: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "buildDescribeInstancesInput error",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Set: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": "foo",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "error building DescribeInstances parameters: error building filters: unexpected type for filter values in \"tag-key\": want array, got string",
|
||||
},
|
||||
{
|
||||
name: "DescribeInstances error",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Set: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
testMockEC2WithDescribeInstancesError(errors.New(testDescribeInstancesError)),
|
||||
)),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error performing dry run of DescribeInstances: %s", testDescribeInstancesError),
|
||||
},
|
||||
{
|
||||
name: "DescribeInstances non-error",
|
||||
req: &pb.OnCreateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Set: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
)),
|
||||
},
|
||||
expectedErr: "query error: DescribeInstances DryRun should have returned error, but none was found",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
p := &AwsPlugin{
|
||||
testStateOpts: tc.opts,
|
||||
}
|
||||
_, err := p.OnCreateSet(context.Background(), tc.req)
|
||||
require.EqualError(err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnUpdateSetErr(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pb.OnUpdateSetRequest
|
||||
opts []awsCatalogPersistedStateOption
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "nil catalog",
|
||||
req: &pb.OnUpdateSetRequest{},
|
||||
expectedErr: "catalog is nil",
|
||||
},
|
||||
{
|
||||
name: "nil catalog attributes",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Secrets: new(structpb.Struct),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog missing attributes",
|
||||
},
|
||||
{
|
||||
name: "persisted state setup error",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
func(s *awsCatalogPersistedState) error {
|
||||
return errors.New(testOptionErr)
|
||||
},
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error loading persisted state: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "invalid region",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "foobar",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog validation error: not a valid region: foobar",
|
||||
},
|
||||
{
|
||||
name: "nil set",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "new set is nil",
|
||||
},
|
||||
{
|
||||
name: "nil attributes in set",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
NewSet: &hostsets.HostSet{},
|
||||
},
|
||||
expectedErr: "new set missing attributes",
|
||||
},
|
||||
{
|
||||
name: "client load error",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
NewSet: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error getting EC2 client: error getting AWS session: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "buildDescribeInstancesInput error",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
NewSet: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": "foo",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "error building DescribeInstances parameters: error building filters: unexpected type for filter values in \"tag-key\": want array, got string",
|
||||
},
|
||||
{
|
||||
name: "DescribeInstances error",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
NewSet: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
testMockEC2WithDescribeInstancesError(errors.New(testDescribeInstancesError)),
|
||||
)),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error performing dry run of DescribeInstances: %s", testDescribeInstancesError),
|
||||
},
|
||||
{
|
||||
name: "DescribeInstances non-error",
|
||||
req: &pb.OnUpdateSetRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
NewSet: &hostsets.HostSet{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
)),
|
||||
},
|
||||
expectedErr: "query error: DescribeInstances DryRun should have returned error, but none was found",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
p := &AwsPlugin{
|
||||
testStateOpts: tc.opts,
|
||||
}
|
||||
_, err := p.OnUpdateSet(context.Background(), tc.req)
|
||||
require.EqualError(err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestListHostsErr(t *testing.T) {
|
||||
cases := []struct {
|
||||
name string
|
||||
req *pb.ListHostsRequest
|
||||
opts []awsCatalogPersistedStateOption
|
||||
expectedErr string
|
||||
}{
|
||||
{
|
||||
name: "nil catalog",
|
||||
req: &pb.ListHostsRequest{},
|
||||
expectedErr: "catalog is nil",
|
||||
},
|
||||
{
|
||||
name: "nil catalog attributes",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Secrets: new(structpb.Struct),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog missing attributes",
|
||||
},
|
||||
{
|
||||
name: "persisted state setup error",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
func(s *awsCatalogPersistedState) error {
|
||||
return errors.New(testOptionErr)
|
||||
},
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error loading persisted state: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "invalid region",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "foobar",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "catalog validation error: not a valid region: foobar",
|
||||
},
|
||||
{
|
||||
name: "nil sets",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
},
|
||||
expectedErr: "sets is nil",
|
||||
},
|
||||
{
|
||||
name: "set missing id",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{&hostsets.HostSet{}},
|
||||
},
|
||||
expectedErr: "set missing id",
|
||||
},
|
||||
{
|
||||
name: "set missing attributes",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{
|
||||
&hostsets.HostSet{
|
||||
Id: "foobar",
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "set missing attributes",
|
||||
},
|
||||
{
|
||||
name: "buildDescribeInstancesInput error",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{
|
||||
&hostsets.HostSet{
|
||||
Id: "foobar",
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": "foo",
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
expectedErr: "error building DescribeInstances parameters for host set id \"foobar\": error building filters: unexpected type for filter values in \"tag-key\": want array, got string",
|
||||
},
|
||||
{
|
||||
name: "client load error",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{
|
||||
&hostsets.HostSet{
|
||||
Id: "foobar",
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withStateTestOpts([]awsutil.Option{
|
||||
awsutil.MockOptionErr(errors.New(testOptionErr)),
|
||||
}),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error getting EC2 client: error getting AWS session: error reading options in NewCredentialsConfig: %s", testOptionErr),
|
||||
},
|
||||
{
|
||||
name: "DescribeInstances error",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{
|
||||
&hostsets.HostSet{
|
||||
Id: "foobar",
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
testMockEC2WithDescribeInstancesError(errors.New(testDescribeInstancesError)),
|
||||
)),
|
||||
},
|
||||
expectedErr: fmt.Sprintf("error running DescribeInstances for host set id \"foobar\": %s", testDescribeInstancesError),
|
||||
},
|
||||
{
|
||||
name: "awsInstanceToHost error",
|
||||
req: &pb.ListHostsRequest{
|
||||
Catalog: &hostcatalogs.HostCatalog{
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constRegion: "us-west-2",
|
||||
}),
|
||||
},
|
||||
Persisted: &pb.HostCatalogPersisted{
|
||||
Secrets: mustStruct(map[string]interface{}{
|
||||
constAccessKeyId: "foobar",
|
||||
constSecretAccessKey: "bazqux",
|
||||
constCredsLastRotatedTime: "2006-01-02T15:04:05+07:00",
|
||||
}),
|
||||
},
|
||||
Sets: []*hostsets.HostSet{
|
||||
&hostsets.HostSet{
|
||||
Id: "foobar",
|
||||
Attributes: mustStruct(map[string]interface{}{
|
||||
constDescribeInstancesFilters: map[string]interface{}{
|
||||
"tag-key": []interface{}{"foo"},
|
||||
},
|
||||
}),
|
||||
},
|
||||
},
|
||||
},
|
||||
opts: []awsCatalogPersistedStateOption{
|
||||
withTestEC2APIFunc(newTestMockEC2(
|
||||
nil,
|
||||
testMockEC2WithDescribeInstancesOutput(
|
||||
&ec2.DescribeInstancesOutput{
|
||||
Reservations: []*ec2.Reservation{
|
||||
&ec2.Reservation{
|
||||
Instances: []*ec2.Instance{
|
||||
&ec2.Instance{
|
||||
// Blank so we error out
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
),
|
||||
)),
|
||||
},
|
||||
expectedErr: "error processing host results for host set id \"foobar\": response integrity error: missing instance state",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
require := require.New(t)
|
||||
p := &AwsPlugin{
|
||||
testStateOpts: tc.opts,
|
||||
}
|
||||
_, err := p.ListHosts(context.Background(), tc.req)
|
||||
require.EqualError(err, tc.expectedErr)
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user