2026-01-16 15:56:19 -08:00
|
|
|
// Copyright IBM Corp. 2021, 2025
|
2023-06-05 09:52:48 -07:00
|
|
|
// SPDX-License-Identifier: MPL-2.0
|
|
|
|
|
|
2023-03-20 11:02:17 -07:00
|
|
|
package host
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"fmt"
|
|
|
|
|
|
2023-06-02 08:55:14 -07:00
|
|
|
cred "github.com/hashicorp/boundary-plugin-aws/internal/credential"
|
|
|
|
|
"github.com/hashicorp/boundary-plugin-aws/internal/errors"
|
|
|
|
|
"github.com/hashicorp/boundary-plugin-aws/internal/values"
|
2023-03-20 11:02:17 -07:00
|
|
|
"github.com/mitchellh/mapstructure"
|
|
|
|
|
"google.golang.org/grpc/codes"
|
|
|
|
|
"google.golang.org/grpc/status"
|
|
|
|
|
"google.golang.org/protobuf/types/known/structpb"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// CatalogAttributes is a Go-native representation of the Attributes
|
|
|
|
|
// map.
|
|
|
|
|
type CatalogAttributes struct {
|
|
|
|
|
*cred.CredentialAttributes
|
2024-10-28 11:50:18 -07:00
|
|
|
|
|
|
|
|
// DualStack is used for configuring how the aws client will resolve requests.
|
|
|
|
|
DualStack bool
|
2023-03-20 11:02:17 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getCatalogAttributes(in *structpb.Struct) (*CatalogAttributes, error) {
|
|
|
|
|
unknownFields := values.StructFields(in)
|
|
|
|
|
badFields := make(map[string]string)
|
|
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
credAttributes, err := cred.GetCredentialAttributes(in)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, err
|
|
|
|
|
}
|
|
|
|
|
|
2024-10-28 11:50:18 -07:00
|
|
|
dualStack, err := values.GetBoolValue(in, ConstAwsDualStack, false)
|
|
|
|
|
if err != nil {
|
|
|
|
|
badFields[fmt.Sprintf("attributes.%s", ConstAwsDualStack)] = err.Error()
|
|
|
|
|
}
|
|
|
|
|
delete(unknownFields, ConstAwsDualStack)
|
|
|
|
|
|
2023-03-20 11:02:17 -07:00
|
|
|
for s := range unknownFields {
|
|
|
|
|
switch s {
|
|
|
|
|
// Ignore knownFields from CredentialAttributes
|
|
|
|
|
case cred.ConstRegion:
|
|
|
|
|
continue
|
|
|
|
|
case cred.ConstDisableCredentialRotation:
|
|
|
|
|
continue
|
2023-07-18 16:33:24 -07:00
|
|
|
case cred.ConstRoleArn:
|
|
|
|
|
continue
|
|
|
|
|
case cred.ConstRoleExternalId:
|
|
|
|
|
continue
|
|
|
|
|
case cred.ConstRoleSessionName:
|
|
|
|
|
continue
|
|
|
|
|
case cred.ConstRoleTags:
|
|
|
|
|
continue
|
2023-03-20 11:02:17 -07:00
|
|
|
default:
|
|
|
|
|
badFields[fmt.Sprintf("attributes.%s", s)] = "unrecognized field"
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if len(badFields) > 0 {
|
|
|
|
|
return nil, errors.InvalidArgumentError("Invalid arguments in catalog attributes", badFields)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &CatalogAttributes{
|
|
|
|
|
CredentialAttributes: credAttributes,
|
2024-10-28 11:50:18 -07:00
|
|
|
DualStack: dualStack,
|
2023-03-20 11:02:17 -07:00
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// SetAttributes is a Go-native representation of the Attributes map that can be
|
|
|
|
|
// used for decoding the incoming map via mapstructure.
|
|
|
|
|
type SetAttributes struct {
|
|
|
|
|
Filters []string
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getSetAttributes(in *structpb.Struct) (*SetAttributes, error) {
|
|
|
|
|
var setAttrs SetAttributes
|
|
|
|
|
|
|
|
|
|
// Quick validation to ensure that there's no non-filter attributes
|
|
|
|
|
// here for now. Make this more complex if we add more attributes
|
|
|
|
|
// to host sets.
|
|
|
|
|
unknownFields := values.StructFields(in)
|
|
|
|
|
badFields := make(map[string]string)
|
|
|
|
|
delete(unknownFields, ConstDescribeInstancesFilters)
|
|
|
|
|
for a := range unknownFields {
|
|
|
|
|
badFields[fmt.Sprintf("attributes.%s", a)] = "unrecognized field"
|
|
|
|
|
}
|
|
|
|
|
if len(badFields) > 0 {
|
|
|
|
|
return nil, errors.InvalidArgumentError("Error in the attributes provided", badFields)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Mapstructure complains if it expects a slice as output and sees a scalar
|
|
|
|
|
// value. Rather than use WeakDecode and risk unintended consequences, I'm
|
|
|
|
|
// manually making this change if necessary.
|
|
|
|
|
inMap := in.AsMap()
|
|
|
|
|
if filtersRaw, ok := inMap[ConstDescribeInstancesFilters]; ok {
|
|
|
|
|
switch filterVal := filtersRaw.(type) {
|
|
|
|
|
case string:
|
|
|
|
|
inMap[ConstDescribeInstancesFilters] = []string{filterVal}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if err := mapstructure.Decode(inMap, &setAttrs); err != nil {
|
|
|
|
|
return nil, status.Errorf(codes.InvalidArgument, "error decoding set attributes: %s", err)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &setAttrs, nil
|
|
|
|
|
}
|