Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

migrate AWS RDS services to AWS SDK v2 #50848

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ require (
github.com/aws/aws-sdk-go-v2/feature/dynamodb/attributevalue v1.15.23
github.com/aws/aws-sdk-go-v2/feature/dynamodbstreams/attributevalue v1.14.58
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45
github.com/aws/aws-sdk-go-v2/service/applicationautoscaling v1.34.3
github.com/aws/aws-sdk-go-v2/service/athena v1.49.2
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,8 @@ github.com/aws/aws-sdk-go-v2/feature/dynamodbstreams/attributevalue v1.14.58/go.
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.13.3/go.mod h1:4Q0UFP0YJf0NrsEuEYHpM9fTSEVnD16Z3uyEF7J9JGM=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 h1:kqOrpojG71DxJm/KDPO+Z/y1phm1JlC8/iT+5XRmAn8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22/go.mod h1:NtSFajXVVL8TA2QNngagVZmUtXciyrHOt7xgz4faS/M=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2 h1:fo+GuZNME9oGDc7VY+EBT+oCrco6RjRgUp1bKTcaHrU=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2/go.mod h1:fnqb94UO6YCjBIic4WaqDYkNVAEFWOWiReVHitBBWW0=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45 h1:ZxB8WFVYwolhDZxuZXoesHkl+L9cXLWy0K/G0QkNATc=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45/go.mod h1:1krrbyoFFDqaNldmltPTP+mK3sAXLHPoaFtISOw2Hkk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.1.33/go.mod h1:7i0PF1ME/2eUPFcjkVIwq+DOygHEoK92t5cDqNgYbIw=
Expand Down
2 changes: 2 additions & 0 deletions integrations/terraform/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,8 @@ github.com/aws/aws-sdk-go-v2/feature/dynamodbstreams/attributevalue v1.14.58 h1:
github.com/aws/aws-sdk-go-v2/feature/dynamodbstreams/attributevalue v1.14.58/go.mod h1:1FDesv+tfF2w5mRnLQbB8P33BPfxrngXtfNcdnrtmjw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 h1:kqOrpojG71DxJm/KDPO+Z/y1phm1JlC8/iT+5XRmAn8=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22/go.mod h1:NtSFajXVVL8TA2QNngagVZmUtXciyrHOt7xgz4faS/M=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2 h1:fo+GuZNME9oGDc7VY+EBT+oCrco6RjRgUp1bKTcaHrU=
github.com/aws/aws-sdk-go-v2/feature/rds/auth v1.5.2/go.mod h1:fnqb94UO6YCjBIic4WaqDYkNVAEFWOWiReVHitBBWW0=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45 h1:ZxB8WFVYwolhDZxuZXoesHkl+L9cXLWy0K/G0QkNATc=
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45/go.mod h1:1krrbyoFFDqaNldmltPTP+mK3sAXLHPoaFtISOw2Hkk=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI=
Expand Down
51 changes: 42 additions & 9 deletions lib/cloud/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (
"slices"
"strings"

rdstypes "github.com/aws/aws-sdk-go-v2/service/rds/types"
redshifttypes "github.com/aws/aws-sdk-go-v2/service/redshift/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/memorydb"
"github.com/aws/aws-sdk-go/service/opensearchservice"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/coreos/go-semver/semver"

"github.com/gravitational/teleport/lib/services"
Expand Down Expand Up @@ -74,18 +74,51 @@ func IsOpenSearchDomainAvailable(domain *opensearchservice.DomainStatus) bool {
}

// IsRDSProxyAvailable checks if the RDS Proxy is available.
func IsRDSProxyAvailable(dbProxy *rds.DBProxy) bool {
return IsResourceAvailable(dbProxy, dbProxy.Status)
func IsRDSProxyAvailable(dbProxy *rdstypes.DBProxy) bool {
switch dbProxy.Status {
case
rdstypes.DBProxyStatusAvailable,
rdstypes.DBProxyStatusModifying,
rdstypes.DBProxyStatusReactivating:
return true
case
rdstypes.DBProxyStatusCreating,
rdstypes.DBProxyStatusDeleting,
rdstypes.DBProxyStatusIncompatibleNetwork,
rdstypes.DBProxyStatusInsufficientResourceLimits,
rdstypes.DBProxyStatusSuspended,
rdstypes.DBProxyStatusSuspending:
return false
}
slog.WarnContext(context.Background(), "Assuming RDS Proxy with unknown status is available",
"status", dbProxy.Status,
)
return true
}

// IsRDSProxyCustomEndpointAvailable checks if the RDS Proxy custom endpoint is available.
func IsRDSProxyCustomEndpointAvailable(customEndpoint *rds.DBProxyEndpoint) bool {
return IsResourceAvailable(customEndpoint, customEndpoint.Status)
func IsRDSProxyCustomEndpointAvailable(customEndpoint *rdstypes.DBProxyEndpoint) bool {
switch customEndpoint.Status {
case
rdstypes.DBProxyEndpointStatusAvailable,
rdstypes.DBProxyEndpointStatusModifying:
return true
case
rdstypes.DBProxyEndpointStatusCreating,
rdstypes.DBProxyEndpointStatusDeleting,
rdstypes.DBProxyEndpointStatusIncompatibleNetwork,
rdstypes.DBProxyEndpointStatusInsufficientResourceLimits:
return false
}
slog.WarnContext(context.Background(), "Assuming RDS Proxy custom endpoint with unknown status is available",
"status", customEndpoint.Status,
)
return true
}

// IsRDSInstanceSupported returns true if database supports IAM authentication.
// Currently, only MariaDB is being checked.
func IsRDSInstanceSupported(instance *rds.DBInstance) bool {
func IsRDSInstanceSupported(instance *rdstypes.DBInstance) bool {
// TODO(jakule): Check other engines.
if aws.StringValue(instance.Engine) != services.RDSEngineMariaDB {
return true
Expand All @@ -105,7 +138,7 @@ func IsRDSInstanceSupported(instance *rds.DBInstance) bool {
}

// IsRDSClusterSupported checks whether the Aurora cluster is supported.
func IsRDSClusterSupported(cluster *rds.DBCluster) bool {
func IsRDSClusterSupported(cluster *rdstypes.DBCluster) bool {
switch aws.StringValue(cluster.EngineMode) {
// Aurora Serverless v1 does NOT support IAM authentication.
// https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/aurora-serverless.html#aurora-serverless.limitations
Expand All @@ -129,7 +162,7 @@ func IsRDSClusterSupported(cluster *rds.DBCluster) bool {
}

// AuroraMySQLVersion extracts aurora mysql version from engine version
func AuroraMySQLVersion(cluster *rds.DBCluster) string {
func AuroraMySQLVersion(cluster *rdstypes.DBCluster) string {
// version guide: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Updates.Versions.html
// a list of all the available versions: https://docs.aws.amazon.com/cli/latest/reference/rds/describe-db-engine-versions.html
//
Expand All @@ -154,7 +187,7 @@ func AuroraMySQLVersion(cluster *rds.DBCluster) string {
// for this DocumentDB cluster.
//
// https://docs.aws.amazon.com/documentdb/latest/developerguide/iam-identity-auth.html
func IsDocumentDBClusterSupported(cluster *rds.DBCluster) bool {
func IsDocumentDBClusterSupported(cluster *rdstypes.DBCluster) bool {
ver, err := semver.NewVersion(aws.StringValue(cluster.EngineVersion))
if err != nil {
slog.ErrorContext(context.Background(), "Failed to parse DocumentDB engine version", "version", aws.StringValue(cluster.EngineVersion))
Expand Down
29 changes: 3 additions & 26 deletions lib/cloud/aws/tags_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@ import (
"slices"

ec2TypesV2 "github.com/aws/aws-sdk-go-v2/service/ec2/types"
rdsTypesV2 "github.com/aws/aws-sdk-go-v2/service/rds/types"
rdstypes "github.com/aws/aws-sdk-go-v2/service/rds/types"
redshifttypes "github.com/aws/aws-sdk-go-v2/service/redshift/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/memorydb"
"github.com/aws/aws-sdk-go/service/opensearchservice"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/redshiftserverless"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"golang.org/x/exp/maps"
Expand All @@ -43,11 +42,10 @@ import (
type ResourceTag interface {
// TODO Go generic does not allow access common fields yet. List all types
// here and use a type switch for now.
rdsTypesV2.Tag |
rdstypes.Tag |
ec2TypesV2.Tag |
redshifttypes.Tag |
*ec2.Tag |
*rds.Tag |
*elasticache.Tag |
*memorydb.Tag |
*redshiftserverless.Tag |
Expand Down Expand Up @@ -76,8 +74,6 @@ func TagsToLabels[Tag ResourceTag](tags []Tag) map[string]string {

func resourceTagToKeyValue[Tag ResourceTag](tag Tag) (string, string) {
switch v := any(tag).(type) {
case *rds.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *ec2.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *elasticache.Tag:
Expand All @@ -86,7 +82,7 @@ func resourceTagToKeyValue[Tag ResourceTag](tag Tag) (string, string) {
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *redshiftserverless.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case rdsTypesV2.Tag:
case rdstypes.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case ec2TypesV2.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
Expand Down Expand Up @@ -123,22 +119,3 @@ func LabelsToTags[T any, PT SettableTag[T]](labels map[string]string) (tags []*T
}
return
}

// LabelsToRDSV2Tags converts labels into [rdsTypesV2.Tag] list.
func LabelsToRDSV2Tags(labels map[string]string) []rdsTypesV2.Tag {
GavinFrazar marked this conversation as resolved.
Show resolved Hide resolved
keys := maps.Keys(labels)
slices.Sort(keys)

ret := make([]rdsTypesV2.Tag, 0, len(keys))
for _, key := range keys {
key := key
value := labels[key]

ret = append(ret, rdsTypesV2.Tag{
Key: &key,
Value: &value,
})
}

return ret
}
25 changes: 2 additions & 23 deletions lib/cloud/aws/tags_helpers_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,18 @@ import (
"testing"

rdsTypesV2 "github.com/aws/aws-sdk-go-v2/service/rds/types"
rdstypes "github.com/aws/aws-sdk-go-v2/service/rds/types"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/aws/aws-sdk-go/service/elasticache"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/stretchr/testify/require"
)

func TestTagsToLabels(t *testing.T) {
t.Parallel()

t.Run("rds", func(t *testing.T) {
inputTags := []*rds.Tag{
inputTags := []rdstypes.Tag{
{
Key: aws.String("Env"),
Value: aws.String("dev"),
Expand Down Expand Up @@ -135,25 +135,4 @@ func TestLabelsToTags(t *testing.T) {
actualTags := LabelsToTags[elasticache.Tag](inputLabels)
require.Equal(t, expectTags, actualTags)
})

t.Run("rdsV2", func(t *testing.T) {
GavinFrazar marked this conversation as resolved.
Show resolved Hide resolved
inputLabels := map[string]string{
"labelB": "valueB",
"labelA": "valueA",
}

expectTags := []rdsTypesV2.Tag{
{
Key: aws.String("labelA"),
Value: aws.String("valueA"),
},
{
Key: aws.String("labelB"),
Value: aws.String("valueB"),
},
}

actualTags := LabelsToRDSV2Tags(inputLabels)
require.EqualValues(t, expectTags, actualTags)
})
}
20 changes: 20 additions & 0 deletions lib/cloud/awstesthelpers/tags.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"maps"
"slices"

rdstypes "github.com/aws/aws-sdk-go-v2/service/rds/types"
redshifttypes "github.com/aws/aws-sdk-go-v2/service/redshift/types"
)

Expand All @@ -43,3 +44,22 @@ func LabelsToRedshiftTags(labels map[string]string) []redshifttypes.Tag {

return ret
}

// LabelsToRDSTags converts labels into a [rdstypes.Tag] list.
func LabelsToRDSTags(labels map[string]string) []rdstypes.Tag {
keys := slices.Collect(maps.Keys(labels))
slices.Sort(keys)

ret := make([]rdstypes.Tag, 0, len(keys))
for _, key := range keys {
key := key
value := labels[key]

ret = append(ret, rdstypes.Tag{
Key: &key,
Value: &value,
})
}

return ret
}
27 changes: 0 additions & 27 deletions lib/cloud/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,6 @@ import (
"github.com/aws/aws-sdk-go/service/memorydb/memorydbiface"
"github.com/aws/aws-sdk-go/service/opensearchservice"
"github.com/aws/aws-sdk-go/service/opensearchservice/opensearchserviceiface"
"github.com/aws/aws-sdk-go/service/rds"
"github.com/aws/aws-sdk-go/service/rds/rdsiface"
"github.com/aws/aws-sdk-go/service/redshiftserverless"
"github.com/aws/aws-sdk-go/service/redshiftserverless/redshiftserverlessiface"
"github.com/aws/aws-sdk-go/service/s3"
Expand Down Expand Up @@ -111,8 +109,6 @@ type GCPClients interface {
type AWSClients interface {
// GetAWSSession returns AWS session for the specified region and any role(s).
GetAWSSession(ctx context.Context, region string, opts ...AWSOptionsFn) (*awssession.Session, error)
// GetAWSRDSClient returns AWS RDS client for the specified region.
GetAWSRDSClient(ctx context.Context, region string, opts ...AWSOptionsFn) (rdsiface.RDSAPI, error)
// GetAWSRedshiftServerlessClient returns AWS Redshift Serverless client for the specified region.
GetAWSRedshiftServerlessClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftserverlessiface.RedshiftServerlessAPI, error)
// GetAWSElastiCacheClient returns AWS ElastiCache client for the specified region.
Expand Down Expand Up @@ -504,15 +500,6 @@ func (c *cloudClients) GetAWSSession(ctx context.Context, region string, opts ..
return c.getAWSSessionForRole(ctx, region, options)
}

// GetAWSRDSClient returns AWS RDS client for the specified region.
func (c *cloudClients) GetAWSRDSClient(ctx context.Context, region string, opts ...AWSOptionsFn) (rdsiface.RDSAPI, error) {
session, err := c.GetAWSSession(ctx, region, opts...)
if err != nil {
return nil, trace.Wrap(err)
}
return rds.New(session), nil
}

// GetAWSRedshiftServerlessClient returns AWS Redshift Serverless client for the specified region.
func (c *cloudClients) GetAWSRedshiftServerlessClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftserverlessiface.RedshiftServerlessAPI, error) {
session, err := c.GetAWSSession(ctx, region, opts...)
Expand Down Expand Up @@ -1018,8 +1005,6 @@ var _ Clients = (*TestCloudClients)(nil)

// TestCloudClients are used in tests.
type TestCloudClients struct {
RDS rdsiface.RDSAPI
RDSPerRegion map[string]rdsiface.RDSAPI
RedshiftServerless redshiftserverlessiface.RedshiftServerlessAPI
ElastiCache elasticacheiface.ElastiCacheAPI
OpenSearch opensearchserviceiface.OpenSearchServiceAPI
Expand Down Expand Up @@ -1089,18 +1074,6 @@ func (c *TestCloudClients) getAWSSessionForRegion(region string) (*awssession.Se
})
}

// GetAWSRDSClient returns AWS RDS client for the specified region.
func (c *TestCloudClients) GetAWSRDSClient(ctx context.Context, region string, opts ...AWSOptionsFn) (rdsiface.RDSAPI, error) {
_, err := c.GetAWSSession(ctx, region, opts...)
if err != nil {
return nil, trace.Wrap(err)
}
if len(c.RDSPerRegion) != 0 {
return c.RDSPerRegion[region], nil
}
return c.RDS, nil
}

// GetAWSRedshiftServerlessClient returns AWS Redshift Serverless client for the specified region.
func (c *TestCloudClients) GetAWSRedshiftServerlessClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftserverlessiface.RedshiftServerlessAPI, error) {
_, err := c.GetAWSSession(ctx, region, opts...)
Expand Down
5 changes: 5 additions & 0 deletions lib/cloud/mocks/aws_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,16 @@ import (
)

type AWSConfigProvider struct {
Err error
STSClient *STSClient
OIDCIntegrationClient awsconfig.OIDCIntegrationClient
}

func (f *AWSConfigProvider) GetConfig(ctx context.Context, region string, optFns ...awsconfig.OptionsFn) (aws.Config, error) {
if f.Err != nil {
return aws.Config{}, f.Err
}

stsClt := f.STSClient
if stsClt == nil {
stsClt = &STSClient{}
Expand Down
Loading
Loading