-
Notifications
You must be signed in to change notification settings - Fork 619
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
ECS Agent tagging support #1618
Conversation
Func tests are expected to fail as the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat!
agent/config/config.go
Outdated
|
||
// When ContainerInstancePropagateTagsEC2InstanceType is specified, agent will | ||
// make DescribeTags API call to get tags remotely. | ||
ContainerInstancePropagateTagsEC2InstanceType |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this get stored in the state file? if so, we should test that the values of these don't change. (IE, we don't accidentally reorder them in the future)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will not be stored in the state file, every time Agent starts it will read the config file and populate this value again.
agent/config/config.go
Outdated
@@ -406,6 +416,9 @@ func environmentConfig() (Config, error) { | |||
var errs []error | |||
instanceAttributes, errs = parseInstanceAttributes(errs) | |||
|
|||
var containerInstanceTags map[string]string | |||
containerInstanceTags, errs = parseContainerInstanceTags(errs) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This might be a silly question, but why doesn't :=
work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah that will work, changed to the simpler format.
@@ -592,6 +601,49 @@ func TestUserDataConfig(t *testing.T) { | |||
} | |||
} | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add test cases for the key:value pairs?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I've already added here. LMK if you want me to include more test cases.
|
||
for _, tc := range testcases { | ||
// Test the parse function only. | ||
t.Run(tc.name, func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd probably merge these two t.Run functions together and just make sure the "message" includes a note that the parsing didn't work as expected.
@@ -208,3 +210,20 @@ func IsAWSErrorCodeEqual(err error, code string) bool { | |||
awsErr, ok := err.(awserr.Error) | |||
return ok && awsErr.Code() == code | |||
} | |||
|
|||
// MapToTags converts a map to a slice of tags. | |||
func MapToTags(tagsMap map[string]string) []*ecs.Tag { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FFTI: I'd consider moving this and the other tagging-specific functions (mergeTags) into a tagging-specific file / package.
agent/api/ecsclient/client_test.go
Outdated
func extractTagsMapFromRegisterContainerInstanceInput(req *ecs.RegisterContainerInstanceInput) map[string]string { | ||
tagsMap := make(map[string]string, len(req.Tags)) | ||
for i := range req.Tags { | ||
tagsMap[*req.Tags[i].Key] = aws.StringValue(req.Tags[i].Value) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why key is using pointer dereference while value is using aws.StringValue here?
ec2metadata "github.com/aws/aws-sdk-go/aws/ec2metadata" | ||
ec20 "github.com/aws/aws-sdk-go/service/ec2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This ec20 is a little bit weird as a name. Maybe change '/agent/ec2' to agent_ec2 and keep '/service/ec2' as ec2.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know, this is something auto-generated...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its the worst!
README.md
Outdated
@@ -131,6 +131,8 @@ additional details on each available environment variable. | |||
| `ECS_ENABLE_CPU_UNBOUNDED_WINDOWS_WORKAROUND` | `true` | When `true`, ECS will allow CPU unbounded(CPU=`0`) tasks to run along with CPU bounded tasks in Windows. | Not applicable | `false` | | |||
| `ECS_TASK_METADATA_RPS_LIMIT` | `100,150` | Comma separated integer values for steady state and burst throttle limits for task metadata endpoint | `40,60` | `40,60` | | |||
| `ECS_SHARED_VOLUME_MATCH_FULL_CONFIG` | `true` | When `true`, ECS Agent will compare name, driver options, and labels to make sure volumes are identical. When `false`, Agent will short circuit shared volume comparison if the names match. This is the default Docker behavior. If a volume is shared across instances, this should be set to `false`. | `false` | `false`| | |||
| `ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS` | `"ec2_instance"` | If `"ec2_instance"` is specified, tags of the ec2 instance will be registered to ECS, make sure you allow `ec2:DescribeTags` action in your instance profile. | `"none"` | `"none"` | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Name ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS
can be a bit confusing and it sounds like a bool var.
how about something like -
ECS_INSTANCE_REGISTER_TAG_TYPES
or ECS_INSTANCE_OBTAIN_TAG_TYPES
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Confirmed with Akram, decided to go with ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS_FROM
.
agent/config/parse.go
Outdated
} | ||
|
||
func parseContainerInstancePropagateTags() ContainerInstancePropagateTagsType { | ||
containerInstancePropagateTagsString := os.Getenv("ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS
should be a list of strings rather than one, if we want to support multiple tag types in the future and not break backwards compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think customer only has one option - either ask Agent to propagate the tags or ask backend to propagate the tags, customer will get the same tags either way, so supporting both of them seems to do duplicate work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The reason why I brought this up is because we have ContainerInstancePropagateTagsType
as an enum -- implying there can be other values too?
Do we know what they could be or if multiple values can be used?
If ec2-instance
is going to be the only value, we could just have a string as opposed to an enum.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it can be other values, but even if there are other possible values, customer can only use one of them. For example, if we have backend
as one of the values in the future, customer only needs ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS
to be either ec2_instance
or backend
, because we will get the same set of tags when we ask backend to propagate or we let Agent propagate tags.
@yumex93 @sharanyad I've refactored accordingly. Also introduced PutAccountSetting API used in functional test, this is required for tags related API. |
Joel reviewed my README. Rebase the dev branch, and added changelog. |
CHANGELOG.md
Outdated
@@ -1,8 +1,11 @@ | |||
# Changelog | |||
|
|||
## 1.22.0-dev | |||
* Feature - Introduce two environment variables to support ECS tagging [#1618](https://github.com/aws/amazon-ecs-agent/pull/1618) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we also specify what they are?
@@ -310,6 +325,20 @@ | |||
{"shape":"ServiceNotFoundException"} | |||
] | |||
}, | |||
"PutAccountSetting":{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this part of tagging?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, used in func test.
assert.Equal(t, localValue, aws.StringValue(mergedTags[2].Value)) | ||
} | ||
|
||
func TestGetContainerInstanceTagsFromEC2API(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please add negative test case as well
localKey, localValue, commonKey, commonKeyLocalValue), | ||
}, | ||
} | ||
agent := RunAgent(t, agentOptions) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test will require specific agent version.
func TestContainerInstanceTags(t *testing.T) { | ||
// We need long container instance ARN for tagging APIs, PutAccountSettingInput | ||
// will enable long container instance ARN. | ||
putAccountSettingInput := ecsapi.PutAccountSettingInput{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will customers have to manually enable this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it will be described in doc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please add a comment in the functional test to change the required agent version during staging
agent/config/config_test.go
Outdated
@@ -88,6 +88,7 @@ func TestEnvironmentConfig(t *testing.T) { | |||
defer setTestEnv("ECS_NUM_IMAGES_DELETE_PER_CYCLE", "2")() | |||
defer setTestEnv("ECS_IMAGE_PULL_BEHAVIOR", "always")() | |||
defer setTestEnv("ECS_INSTANCE_ATTRIBUTES", "{\"my_attribute\": \"testing\"}")() | |||
defer setTestEnv("ECS_CONTAINER_INSTANCE_TAGS", "{\"my_tag\": \"testing\"}")() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: Use string literals instead of escaping:
defer setTestEnv("ECS_CONTAINER_INSTANCE_TAGS", `{"my_tag": "testing"}`)()
ec2metadata "github.com/aws/aws-sdk-go/aws/ec2metadata" | ||
ec20 "github.com/aws/aws-sdk-go/service/ec2" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
its the worst!
Introduce ECS_CONTAINER_INSTANCE_TAGS environment variable and ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS to allow Agent retrieve tags locally and remotely.
Summary
ECS local tags support
Implementation details
ECS_CONTAINER_INSTANCE_TAGS
env var to allow customer to configure tags on the instance.ECS_CONTAINER_INSTANCE_PROPAGATE_TAGS
to get the tags of the ec2 instance that Agent is running on using DescribeTags API. We can specify eithernone
orec2_instance
for this env var, the reason that we don't use a boolean is because we may introduce other ways to propagate the tags (like ask backend to propagate tags instead of doing it on Agent side).ListTagsForResourceInput
for testing purpose.DescribeECSTagsForInstance
is used for RCI call, andCreateTags
for func test.InstanceID
API to EC2 metadata client.TODO:
Make func test pass once the
ListTagsForResource
API is in prod.Testing
make release
)go build -out amazon-ecs-agent.exe ./agent
)make test
) passgo test -timeout=25s ./agent/...
) passmake run-integ-tests
) pass.\scripts\run-integ-tests.ps1
) passmake run-functional-tests
) pass.\scripts\run-functional-tests.ps1
) passDescription for the changelog
Licensing
By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.