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 Redshift services to AWS SDK v2 #50600

Open
wants to merge 1 commit into
base: gavinfrazar/update-awsconfig
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 integrations/event-handler/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/kms v1.37.7 // indirect
github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0 // indirect
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0 // indirect
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 // indirect
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect
Expand Down
2 changes: 2 additions & 0 deletions integrations/event-handler/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,8 @@ github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0 h1:CVHfN8ZVvWzDkAf/Qj
github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0/go.mod h1:SVY+doFrL3KTvVMWzFLKvD7KYQ6GQfwNRPSQS7eA3cA=
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0 h1:W0gUYAjO24u/M6tpR041wMHJWGzleOhxtCnNLImdrZs=
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0/go.mod h1:ADD2uROOoEIXjbjDPEvDDZWnGmfKFYMddgKwG5RlBGw=
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0 h1:4/hmROBioc89sKlMVjHgOaH92zAkrAAMZR3BIvYwyD0=
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0/go.mod h1:UydVhUJOB/DaCJWiaBkPlvuzvWVcUlgbS2Bxn33bcKI=
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw=
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY=
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.1 h1:cfVjoEwOMOJOI6VoRQua0nI0KjZV9EAnR8bKaMeSppE=
Expand Down
1 change: 1 addition & 0 deletions integrations/terraform/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ require (
github.com/aws/aws-sdk-go-v2/service/kms v1.37.7 // indirect
github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0 // indirect
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0 // indirect
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0 // indirect
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 // indirect
github.com/aws/aws-sdk-go-v2/service/ssm v1.56.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect
Expand Down
2 changes: 2 additions & 0 deletions integrations/terraform/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,8 @@ github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0 h1:CVHfN8ZVvWzDkAf/Qj
github.com/aws/aws-sdk-go-v2/service/organizations v1.36.0/go.mod h1:SVY+doFrL3KTvVMWzFLKvD7KYQ6GQfwNRPSQS7eA3cA=
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0 h1:W0gUYAjO24u/M6tpR041wMHJWGzleOhxtCnNLImdrZs=
github.com/aws/aws-sdk-go-v2/service/rds v1.92.0/go.mod h1:ADD2uROOoEIXjbjDPEvDDZWnGmfKFYMddgKwG5RlBGw=
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0 h1:4/hmROBioc89sKlMVjHgOaH92zAkrAAMZR3BIvYwyD0=
github.com/aws/aws-sdk-go-v2/service/redshift v1.53.0/go.mod h1:UydVhUJOB/DaCJWiaBkPlvuzvWVcUlgbS2Bxn33bcKI=
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0 h1:nyuzXooUNJexRT0Oy0UQY6AhOzxPxhtt4DcBIHyCnmw=
github.com/aws/aws-sdk-go-v2/service/s3 v1.71.0/go.mod h1:sT/iQz8JK3u/5gZkT+Hmr7GzVZehUMkRZpOaAwYXeGY=
github.com/aws/aws-sdk-go-v2/service/sns v1.33.7 h1:N3o8mXK6/MP24BtD9sb51omEO9J9cgPM3Ughc293dZc=
Expand Down
4 changes: 2 additions & 2 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"

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/aws/aws-sdk-go/service/redshift"
"github.com/coreos/go-semver/semver"

"github.com/gravitational/teleport/lib/services"
Expand Down Expand Up @@ -244,7 +244,7 @@ func IsDBClusterAvailable(clusterStatus, clusterIndetifier *string) bool {
}

// IsRedshiftClusterAvailable checks if the Redshift cluster is available.
func IsRedshiftClusterAvailable(cluster *redshift.Cluster) bool {
func IsRedshiftClusterAvailable(cluster *redshifttypes.Cluster) bool {
// For a full list of status values, see:
// https://docs.aws.amazon.com/redshift/latest/mgmt/working-with-clusters.html#rs-mgmt-cluster-status
//
Expand Down
15 changes: 12 additions & 3 deletions lib/cloud/aws/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,23 @@ import (
"github.com/gravitational/trace"
)

// ConvertRequestFailureError converts `error` into AWS RequestFailure errors
// to trace errors. If the provided error is not an `RequestFailure` it returns
// the error without modifying it.
// ConvertRequestFailureError converts `err` into AWS errors to trace errors.
// If the provided error is not a [awserr.RequestFailure] it delegates
// error conversion to [ConvertRequestFailureErrorV2] for SDK v2 compatibility.
// Prefer using [ConvertRequestFailureErrorV2] directly for AWS SDK v2 client
// errors.
func ConvertRequestFailureError(err error) error {
var requestErr awserr.RequestFailure
if errors.As(err, &requestErr) {
return convertRequestFailureErrorFromStatusCode(requestErr.StatusCode(), requestErr)
}
return ConvertRequestFailureErrorV2(err)
}

// ConvertRequestFailureErrorV2 converts AWS SDK v2 errors to trace errors.
// If the provided error is not a [awshttp.ResponseError] it returns the error
// without modifying it.
func ConvertRequestFailureErrorV2(err error) error {
var re *awshttp.ResponseError
if errors.As(err, &re) {
return convertRequestFailureErrorFromStatusCode(re.HTTPStatusCode(), re.Err)
Expand Down
8 changes: 4 additions & 4 deletions lib/cloud/aws/tags_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ import (

ec2TypesV2 "github.com/aws/aws-sdk-go-v2/service/ec2/types"
rdsTypesV2 "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/redshift"
"github.com/aws/aws-sdk-go/service/redshiftserverless"
"github.com/aws/aws-sdk-go/service/secretsmanager"
"golang.org/x/exp/maps"
Expand All @@ -45,9 +45,9 @@ type ResourceTag interface {
// here and use a type switch for now.
rdsTypesV2.Tag |
ec2TypesV2.Tag |
redshifttypes.Tag |
*ec2.Tag |
*rds.Tag |
*redshift.Tag |
*elasticache.Tag |
*memorydb.Tag |
*redshiftserverless.Tag |
Expand Down Expand Up @@ -80,8 +80,6 @@ func resourceTagToKeyValue[Tag ResourceTag](tag Tag) (string, string) {
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *ec2.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *redshift.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *elasticache.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *memorydb.Tag:
Expand All @@ -92,6 +90,8 @@ func resourceTagToKeyValue[Tag ResourceTag](tag Tag) (string, string) {
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case ec2TypesV2.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case redshifttypes.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *opensearchservice.Tag:
return aws.StringValue(v.Key), aws.StringValue(v.Value)
case *secretsmanager.Tag:
Expand Down
45 changes: 45 additions & 0 deletions lib/cloud/awstesthelpers/tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package awstesthelpers

import (
"maps"
"slices"

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

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

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

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

return ret
}
23 changes: 0 additions & 23 deletions lib/cloud/clients.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ import (
"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/redshift"
"github.com/aws/aws-sdk-go/service/redshift/redshiftiface"
"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 @@ -115,8 +113,6 @@ type AWSClients interface {
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)
// GetAWSRedshiftClient returns AWS Redshift client for the specified region.
GetAWSRedshiftClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftiface.RedshiftAPI, 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 @@ -517,15 +513,6 @@ func (c *cloudClients) GetAWSRDSClient(ctx context.Context, region string, opts
return rds.New(session), nil
}

// GetAWSRedshiftClient returns AWS Redshift client for the specified region.
func (c *cloudClients) GetAWSRedshiftClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftiface.RedshiftAPI, error) {
session, err := c.GetAWSSession(ctx, region, opts...)
if err != nil {
return nil, trace.Wrap(err)
}
return redshift.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 @@ -1033,7 +1020,6 @@ var _ Clients = (*TestCloudClients)(nil)
type TestCloudClients struct {
RDS rdsiface.RDSAPI
RDSPerRegion map[string]rdsiface.RDSAPI
Redshift redshiftiface.RedshiftAPI
RedshiftServerless redshiftserverlessiface.RedshiftServerlessAPI
ElastiCache elasticacheiface.ElastiCacheAPI
OpenSearch opensearchserviceiface.OpenSearchServiceAPI
Expand Down Expand Up @@ -1115,15 +1101,6 @@ func (c *TestCloudClients) GetAWSRDSClient(ctx context.Context, region string, o
return c.RDS, nil
}

// GetAWSRedshiftClient returns AWS Redshift client for the specified region.
func (c *TestCloudClients) GetAWSRedshiftClient(ctx context.Context, region string, opts ...AWSOptionsFn) (redshiftiface.RedshiftAPI, error) {
_, err := c.GetAWSSession(ctx, region, opts...)
if err != nil {
return nil, trace.Wrap(err)
}
return c.Redshift, 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
18 changes: 9 additions & 9 deletions lib/cloud/mocks/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ import (
"github.com/gravitational/trace"
)

// STSMock mocks AWS STS API.
type STSMock struct {
// STSClientV1 mocks AWS STS API for AWS SDK v1.
type STSClientV1 struct {
stsiface.STSAPI
ARN string
URL *url.URL
Expand All @@ -47,36 +47,36 @@ type STSMock struct {
mu sync.Mutex
}

func (m *STSMock) GetAssumedRoleARNs() []string {
func (m *STSClientV1) GetAssumedRoleARNs() []string {
m.mu.Lock()
defer m.mu.Unlock()
return m.assumedRoleARNs
}

func (m *STSMock) GetAssumedRoleExternalIDs() []string {
func (m *STSClientV1) GetAssumedRoleExternalIDs() []string {
m.mu.Lock()
defer m.mu.Unlock()
return m.assumedRoleExternalIDs
}

func (m *STSMock) ResetAssumeRoleHistory() {
func (m *STSClientV1) ResetAssumeRoleHistory() {
m.mu.Lock()
defer m.mu.Unlock()
m.assumedRoleARNs = nil
m.assumedRoleExternalIDs = nil
}

func (m *STSMock) GetCallerIdentityWithContext(aws.Context, *sts.GetCallerIdentityInput, ...request.Option) (*sts.GetCallerIdentityOutput, error) {
func (m *STSClientV1) GetCallerIdentityWithContext(aws.Context, *sts.GetCallerIdentityInput, ...request.Option) (*sts.GetCallerIdentityOutput, error) {
return &sts.GetCallerIdentityOutput{
Arn: aws.String(m.ARN),
}, nil
}

func (m *STSMock) AssumeRole(in *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
func (m *STSClientV1) AssumeRole(in *sts.AssumeRoleInput) (*sts.AssumeRoleOutput, error) {
return m.AssumeRoleWithContext(context.Background(), in)
}

func (m *STSMock) AssumeRoleWithContext(ctx aws.Context, in *sts.AssumeRoleInput, _ ...request.Option) (*sts.AssumeRoleOutput, error) {
func (m *STSClientV1) AssumeRoleWithContext(ctx aws.Context, in *sts.AssumeRoleInput, _ ...request.Option) (*sts.AssumeRoleOutput, error) {
m.mu.Lock()
defer m.mu.Unlock()
if !slices.Contains(m.assumedRoleARNs, aws.StringValue(in.RoleArn)) {
Expand All @@ -94,7 +94,7 @@ func (m *STSMock) AssumeRoleWithContext(ctx aws.Context, in *sts.AssumeRoleInput
}, nil
}

func (m *STSMock) GetCallerIdentityRequest(req *sts.GetCallerIdentityInput) (*request.Request, *sts.GetCallerIdentityOutput) {
func (m *STSClientV1) GetCallerIdentityRequest(req *sts.GetCallerIdentityInput) (*request.Request, *sts.GetCallerIdentityOutput) {
return &request.Request{
HTTPRequest: &http.Request{
Header: http.Header{},
Expand Down
54 changes: 54 additions & 0 deletions lib/cloud/mocks/aws_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Teleport
* Copyright (C) 2024 Gravitational, Inc.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package mocks

import (
"context"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/credentials/stscreds"

"github.com/gravitational/teleport/lib/cloud/awsconfig"
)

type AWSConfigProvider struct {
STSClient *STSClient
}

func (f *AWSConfigProvider) GetConfig(ctx context.Context, region string, optFns ...awsconfig.OptionsFn) (aws.Config, error) {
stsClt := f.STSClient
if stsClt == nil {
stsClt = &STSClient{}
}
optFns = append(optFns, awsconfig.WithAssumeRoleClientProviderFunc(func(cfg aws.Config) stscreds.AssumeRoleAPIClient {
if cfg.Credentials != nil {
if _, ok := cfg.Credentials.(*stscreds.AssumeRoleProvider); ok {
// Create a new fake client linked to the old one.
// Only do this for AssumeRoleProvider, to avoid attempting to
// load the real credential chain.
return &STSClient{
credentialProvider: cfg.Credentials,
root: stsClt,
}
}
}
return stsClt
}))
return awsconfig.GetConfig(ctx, region, optFns...)
}
Loading
Loading