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

Add scrapping ECS_CONTAINER_METADATA_URI_V4 for ECS #453

Merged
merged 29 commits into from
May 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
41bcb1a
Add metadata point v4 and delete run in aws
khanhntd Apr 20, 2022
771ab69
Add log and delete flag
khanhntd Apr 22, 2022
4a3d227
Add some interface and add final endpoint v4
khanhntd Apr 22, 2022
dc97cff
Fix some typo and add interface
khanhntd Apr 22, 2022
13ca933
Fix typo
khanhntd Apr 22, 2022
bb5ec63
Delete apply interface
khanhntd Apr 22, 2022
39d79d1
Delete interface and debug
khanhntd Apr 22, 2022
8302a6e
Delete Ecs Util instance variable
khanhntd Apr 22, 2022
a080fcd
Add back ecsUtilInstance
khanhntd Apr 22, 2022
16d8af8
Add type assertion
khanhntd Apr 22, 2022
8713b5b
Delete type assertion
khanhntd Apr 22, 2022
d750aed
Add type assertion again
khanhntd Apr 22, 2022
5644636
Delete type assertion
khanhntd Apr 22, 2022
d77b840
Fix typo and nitpick
khanhntd Apr 22, 2022
50c4774
Add back mode EC2
khanhntd Apr 23, 2022
e28fef6
Add runinAws
khanhntd Apr 23, 2022
a483a6f
Add type assertion
khanhntd Apr 23, 2022
90ab672
Add type assertion
khanhntd Apr 23, 2022
e013ce1
delete type interface
khanhntd Apr 23, 2022
a5737cc
Add log for validating
khanhntd Apr 29, 2022
84f36d8
change to parse ecs region
khanhntd Apr 29, 2022
5d6f694
Build back image
khanhntd Apr 29, 2022
866f1b5
Revert back to original
khanhntd Apr 29, 2022
38845aa
Add back strings
khanhntd Apr 29, 2022
1bbd660
Add parseClusterName
khanhntd Apr 29, 2022
c3bfe4e
Parse the cluster
khanhntd Apr 29, 2022
b328b91
Delete parse cluster
khanhntd May 2, 2022
30098af
Delete go proxy
khanhntd May 2, 2022
9d414c9
Fix testing
khanhntd May 3, 2022
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
2 changes: 1 addition & 1 deletion cmd/config-downloader/downloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ func main() {
outputDir,
func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("Cannot access %v: %v", path, err)
fmt.Printf("Cannot access %v: %v \n", path, err)
return err
}
if info.IsDir() {
Expand Down
1 change: 1 addition & 0 deletions plugins/processors/ecsdecorator/ecsinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ func (e *ecsInfo) getMemReserved() int64 {
func newECSInfo(hostIP string) (e *ecsInfo) {
e = &ecsInfo{hostIP: hostIP, refreshInterval: 1 * time.Minute, shutdownC: make(chan bool), httpClient: httpclient.New()}
containerInstance := e.getContainerInstanceInfo()
//Sample Cluster Name: https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-introspection.html
e.clusterName = containerInstance.Cluster
e.containerInstanceId = e.getContainerInstanceIdFromArn(containerInstance.ContainerInstanceArn)
e.cgroup = newCGroupScannerForContainer()
Expand Down
2 changes: 1 addition & 1 deletion translator/cmdutil/translatorutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ func GenerateMergedJsonConfigMap(ctx *context.Context) (map[string]interface{},
ctx.InputJsonDirPath(),
func(path string, info os.FileInfo, err error) error {
if err != nil {
fmt.Printf("Cannot access %v: %v", path, err)
fmt.Printf("Cannot access %v: %v \n", path, err)
return err
}
if info.Mode()&os.ModeSymlink != 0 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ func (d *LogGroupName) ApplyRule(input interface{}) (string, interface{}) {

if context.CurrentContext().RunInContainer() {
if ecsutil.GetECSUtilSingleton().IsECS() {
clusterName := util.GetECSClusterNameFromEnv()
clusterName := ecsutil.GetECSUtilSingleton().Cluster
if clusterName != "" {
lgName = fmt.Sprintf(ECSLogGroupNameFormat, clusterName)
}
Expand Down
16 changes: 1 addition & 15 deletions translator/translate/logs/util/get_ecs_cluster_name.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
package util

import (
"strings"

"github.com/aws/amazon-cloudwatch-agent/translator/util/ecsutil"
)

Expand All @@ -17,19 +15,7 @@ func GetECSClusterName(sectionKey string, input map[string]interface{}) string {
}

if clusterName == "" {
clusterName = GetECSClusterNameFromEnv()
}
return clusterName
}

func GetECSClusterNameFromEnv() string {
var clusterName string
if ecsutil.GetECSUtilSingleton().IsECS() {
clusterName = ecsutil.GetECSUtilSingleton().Cluster
res := strings.Split(clusterName, "/")
if len(res) > 0 {
clusterName = res[len(res)-1]
}
}
return clusterName
}
}
33 changes: 25 additions & 8 deletions translator/util/ecsutil/ecsutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
const (
v2MetadataEndpoint = "http://169.254.170.2/v2/metadata"
v3MetadataEndpointEnv = "ECS_CONTAINER_METADATA_URI"
v4MetadataEndpointEnv = "ECS_CONTAINER_METADATA_URI_V4"
)

type ecsMetadataResponse struct {
Expand All @@ -32,6 +33,7 @@ type ecsUtil struct {
}

var ecsUtilInstance *ecsUtil

var ecsUtilOnce sync.Once

func GetECSUtilSingleton() *ecsUtil {
Expand All @@ -48,13 +50,14 @@ func initECSUtilSingleton() (newInstance *ecsUtil) {
}
log.Println("I! attempt to access ECS task metadata to determine whether I'm running in ECS.")
ecsMetadataResponse, err := newInstance.getECSMetadata()

if err != nil {
log.Printf("I! access ECS task metadata fail with response %v, assuming I'm not running in ECS.\n", err)
return
}

newInstance.parseRegion(ecsMetadataResponse)
newInstance.Cluster = ecsMetadataResponse.Cluster
newInstance.parseClusterName(ecsMetadataResponse)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally, I prefer explicitly setting the value like it did originally rather than expecting that the parseClusterName sets the value for the Cluster field, but I'm fine with this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer the same since its does not directly use the Cluster Name but the Cluster ARN in this case. Therefore, implicitly setting the value would be fine as long as its clarify the meaning though.

newInstance.TaskARN = ecsMetadataResponse.TaskARN
return

Expand All @@ -65,26 +68,29 @@ func (e *ecsUtil) IsECS() bool {
}

func (e *ecsUtil) getECSMetadata() (em *ecsMetadataResponse, err error) {
// choose available endpoint
if v3MetadataEndpoint, ok := os.LookupEnv(v3MetadataEndpointEnv); !ok {
em, err = e.getMetadataResponse(v2MetadataEndpoint)
} else {
// Based on endpoint to get ECS metadata, for more information on the respond, https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-metadata-endpoint.html
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need to support v2 and v3? If endpoint is there but get metadata fails should we fall back?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IDC either way.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we still need to support v2 and v3 so long as people can create ECS clusters that still rely on them. I think we'd have to investigate further where the drop off points are for v2 and v3 before we could take out support for them.

if v4MetadataEndpoint, ok := os.LookupEnv(v4MetadataEndpointEnv); ok {
em, err = e.getMetadataResponse(v4MetadataEndpoint + "/task")
khanhntd marked this conversation as resolved.
Show resolved Hide resolved
} else if v3MetadataEndpoint, ok := os.LookupEnv(v3MetadataEndpointEnv); ok {
em, err = e.getMetadataResponse(v3MetadataEndpoint + "/task")
} else {
em, err = e.getMetadataResponse(v2MetadataEndpoint)
}
return
}

func (e *ecsUtil) getMetadataResponse(endpoint string) (em *ecsMetadataResponse, err error) {
em = &ecsMetadataResponse{}
resp, err := e.httpClient.Request(endpoint)

if err != nil {
return
}

err = json.Unmarshal(resp, em)
if err != nil {
log.Printf("E! unable to parse resp from ecsmetadata endpoint, error: %v", err)
log.Printf("D! resp content is %s", string(resp))
log.Printf("E! Unable to parse response from ecsmetadata endpoint, error: %v", err)
log.Printf("D! Content is %s", string(resp))
}
return
}
Expand All @@ -97,7 +103,18 @@ func (e *ecsUtil) parseRegion(em *ecsMetadataResponse) {
splitedContent := strings.Split(em.TaskARN, ":")
// When splitting the ARN with ":", the 4th segment is the region
if len(splitedContent) < 4 {
log.Printf("E! invalid ecs task arn: %s", em.TaskARN)
log.Printf("E! Invalid ecs task arn: %s", em.TaskARN)
}
e.Region = splitedContent[3]
}

// There is only one format for ClusterArn (https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_Cluster.html)
// arn:aws:ecs:region:aws_account_id:cluster/cluster-name
func (e *ecsUtil) parseClusterName(em *ecsMetadataResponse) {
splitedContent := strings.Split(em.Cluster, "/")
// When splitting the ClusterName with /, the last is always the cluster name
if len(splitedContent) == 0 {
log.Printf("E! Invalid cluster arn: %s", em.Cluster)
}
Comment on lines +116 to +118
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the ARN is invalid, should we still try to assign the cluster ARN to the last element?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never mind. I see it in the old code. I would feel better if it was ported over more accurately to the existing code in get_ecs_cluster_name

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wrote this code based on behavior of parsing Region from taskARN. However, I have not had more information regarding this to change behavior. However, for one short notice is that even though the clusterName is invalid based on what I have skimmed, it would not affect the whole flow so I am still considering whether we need to fatal if clusterName is invalid.

e.Cluster = splitedContent[len(splitedContent)-1]
}
8 changes: 4 additions & 4 deletions translator/util/sdkutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
"github.com/aws/amazon-cloudwatch-agent/translator/config"
"github.com/aws/amazon-cloudwatch-agent/translator/util/ec2util"
"github.com/aws/amazon-cloudwatch-agent/translator/util/ecsutil"

"github.com/aws/aws-sdk-go/aws/session"
)

Expand All @@ -36,7 +35,7 @@ func DetectAgentMode(configuredMode string) string {
fmt.Println("I! Detected from ENV instance is EC2")
return config.ModeEC2
}

if defaultEC2Region() != "" {
fmt.Println("I! Detected the instance is EC2")
return config.ModeEC2
Expand Down Expand Up @@ -93,15 +92,16 @@ func detectRegion(mode string, credsConfig map[string]string) (region string) {

// For ec2, fallback to metadata when no region info found in credential profile.
if region == "" && mode == config.ModeEC2 {
fmt.Println("I! Trying to detect region from ec2")
region = defaultEC2Region()
}

// try to get region from ecs metadata
if region == "" && mode == config.ModeEC2 {
fmt.Println("I! detect region from ecs")
fmt.Println("I! Trying to detect region from ecs")
region = defaultECSRegion()
}

return
}

Expand Down