Skip to content

Commit

Permalink
Merge pull request #1044 from mmerkes/release-1.30
Browse files Browse the repository at this point in the history
Cherry-picked not topology labels for 1.30
  • Loading branch information
k8s-ci-robot authored Nov 1, 2024
2 parents 44bc107 + 98a9175 commit 2f4b2e2
Show file tree
Hide file tree
Showing 18 changed files with 741 additions and 178 deletions.
59 changes: 30 additions & 29 deletions cmd/ecr-credential-provider/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import (
"strings"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go/service/ecrpublic"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecrpublic"
"github.com/spf13/cobra"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -46,67 +46,68 @@ var ecrPrivateHostPattern = regexp.MustCompile(`^(\d{12})\.dkr\.ecr(\-fips)?\.([

// ECR abstracts the calls we make to aws-sdk for testing purposes
type ECR interface {
GetAuthorizationToken(input *ecr.GetAuthorizationTokenInput) (*ecr.GetAuthorizationTokenOutput, error)
GetAuthorizationToken(ctx context.Context, params *ecr.GetAuthorizationTokenInput, optFns ...func(*ecr.Options)) (*ecr.GetAuthorizationTokenOutput, error)
}

// ECRPublic abstracts the calls we make to aws-sdk for testing purposes
type ECRPublic interface {
GetAuthorizationToken(input *ecrpublic.GetAuthorizationTokenInput) (*ecrpublic.GetAuthorizationTokenOutput, error)
GetAuthorizationToken(ctx context.Context, params *ecrpublic.GetAuthorizationTokenInput, optFns ...func(*ecrpublic.Options)) (*ecrpublic.GetAuthorizationTokenOutput, error)
}

type ecrPlugin struct {
ecr ECR
ecrPublic ECRPublic
}

func defaultECRProvider(region string) (*ecr.ECR, error) {
cfg := aws.Config{}
func defaultECRProvider(ctx context.Context, region string) (ECR, error) {
var cfg aws.Config
var err error
if region != "" {
klog.Warningf("No region found in the image reference, the default region will be used. Please refer to AWS SDK documentation for configuration purpose.")
cfg.Region = aws.String(region)
cfg, err = config.LoadDefaultConfig(ctx,
config.WithRegion(region),
)
} else {
cfg, err = config.LoadDefaultConfig(ctx)
}
sess, err := session.NewSessionWithOptions(session.Options{
Config: cfg,
SharedConfigState: session.SharedConfigEnable,
})

if err != nil {
return nil, err
}

return ecr.New(sess), nil
return ecr.NewFromConfig(cfg), nil
}

func publicECRProvider() (*ecrpublic.ECRPublic, error) {
func publicECRProvider(ctx context.Context) (ECRPublic, error) {
// ECR public registries are only in one region and only accessible from regions
// in the "aws" partition.
sess, err := session.NewSessionWithOptions(session.Options{
Config: aws.Config{Region: aws.String(ecrPublicRegion)},
SharedConfigState: session.SharedConfigEnable,
})
cfg, err := config.LoadDefaultConfig(ctx,
config.WithRegion(ecrPublicRegion),
)
if err != nil {
return nil, err
}

return ecrpublic.New(sess), nil
return ecrpublic.NewFromConfig(cfg), nil
}

type credsData struct {
authToken *string
expiresAt *time.Time
}

func (e *ecrPlugin) getPublicCredsData() (*credsData, error) {
func (e *ecrPlugin) getPublicCredsData(ctx context.Context) (*credsData, error) {
klog.Infof("Getting creds for public registry")
var err error

if e.ecrPublic == nil {
e.ecrPublic, err = publicECRProvider()
e.ecrPublic, err = publicECRProvider(ctx)
}
if err != nil {
return nil, err
}

output, err := e.ecrPublic.GetAuthorizationToken(&ecrpublic.GetAuthorizationTokenInput{})
output, err := e.ecrPublic.GetAuthorizationToken(ctx, &ecrpublic.GetAuthorizationTokenInput{})
if err != nil {
return nil, err
}
Expand All @@ -125,18 +126,18 @@ func (e *ecrPlugin) getPublicCredsData() (*credsData, error) {
}, nil
}

func (e *ecrPlugin) getPrivateCredsData(imageHost string, image string) (*credsData, error) {
func (e *ecrPlugin) getPrivateCredsData(ctx context.Context, imageHost string, image string) (*credsData, error) {
klog.Infof("Getting creds for private image %s", image)
var err error

if e.ecr == nil {
region := parseRegionFromECRPrivateHost(imageHost)
e.ecr, err = defaultECRProvider(region)
e.ecr, err = defaultECRProvider(ctx, region)
if err != nil {
return nil, err
}
}
output, err := e.ecr.GetAuthorizationToken(&ecr.GetAuthorizationTokenInput{})
output, err := e.ecr.GetAuthorizationToken(ctx, &ecr.GetAuthorizationTokenInput{})
if err != nil {
return nil, err
}
Expand All @@ -162,9 +163,9 @@ func (e *ecrPlugin) GetCredentials(ctx context.Context, image string, args []str
}

if imageHost == ecrPublicHost {
creds, err = e.getPublicCredsData()
creds, err = e.getPublicCredsData(ctx)
} else {
creds, err = e.getPrivateCredsData(imageHost, image)
creds, err = e.getPrivateCredsData(ctx, imageHost, image)
}

if err != nil {
Expand All @@ -175,7 +176,7 @@ func (e *ecrPlugin) GetCredentials(ctx context.Context, image string, args []str
return nil, errors.New("authorization token in response was nil")
}

decodedToken, err := base64.StdEncoding.DecodeString(aws.StringValue(creds.authToken))
decodedToken, err := base64.StdEncoding.DecodeString(aws.ToString(creds.authToken))
if err != nil {
return nil, err
}
Expand Down
75 changes: 46 additions & 29 deletions cmd/ecr-credential-provider/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,50 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/aws/aws-sdk-go/service/ecrpublic"
"github.com/golang/mock/gomock"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/ecr"
"github.com/aws/aws-sdk-go-v2/service/ecr/types"
"github.com/aws/aws-sdk-go-v2/service/ecrpublic"
publictypes "github.com/aws/aws-sdk-go-v2/service/ecrpublic/types"
"github.com/stretchr/testify/mock"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/cloud-provider-aws/pkg/mocks"
v1 "k8s.io/kubelet/pkg/apis/credentialprovider/v1"
)

type MockedECR struct {
mock.Mock
}

func (m *MockedECR) GetAuthorizationToken(ctx context.Context, params *ecr.GetAuthorizationTokenInput, optFns ...func(*ecr.Options)) (*ecr.GetAuthorizationTokenOutput, error) {
args := m.Called(ctx, params)
if args.Get(1) != nil {
return args.Get(0).(*ecr.GetAuthorizationTokenOutput), args.Get(1).(error)
}
return args.Get(0).(*ecr.GetAuthorizationTokenOutput), nil
}

// ECRPublic abstracts the calls we make to aws-sdk for testing purposes
type MockedECRPublic struct {
mock.Mock
}

func (m *MockedECRPublic) GetAuthorizationToken(ctx context.Context, params *ecrpublic.GetAuthorizationTokenInput, optFns ...func(*ecrpublic.Options)) (*ecrpublic.GetAuthorizationTokenOutput, error) {
args := m.Called(ctx, params)
if args.Get(1) != nil {
return args.Get(0).(*ecrpublic.GetAuthorizationTokenOutput), args.Get(1).(error)
}
return args.Get(0).(*ecrpublic.GetAuthorizationTokenOutput), nil
}

func generatePrivateGetAuthorizationTokenOutput(user string, password string, proxy string, expiration *time.Time) *ecr.GetAuthorizationTokenOutput {
creds := []byte(fmt.Sprintf("%s:%s", user, password))
data := &ecr.AuthorizationData{
data := types.AuthorizationData{
AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString(creds)),
ExpiresAt: expiration,
ProxyEndpoint: aws.String(proxy),
}
output := &ecr.GetAuthorizationTokenOutput{
AuthorizationData: []*ecr.AuthorizationData{data},
AuthorizationData: []types.AuthorizationData{data},
}
return output
}
Expand All @@ -60,11 +86,6 @@ func generateResponse(registry string, username string, password string) *v1.Cre
}

func Test_GetCredentials_Private(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockECR := mocks.NewMockECR(ctrl)

testcases := []struct {
name string
image string
Expand Down Expand Up @@ -109,7 +130,7 @@ func Test_GetCredentials_Private(t *testing.T) {
{
name: "empty authorization token",
image: "123456789123.dkr.ecr.us-west-2.amazonaws.com",
getAuthorizationTokenOutput: &ecr.GetAuthorizationTokenOutput{AuthorizationData: []*ecr.AuthorizationData{{}}},
getAuthorizationTokenOutput: &ecr.GetAuthorizationTokenOutput{AuthorizationData: []types.AuthorizationData{{}}},
getAuthorizationTokenError: nil,
expectedError: errors.New("authorization token in response was nil"),
},
Expand All @@ -124,19 +145,19 @@ func Test_GetCredentials_Private(t *testing.T) {
name: "invalid authorization token",
image: "123456789123.dkr.ecr.us-west-2.amazonaws.com",
getAuthorizationTokenOutput: &ecr.GetAuthorizationTokenOutput{
AuthorizationData: []*ecr.AuthorizationData{
{AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString([]byte(fmt.Sprint("foo"))))},
AuthorizationData: []types.AuthorizationData{
{AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString([]byte("foo")))},
},
},
getAuthorizationTokenError: nil,
expectedError: errors.New("error parsing username and password from authorization token"),
},
}

for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
p := &ecrPlugin{ecr: mockECR}
mockECR.EXPECT().GetAuthorizationToken(gomock.Any()).Return(testcase.getAuthorizationTokenOutput, testcase.getAuthorizationTokenError)
mockECR := MockedECR{}
p := &ecrPlugin{ecr: &mockECR}
mockECR.On("GetAuthorizationToken", mock.Anything, mock.Anything).Return(testcase.getAuthorizationTokenOutput, testcase.getAuthorizationTokenError)

creds, err := p.GetCredentials(context.TODO(), testcase.image, testcase.args)

Expand All @@ -163,7 +184,7 @@ func Test_GetCredentials_Private(t *testing.T) {

func generatePublicGetAuthorizationTokenOutput(user string, password string, proxy string, expiration *time.Time) *ecrpublic.GetAuthorizationTokenOutput {
creds := []byte(fmt.Sprintf("%s:%s", user, password))
data := &ecrpublic.AuthorizationData{
data := &publictypes.AuthorizationData{
AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString(creds)),
ExpiresAt: expiration,
}
Expand All @@ -174,11 +195,6 @@ func generatePublicGetAuthorizationTokenOutput(user string, password string, pro
}

func Test_GetCredentials_Public(t *testing.T) {
ctrl := gomock.NewController(t)
defer ctrl.Finish()

mockECRPublic := mocks.NewMockECRPublic(ctrl)

testcases := []struct {
name string
image string
Expand Down Expand Up @@ -211,7 +227,7 @@ func Test_GetCredentials_Public(t *testing.T) {
{
name: "empty authorization token",
image: "public.ecr.aws",
getAuthorizationTokenOutput: &ecrpublic.GetAuthorizationTokenOutput{AuthorizationData: &ecrpublic.AuthorizationData{}},
getAuthorizationTokenOutput: &ecrpublic.GetAuthorizationTokenOutput{AuthorizationData: &publictypes.AuthorizationData{}},
getAuthorizationTokenError: nil,
expectedError: errors.New("authorization token in response was nil"),
},
Expand All @@ -226,8 +242,8 @@ func Test_GetCredentials_Public(t *testing.T) {
name: "invalid authorization token",
image: "public.ecr.aws",
getAuthorizationTokenOutput: &ecrpublic.GetAuthorizationTokenOutput{
AuthorizationData: &ecrpublic.AuthorizationData{
AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString([]byte(fmt.Sprint("foo")))),
AuthorizationData: &publictypes.AuthorizationData{
AuthorizationToken: aws.String(base64.StdEncoding.EncodeToString([]byte("foo"))),
},
},
getAuthorizationTokenError: nil,
Expand All @@ -237,8 +253,9 @@ func Test_GetCredentials_Public(t *testing.T) {

for _, testcase := range testcases {
t.Run(testcase.name, func(t *testing.T) {
p := &ecrPlugin{ecrPublic: mockECRPublic}
mockECRPublic.EXPECT().GetAuthorizationToken(gomock.Any()).Return(testcase.getAuthorizationTokenOutput, testcase.getAuthorizationTokenError)
mockECRPublic := MockedECRPublic{}
p := &ecrPlugin{ecrPublic: &mockECRPublic}
mockECRPublic.On("GetAuthorizationToken", mock.Anything, mock.Anything).Return(testcase.getAuthorizationTokenOutput, testcase.getAuthorizationTokenError)

creds, err := p.GetCredentials(context.TODO(), testcase.image, testcase.args)

Expand Down
1 change: 1 addition & 0 deletions docs/prerequisites.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ For the `aws-cloud-controller-manager` to be able to communicate to AWS APIs, yo
"ec2:DetachVolume",
"ec2:RevokeSecurityGroupIngress",
"ec2:DescribeVpcs",
"ec2:DescribeInstanceTopology",
"elasticloadbalancing:AddTags",
"elasticloadbalancing:AttachLoadBalancerToSubnets",
"elasticloadbalancing:ApplySecurityGroupsToLoadBalancer",
Expand Down
21 changes: 18 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ module k8s.io/cloud-provider-aws
go 1.22.7

require (
github.com/aws/aws-sdk-go v1.51.1
github.com/golang/mock v1.6.0
github.com/spf13/cobra v1.8.0
github.com/aws/aws-sdk-go v1.55.5
github.com/aws/aws-sdk-go-v2 v1.32.2
github.com/aws/aws-sdk-go-v2/config v1.28.0
github.com/aws/aws-sdk-go-v2/service/ecr v1.36.2
github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.27.2
github.com/spf13/cobra v1.8.1
github.com/spf13/pflag v1.0.5
github.com/stretchr/testify v1.9.0
golang.org/x/time v0.5.0
Expand All @@ -28,6 +31,18 @@ require (
github.com/NYTimes/gziphandler v1.1.1 // indirect
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230321174746-8dcc6526cfb1 // indirect
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.41 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.21 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.21 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
github.com/aws/aws-sdk-go-v2/service/ec2 v1.186.0
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.24.2 // indirect
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.32.2 // indirect
github.com/aws/smithy-go v1.22.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/blang/semver/v4 v4.0.0 // indirect
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
Expand Down
Loading

0 comments on commit 2f4b2e2

Please sign in to comment.