Skip to content

Migrate ACS to sdk-go-v2 #4534

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

Merged
merged 6 commits into from
Mar 31, 2025
Merged
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
6 changes: 3 additions & 3 deletions agent/acs/session/attach_instance_eni_responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/aws/amazon-ecs-agent/ecs-agent/api/attachment"
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -81,7 +81,7 @@ func TestInstanceENIAckHappyPath(t *testing.T) {
go handleAttachMessage(testAttachInstanceENIMessage)

attachInstanceEniAckSent := <-ackSent
assert.Equal(t, aws.StringValue(attachInstanceEniAckSent.MessageId), testconst.MessageID)
assert.Equal(t, aws.ToString(attachInstanceEniAckSent.MessageId), testconst.MessageID)
}

// TestInstanceENIAckSingleMessageWithDuplicateENIAttachment tests the path for an
Expand Down Expand Up @@ -137,5 +137,5 @@ func TestInstanceENIAckSingleMessageWithDuplicateENIAttachment(t *testing.T) {

attachInstanceEniAckSent := <-ackSent
wg.Wait()
assert.Equal(t, aws.StringValue(attachInstanceEniAckSent.MessageId), testconst.MessageID)
assert.Equal(t, aws.ToString(attachInstanceEniAckSent.MessageId), testconst.MessageID)
}
6 changes: 3 additions & 3 deletions agent/acs/session/attach_task_eni_responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
"testing"
"time"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"

Expand Down Expand Up @@ -81,7 +81,7 @@ func TestTaskENIAckHappyPath(t *testing.T) {
go handleAttachMessage(testAttachTaskENIMessage)

attachTaskEniAckSent := <-ackSent
assert.Equal(t, aws.StringValue(attachTaskEniAckSent.MessageId), testconst.MessageID)
assert.Equal(t, aws.ToString(attachTaskEniAckSent.MessageId), testconst.MessageID)
}

// TestTaskENIAckSingleMessageWithDuplicateENIAttachment tests the path for an
Expand Down Expand Up @@ -136,5 +136,5 @@ func TestTaskENIAckSingleMessageWithDuplicateENIAttachment(t *testing.T) {

attachTaskEniAckSent := <-ackSent
wg.Wait()
assert.Equal(t, aws.StringValue(attachTaskEniAckSent.MessageId), testconst.MessageID)
assert.Equal(t, aws.ToString(attachTaskEniAckSent.MessageId), testconst.MessageID)
}
16 changes: 8 additions & 8 deletions agent/acs/session/payload_responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
nlappmesh "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/appmesh"
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -104,7 +104,7 @@ func (pmHandler *payloadMessageHandler) addPayloadTasks(payload *ecsacs.PayloadM
for _, task := range payload.Tasks {
if task == nil {
logger.Critical("Received nil task for message", logger.Fields{
loggerfield.MessageID: aws.StringValue(payload.MessageId),
loggerfield.MessageID: aws.ToString(payload.MessageId),
})
allTasksOK = false
continue
Expand Down Expand Up @@ -146,7 +146,7 @@ func (pmHandler *payloadMessageHandler) addPayloadTasks(payload *ecsacs.PayloadM
credentials.ApplicationRoleType)
err = pmHandler.credentialsManager.SetTaskCredentials(
&(credentials.TaskIAMRoleCredentials{
ARN: aws.StringValue(task.Arn),
ARN: aws.ToString(task.Arn),
IAMRoleCredentials: taskIAMRoleCredentials,
}))
if err != nil {
Expand Down Expand Up @@ -194,7 +194,7 @@ func (pmHandler *payloadMessageHandler) addPayloadTasks(payload *ecsacs.PayloadM
credentials.ExecutionRoleType)
err = pmHandler.credentialsManager.SetTaskCredentials(
&(credentials.TaskIAMRoleCredentials{
ARN: aws.StringValue(task.Arn),
ARN: aws.ToString(task.Arn),
IAMRoleCredentials: taskExecutionIAMRoleCredentials,
}))
if err != nil {
Expand Down Expand Up @@ -235,14 +235,14 @@ func (pmHandler *payloadMessageHandler) addPayloadTasks(payload *ecsacs.PayloadM
func (pmHandler *payloadMessageHandler) handleInvalidTask(task *ecsacs.Task, err error,
payload *ecsacs.PayloadMessage) {
logger.Warn("Received unexpected ACS message", logger.Fields{
loggerfield.MessageID: aws.StringValue(payload.MessageId),
loggerfield.TaskARN: aws.StringValue(task.Arn),
loggerfield.MessageID: aws.ToString(payload.MessageId),
loggerfield.TaskARN: aws.ToString(task.Arn),
loggerfield.Error: err,
})

if aws.StringValue(task.Arn) == "" {
if aws.ToString(task.Arn) == "" {
logger.Critical("Received task with no ARN for payload message", logger.Fields{
loggerfield.MessageID: aws.StringValue(payload.MessageId),
loggerfield.MessageID: aws.ToString(payload.MessageId),
})
return
}
Expand Down
28 changes: 14 additions & 14 deletions agent/acs/session/payload_responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import (
ni "github.com/aws/amazon-ecs-agent/ecs-agent/netlib/model/networkinterface"
"github.com/aws/amazon-ecs-agent/ecs-agent/wsclient"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
Expand Down Expand Up @@ -404,7 +404,7 @@ func TestHandlePayloadMessageCredentialsAckedWhenTaskAddedMultipleTasks(t *testi
var payloadMessageResp *ecsacs.AckRequest
credentialsResp, ok := response.(*ecsacs.IAMRoleCredentialsAckRequest)
if ok {
switch aws.StringValue(credentialsResp.CredentialsId) {
switch aws.ToString(credentialsResp.CredentialsId) {
case firstTaskCredentialsId:
firstCredentialsAckSent <- credentialsResp
case secondTaskCredentialsId:
Expand Down Expand Up @@ -649,12 +649,12 @@ func TestHandlePayloadMessageAddedENIToTask(t *testing.T) {
// Validate the added task has the ENI information as expected.
expectedENI := testPayloadMessage.Tasks[0].ElasticNetworkInterfaces[0]
taskeni := addedTask.GetPrimaryENI()
assert.Equal(t, aws.StringValue(expectedENI.Ec2Id), taskeni.ID)
assert.Equal(t, aws.StringValue(expectedENI.MacAddress), taskeni.MacAddress)
assert.Equal(t, aws.ToString(expectedENI.Ec2Id), taskeni.ID)
assert.Equal(t, aws.ToString(expectedENI.MacAddress), taskeni.MacAddress)
assert.Equal(t, 1, len(taskeni.IPV4Addresses))
assert.Equal(t, 1, len(taskeni.IPV6Addresses))
assert.Equal(t, aws.StringValue(expectedENI.Ipv4Addresses[0].PrivateAddress), taskeni.IPV4Addresses[0].Address)
assert.Equal(t, aws.StringValue(expectedENI.Ipv6Addresses[0].Address), taskeni.IPV6Addresses[0].Address)
assert.Equal(t, aws.ToString(expectedENI.Ipv4Addresses[0].PrivateAddress), taskeni.IPV4Addresses[0].Address)
assert.Equal(t, aws.ToString(expectedENI.Ipv6Addresses[0].Address), taskeni.IPV6Addresses[0].Address)
}

func TestHandlePayloadMessageAddedEBSToTask(t *testing.T) {
Expand Down Expand Up @@ -949,9 +949,9 @@ func TestHandlePayloadMessageAddedECRAuthData(t *testing.T) {
actual := addedTask.Containers[0].RegistryAuthentication
assert.NotNil(t, actual.ECRAuthData)
assert.Nil(t, actual.ASMAuthData)
assert.Equal(t, aws.StringValue(expected.Type), actual.Type)
assert.Equal(t, aws.StringValue(expected.EcrAuthData.Region), actual.ECRAuthData.Region)
assert.Equal(t, aws.StringValue(expected.EcrAuthData.RegistryId), actual.ECRAuthData.RegistryID)
assert.Equal(t, aws.ToString(expected.Type), actual.Type)
assert.Equal(t, aws.ToString(expected.EcrAuthData.Region), actual.ECRAuthData.Region)
assert.Equal(t, aws.ToString(expected.EcrAuthData.RegistryId), actual.ECRAuthData.RegistryID)
}

func TestHandlePayloadMessageAddedASMAuthData(t *testing.T) {
Expand Down Expand Up @@ -1001,9 +1001,9 @@ func TestHandlePayloadMessageAddedASMAuthData(t *testing.T) {
actual := addedTask.Containers[0].RegistryAuthentication
assert.NotNil(t, actual.ASMAuthData)
assert.Nil(t, actual.ECRAuthData)
assert.Equal(t, aws.StringValue(expected.Type), actual.Type)
assert.Equal(t, aws.StringValue(expected.AsmAuthData.Region), actual.ASMAuthData.Region)
assert.Equal(t, aws.StringValue(expected.AsmAuthData.CredentialsParameter), actual.ASMAuthData.CredentialsParameter)
assert.Equal(t, aws.ToString(expected.Type), actual.Type)
assert.Equal(t, aws.ToString(expected.AsmAuthData.Region), actual.ASMAuthData.Region)
assert.Equal(t, aws.ToString(expected.AsmAuthData.CredentialsParameter), actual.ASMAuthData.CredentialsParameter)
}

func TestHandlePayloadMessageAddedFirelensData(t *testing.T) {
Expand Down Expand Up @@ -1050,9 +1050,9 @@ func TestHandlePayloadMessageAddedFirelensData(t *testing.T) {
// Validate the pieces of the Firelens container.
expected := testPayloadMessage.Tasks[0].Containers[0].FirelensConfiguration
actual := addedTask.Containers[0].FirelensConfig
assert.Equal(t, aws.StringValue(expected.Type), actual.Type)
assert.Equal(t, aws.ToString(expected.Type), actual.Type)
assert.NotNil(t, actual.Options)
assert.Equal(t, aws.StringValue(expected.Options["enable-ecs-log-metadata"]),
assert.Equal(t, aws.ToString(expected.Options["enable-ecs-log-metadata"]),
actual.Options["enable-ecs-log-metadata"])
}

Expand Down
14 changes: 7 additions & 7 deletions agent/acs/session/refresh_credentials_responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ package session
import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/pkg/errors"

apitask "github.com/aws/amazon-ecs-agent/agent/api/task"
Expand Down Expand Up @@ -48,7 +48,7 @@ func (cmSetter *credentialsMetadataSetter) SetTaskRoleCredentialsMetadata(
if err != nil {
return err
}
task.SetCredentialsID(aws.StringValue(message.RoleCredentials.CredentialsId))
task.SetCredentialsID(aws.ToString(message.RoleCredentials.CredentialsId))
return nil
}

Expand All @@ -58,23 +58,23 @@ func (cmSetter *credentialsMetadataSetter) SetExecRoleCredentialsMetadata(
if err != nil {
return errors.Wrap(err, "unable to get credentials message's task")
}
task.SetExecutionRoleCredentialsID(aws.StringValue(message.RoleCredentials.CredentialsId))
task.SetExecutionRoleCredentialsID(aws.ToString(message.RoleCredentials.CredentialsId))

// Refresh domainless gMSA plugin credentials if needed.
err = checkAndSetDomainlessGMSATaskExecutionRoleCredentialsImpl(credentials.IAMRoleCredentialsFromACS(
message.RoleCredentials, aws.StringValue(message.RoleType)), task)
message.RoleCredentials, aws.ToString(message.RoleType)), task)
if err != nil {
return errors.Wrap(err, fmt.Sprintf("unable to set %s for task with ARN %s",
"DomainlessGMSATaskExecutionRoleCredentials", aws.StringValue(message.TaskArn)))
"DomainlessGMSATaskExecutionRoleCredentials", aws.ToString(message.TaskArn)))
}

return nil
}

func (cmSetter *credentialsMetadataSetter) getCredentialsMessageTask(
message *ecsacs.IAMRoleCredentialsMessage) (*apitask.Task, error) {
taskARN := aws.StringValue(message.TaskArn)
messageID := aws.StringValue(message.MessageId)
taskARN := aws.ToString(message.TaskArn)
messageID := aws.ToString(message.MessageId)
task, ok := cmSetter.taskEngine.GetTaskByArn(taskARN)
if !ok {
return nil, errors.Errorf(
Expand Down
2 changes: 1 addition & 1 deletion agent/acs/session/refresh_credentials_responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import (
"github.com/aws/amazon-ecs-agent/ecs-agent/acs/session/testconst"
"github.com/aws/amazon-ecs-agent/ecs-agent/credentials"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
Expand Down
2 changes: 1 addition & 1 deletion agent/acs/session/task_manifest_responder.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"github.com/aws/amazon-ecs-agent/agent/engine"
"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
apitaskstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/task/status"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
)

// taskComparer implements the TaskComparer interface defined in ecs-agent module.
Expand Down
2 changes: 1 addition & 1 deletion agent/acs/session/task_manifest_responder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
apitaskstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/task/status"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
"github.com/aws/amazon-ecs-agent/ecs-agent/wsclient"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import (
apicontainerstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/container/status"
apitaskstatus "github.com/aws/amazon-ecs-agent/ecs-agent/api/task/status"
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/stretchr/testify/require"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (
"github.com/aws/amazon-ecs-agent/ecs-agent/metrics"
"github.com/aws/amazon-ecs-agent/ecs-agent/wsclient"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/golang/mock/gomock"
"github.com/stretchr/testify/assert"
)
Expand Down
2 changes: 1 addition & 1 deletion agent/acs/updater/updater.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ import (
"github.com/aws/amazon-ecs-agent/ecs-agent/utils/ttime"
"github.com/aws/amazon-ecs-agent/ecs-agent/wsclient"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/cihub/seelog"
)

Expand Down
12 changes: 6 additions & 6 deletions agent/api/appmesh/appmesh.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
"strings"

"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
)

const (
Expand Down Expand Up @@ -62,11 +62,11 @@ func AppMeshFromACS(proxyConfig *ecsacs.ProxyConfiguration) (*AppMesh, error) {
}

return &AppMesh{
ContainerName: aws.StringValue(proxyConfig.ContainerName),
IgnoredUID: aws.StringValue(proxyConfig.Properties[ignoredUID]),
IgnoredGID: aws.StringValue(proxyConfig.Properties[ignoredGID]),
ProxyIngressPort: aws.StringValue(proxyConfig.Properties[proxyIngressPort]),
ProxyEgressPort: aws.StringValue(proxyConfig.Properties[proxyEgressPort]),
ContainerName: aws.ToString(proxyConfig.ContainerName),
IgnoredUID: aws.ToString(proxyConfig.Properties[ignoredUID]),
IgnoredGID: aws.ToString(proxyConfig.Properties[ignoredGID]),
ProxyIngressPort: aws.ToString(proxyConfig.Properties[proxyIngressPort]),
ProxyEgressPort: aws.ToString(proxyConfig.Properties[proxyEgressPort]),
AppPorts: buildAppPorts(proxyConfig),
EgressIgnoredIPs: buildEgressIgnoredIPs(proxyConfig),
EgressIgnoredPorts: buildEgressIgnoredPorts(proxyConfig),
Expand Down
2 changes: 1 addition & 1 deletion agent/api/appmesh/appmesh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (
"testing"

"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/stretchr/testify/assert"
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import (

"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
"github.com/aws/amazon-ecs-agent/ecs-agent/logger"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
)

const (
Expand Down Expand Up @@ -47,19 +47,19 @@ func ParseServiceConnectAttachment(scAttachment *ecsacs.Attachment) (*Config, er
foundSCContainerNameKey := false

for _, property := range scAttachment.AttachmentProperties {
switch aws.StringValue(property.Name) {
switch aws.ToString(property.Name) {
case serviceConnectConfigKey:
foundSCConfigKey = true
// extract service connect config value from the attachment property,
// and translate the attachment property value to Config
data := aws.StringValue(property.Value)
data := aws.ToString(property.Value)
if err := json.Unmarshal([]byte(data), scConfigValue); err != nil {
return nil, fmt.Errorf("failed to unmarshal service connect attachment property value: %w", err)
}
case serviceConnectContainerNameKey:
foundSCContainerNameKey = true
// extract service connect container name from the attachment property
containerName = aws.StringValue(property.Value)
containerName = aws.ToString(property.Value)
default:
logger.Warn("Received an unrecognized attachment property", logger.Fields{
"attachmentProperty": property.String(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import (
"strconv"

"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
"github.com/stretchr/testify/assert"
)

Expand Down
12 changes: 6 additions & 6 deletions agent/api/serviceconnect/service_connect_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import (

"github.com/aws/amazon-ecs-agent/ecs-agent/acs/model/ecsacs"
"github.com/aws/amazon-ecs-agent/ecs-agent/logger"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go-v2/aws"
)

const (
Expand Down Expand Up @@ -50,7 +50,7 @@ func validateContainerName(scContainerName string, taskContainers []*ecsacs.Cont
// validate the specified service connect container name exists in the task
numOfFoundScContainer := 0
for _, container := range taskContainers {
if aws.StringValue(container.Name) == scContainerName {
if aws.ToString(container.Name) == scContainerName {
numOfFoundScContainer += 1
}
}
Expand Down Expand Up @@ -195,14 +195,14 @@ func validateIngressConfigEntry(scIngressConfigList []IngressConfigEntry, networ
logger.Warn(warningMsg, logger.Fields{
"listenerName": entry.ListenerName,
"listenerPort": entry.ListenerPort,
"hostPort": aws.Uint16Value(entry.HostPort),
"interceptPort": aws.Uint16Value(entry.InterceptPort),
"hostPort": aws.ToUint16(entry.HostPort),
"interceptPort": aws.ToUint16(entry.InterceptPort),
})
}

// verify the intercept port for awsvpc mode
if entry.InterceptPort != nil && networkMode == AWSVPCNetworkMode {
interceptPortValue = aws.Uint16Value(entry.InterceptPort)
interceptPortValue = aws.ToUint16(entry.InterceptPort)
if err := validateInterceptPort(interceptPortValue, entry.ListenerName, interceptAndListenerPortsMap); err != nil {
return err
}
Expand All @@ -222,7 +222,7 @@ func validateIngressConfigEntry(scIngressConfigList []IngressConfigEntry, networ

// verify the host port for bridge mode
if entry.HostPort != nil && networkMode == BridgeNetworkMode {
hostPortValue = aws.Uint16Value(entry.HostPort)
hostPortValue = aws.ToUint16(entry.HostPort)
if err := validateHostPort(hostPortValue, entry.ListenerName, hostPortsMap); err != nil {
return err
}
Expand Down
Loading
Loading