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

metadata service continued #981

Merged
merged 21 commits into from
Oct 12, 2017
Merged

metadata service continued #981

merged 21 commits into from
Oct 12, 2017

Conversation

adnxn
Copy link
Contributor

@adnxn adnxn commented Sep 12, 2017

Summary

carried over work from #913 with following additions:

  • fix mismatch of generated mocks between metadata service and dev branch
  • includes dev changes up to 6f11735
  • updated gomock to latest version and regenerated all mocks
  • added code to handle agent restarts and unit test
  • functional testing for unix

Implementation details

n/a

Testing

  • Builds on Linux (make release)
  • Builds on Windows (go build -out amazon-ecs-agent.exe ./agent)
  • Unit tests on Linux (make test) pass
  • Unit tests on Windows (go test -timeout=25s ./agent/...) pass
  • Integration tests on Linux (make run-integ-tests) pass
  • Integration tests on Windows (.\scripts\run-integ-tests.ps1) pass
  • Functional tests on Linux (make run-functional-tests) pass
  • Functional tests on Windows (.\scripts\run-functional-tests.ps1) pass

New tests cover the changes:

Description for the changelog

Licensing

This contribution is under the terms of the Apache 2.0 License:

@adnxn adnxn force-pushed the mdservice-dev branch 3 times, most recently from 2af95e7 to 2feb1fa Compare September 13, 2017 19:47
@adnxn adnxn changed the title [WIP] metadata service continued metadata service continued Sep 13, 2017
@adnxn adnxn force-pushed the mdservice-dev branch 2 times, most recently from 7ac27ba to 9383f5f Compare September 13, 2017 23:03
Copy link
Contributor

@aaithal aaithal left a comment

Choose a reason for hiding this comment

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

First pass of review. I'll take another detailed look.

README.md Outdated
@@ -175,10 +175,16 @@ configure them as something other than the defaults.
| `ECS_IMAGE_MINIMUM_CLEANUP_AGE` | 30m | The minimum time interval between when an image is pulled and when it can be considered for automated image cleanup. | 1h | 1h |
| `ECS_NUM_IMAGES_DELETE_PER_CYCLE` | 5 | The maximum number of images to delete in a single automated image cleanup cycle. If set to less than 1, the value is ignored. | 5 | 5 |
| `ECS_INSTANCE_ATTRIBUTES` | `{"stack": "prod"}` | These attributes take effect only during initial registration. After the agent has joined an ECS cluster, use the PutAttributes API action to add additional attributes. For more information, see [Amazon ECS Container Agent Configuration](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-config.html) in the Amazon ECS Developer Guide.| `{}` | `{}` |
<<<<<<< 6f11735d92bbf1ce7bbe099721a17384095fdff7
Copy link
Contributor

Choose a reason for hiding this comment

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

Seems like a remnant of merge resolution. please get rid of this.

@@ -393,6 +395,8 @@ func environmentConfig() (Config, error) {
CNIPluginsPath: cniPluginsPath,
AWSVPCBlockInstanceMetdata: awsVPCBlockInstanceMetadata,
AWSVPCAdditionalLocalRoutes: additionalLocalRoutes,
ContainerMetadataEnabled: containerMetadataEnabled,
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you also update DefaultConfig to set ContainerMetadataEnabled to false?

@@ -353,6 +353,8 @@ func environmentConfig() (Config, error) {
errs = append(errs, err)
}
}
containerMetadataEnabled := utils.ParseBool(os.Getenv("ECS_ENABLE_CONTAINER_METADATA"), false)
dataDirOnHost := os.Getenv("ECS_HOST_DATA_DIR")
Copy link
Contributor

@aaithal aaithal Sep 14, 2017

Choose a reason for hiding this comment

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

What happens when ECS Init/whatever's starting the Agent mounts some other directory as Agent's data directory (-v /tmp:/data) sets ECS_HOST_DATA_DIR to "/var/lib/ecs"

It doesn't seem like a strong enough abstraction to be dependent on Agent configuration options to expect ECS_HOST_DATA_DIR to be the same as whatever's being mounted as /data on the host. My main concern is the late-binding/asynchronous failures this could lead to if the wrong host mount was specified. Wondering if there are better alternatives here. Can we at the very least inspect the Agent container and check if ECS_HOST_DATA_DIR is mounted? If the answer is that we'll revisit the validation here at some latter stage, that's fine too. But, I want us to be aware of potential failures here.

Copy link
Contributor

@huerdong huerdong Sep 14, 2017

Choose a reason for hiding this comment

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

I think we can get rid of ECS_HOST_DATA_DIR if we directly inspect the Agent container for whichever directory is mounted as /data and pass that into the metadata methods wherever appropriate.

Copy link
Contributor Author

@adnxn adnxn Sep 14, 2017

Choose a reason for hiding this comment

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

@aaithal hm you're right, there's a failure case here. i agree it makes sense to validate ECS_HOST_DATA_DIR is mounted by inspecting the Agent container.

however, i'm not sure if it makes more sense to fail during agent creation with a configuration error since the user will be expecting the metadata feature to be enabled, or if it would make more sense for us to surface a warning log and just disable the metadata feature.

i think failing explicitly during agent creation, newAgent(...), makes more sense since this would be a configuration error. whereas logging, disabling the feature and moving forward seems like a poor experience since the only ways for the user to find out about these errors would be to catch it in the log, or through containers failing because they expect a metadata file.

or do you have a more sensible way to communicate this error to the user?

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 failing explicitly during agent creation, newAgent(...), makes more sense since this would be a configuration error.

I agree

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@aaithal so as per our discussion earlier, we will call this out in the README under usage instructions for the metadata feature.

Copy link
Contributor

Choose a reason for hiding this comment

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

There are a few assumptions here that I think are problematic:

  • Assuming that ECS_HOST_DATA_DIR is /var/lib/ecs on the host
  • Assuming that the ECS agent is running inside a container (it runs outside a container on Windows)
  • Assuming that the ECS agent container has the name ecs-agent so you can inspect the container (true on ECS-optimized AMIs and other places where ecs-init is used, but not elsewhere)
  • Assuming that you can get the ECS agent container ID through its hostname so you can inspect the container (won't be true if the UTS namespace is shared)

Copy link
Contributor

@huerdong huerdong Sep 18, 2017

Choose a reason for hiding this comment

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

Adding to samuelkarp's second point, I believe the metadata feature does not work when the agent is run outside a container on Linux environments. Initially I was told this is a minor concern, but do we have use cases for the agent being run outside a container on Linux? For Windows, this situation is explicitly handled (As noted in the current documentation).

// Network is a struct that keeps track of metadata of a network interface
type Network struct {
NetworkMode string `json:"NetworkMode,omitempty"`
IPv4Address string `json:"IPv4Address,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you change this to IPv4Addresses instead? For now it can be a list of length 1. It'd be helpful to surface this info when we start containers with multiple IP addresses.

type Network struct {
NetworkMode string `json:"NetworkMode,omitempty"`
IPv4Address string `json:"IPv4Address,omitempty"`
IPv6Address string `json:"IPv6Address,omitempty"`
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above. Can you change this to IPv6Addresses instead ([]string)?

"name": "mdservice-validator-unix",
"cpu": 10,
"memory": 10,
"command": ["sh", "-c", "sleep 1 && if cat $ECS_CONTAINER_METADATA_FILE | grep \"READY\"; then exit 42; else exit 1; fi"]
Copy link
Contributor

Choose a reason for hiding this comment

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

sleep 1 may not always be sufficient. Can you increase this duration to something like 10s? Or, you can check for the existence in a loop and poll on the file for a maximum of 1m.

README.md Outdated
@@ -175,10 +175,16 @@ configure them as something other than the defaults.
| `ECS_IMAGE_MINIMUM_CLEANUP_AGE` | 30m | The minimum time interval between when an image is pulled and when it can be considered for automated image cleanup. | 1h | 1h |
| `ECS_NUM_IMAGES_DELETE_PER_CYCLE` | 5 | The maximum number of images to delete in a single automated image cleanup cycle. If set to less than 1, the value is ignored. | 5 | 5 |
| `ECS_INSTANCE_ATTRIBUTES` | `{"stack": "prod"}` | These attributes take effect only during initial registration. After the agent has joined an ECS cluster, use the PutAttributes API action to add additional attributes. For more information, see [Amazon ECS Container Agent Configuration](http://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-agent-config.html) in the Amazon ECS Developer Guide.| `{}` | `{}` |
<<<<<<< 6f11735d92bbf1ce7bbe099721a17384095fdff7

Choose a reason for hiding this comment

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

Is this a merge conflict not fixed?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

README.md Outdated
| `ECS_ENABLE_TASK_ENI` | `false` | Whether to enable task networking for task to be launched with its own network interface | `false` | Not applicable |
| `ECS_CNI_PLUGINS_PATH` | `/ecs/cni` | The path where the cni binary file is located | `/amazon-ecs-cni-plugins` | Not applicable |
| `ECS_AWSVPC_BLOCK_IMDS` | `true` | Whether to block access to [Instance Metdata](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for Tasks started with `awsvpc` network mode | `false` | Not applicable |
| `ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES` | `["10.0.15.0/24"]` | In `awsvpc` network mode, traffic to these prefixes will be routed via the host bridge instead of the task ENI | `[]` | Not applicable |
| `ECS_ENABLE_TASK_ENI` | `false` | Whether to enable task networking for task to be launched with its own network interface | `false` | `false` |

Choose a reason for hiding this comment

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

Why this appeared in this pr?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ugh it's related to your last comment, left over from merge resolution. fixed.

@@ -112,6 +112,10 @@ type Container struct {
// handled properly so that the state storage continues to work.
SentStatusUnsafe ContainerStatus `json:"SentStatus"`

// MetadataUpdated is set to true when we have completed updating the

Choose a reason for hiding this comment

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

nit: MetadataFileUpdated

// starts up
// In the future the metadata may require multiple stages of update and these
// statuses should amended/appended accordingly.
type MetadataStatus string

Choose a reason for hiding this comment

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

Why not use enum type like the container/task status?

Copy link
Contributor

@huerdong huerdong Sep 14, 2017

Choose a reason for hiding this comment

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

I believe this was a section I wrote and the reason I used a string rather than enum was to display the actual name of the status in the JSON Marshaling. Not quite certain but using an enum would produce numerical codes in the Marshaled output, which I think is less helpful to users checking for this status.

Copy link
Contributor

Choose a reason for hiding this comment

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

You can still have status names in marshaled JSON output with iotas (Go doesn't actually have enums), but you'd need to implement the TextMarshaler and TextUnmarshaler interfaces.

I would recommend doing this, as you then get stronger assurances about what will be marshaled/unmarshaled.

Copy link
Contributor

Choose a reason for hiding this comment

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

@adnxn can you address @samuelkarp's comment as well? Also, can this be moved to containermetadata/types.go ?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

gotcha, fixed. using iotas and moved to containermetadata/types.go.


"github.com/aws/amazon-ecs-agent/agent/config"
"github.com/aws/amazon-ecs-agent/agent/utils/ioutilwrapper"

Choose a reason for hiding this comment

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

please remove this blank line

}
}

// TestClean is the mainline case for metadata create

Choose a reason for hiding this comment

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

Can you fix this comment, it's not clear to me.

Copy link
Contributor

Choose a reason for hiding this comment

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

As with the comment below, I wrote this comment intending it to mean "TestClean is the happy path case for metadata file cleanup".

Choose a reason for hiding this comment

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

Then we may want these comments to be more specific to the test, as the current comment doesn't have useful and clear meaning for the test.

"github.com/golang/mock/gomock"
)

// TestCreate is the mainline case for metadata create

Choose a reason for hiding this comment

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

why this comment is reused everywhere, can you fix this? Also please use assert or require for this package.

Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above

_, err := getTaskIDfromARN(mockTaskARN)
expectErrorMessage := fmt.Sprintf("get task ARN: cannot find TaskID for TaskARN %s", mockTaskARN)

if err.Error() != expectErrorMessage {

Choose a reason for hiding this comment

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

Please use assert instead, same for other packages.

@@ -26,6 +27,6 @@ import (
var log = logger.ForModule("TaskEngine")

// NewTaskEngine returns a default TaskEngine
func NewTaskEngine(cfg *config.Config, client DockerClient, credentialsManager credentials.Manager, containerChangeEventStream *eventstream.EventStream, imageManager ImageManager, state dockerstate.TaskEngineState) TaskEngine {
return NewDockerTaskEngine(cfg, client, credentialsManager, containerChangeEventStream, imageManager, state)
func NewTaskEngine(cfg *config.Config, client DockerClient, credentialsManager credentials.Manager, containerChangeEventStream *eventstream.EventStream, imageManager ImageManager, state dockerstate.TaskEngineState, metadataManager containermetadata.Manager) TaskEngine {

Choose a reason for hiding this comment

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

Can you break this into multiple lines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

}

// NewDockerTaskEngine returns a created, but uninitialized, DockerTaskEngine.
// The distinction between created and initialized is that when created it may
// be serialized/deserialized, but it will not communicate with docker until it
// is also initialized.
func NewDockerTaskEngine(cfg *config.Config, client DockerClient, credentialsManager credentials.Manager, containerChangeEventStream *eventstream.EventStream, imageManager ImageManager, state dockerstate.TaskEngineState) *DockerTaskEngine {
func NewDockerTaskEngine(cfg *config.Config, client DockerClient, credentialsManager credentials.Manager, containerChangeEventStream *eventstream.EventStream, imageManager ImageManager, state dockerstate.TaskEngineState, metadataManager containermetadata.Manager) *DockerTaskEngine {

Choose a reason for hiding this comment

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

please break this into multiple lines

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

@adnxn adnxn force-pushed the mdservice-dev branch 4 times, most recently from 558b98a to ff162ba Compare September 15, 2017 21:53
@aaithal aaithal mentioned this pull request Sep 18, 2017
8 tasks
@@ -306,3 +310,17 @@ func (c *Container) IsInternal() bool {
func (c *Container) IsRunning() bool {
return c.GetKnownStatus().IsRunning()
}

func (c *Container) IsMetadataFileUpdated() bool {

Choose a reason for hiding this comment

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

Lint: Please add a comment here for public methods, same for below.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed

@@ -59,7 +60,9 @@ func DefaultConfig() Config {
netBIOSPort,
},
ReservedPortsUDP: []uint16{},
DataDir: filepath.Join(ecsRoot, "data"),
DataDir: dataDir,
// DataDirOnHost is identical to DataDir for Windows because we do not run on a container

Choose a reason for hiding this comment

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

nit: run agent as a container

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

if err != nil {
// Retry if file does not exist
if osWrap.IsNotExist(err) {
file, err = osWrap.Create(metadataFileName)

Choose a reason for hiding this comment

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

Do we need to set the file permission after creating?

Copy link
Contributor Author

@adnxn adnxn Sep 22, 2017

Choose a reason for hiding this comment

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

looking at this again, we can remove the retry block with osWrap.IsNotExist(err) {... by changing the open file line to file, err := osWrap.OpenFile(metadataFileName, os.O_WRONLY | os.O_CREATE, metadataPerm).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

actually nvm. from godocs,

"On Windows, the mode must be non-zero but otherwise only the 0200 bit (owner writable) of mode is used; it controls whether the file's read-only attribute is set or cleared. attribute. The other bits are currently unused. Use mode 0400 for a read-only file and 0600 for a readable+writable file."

so we might not be able to have the exact same permission as we do on linux. i'll follow up with someone on the team that knows more about windows file permissions.

@@ -636,3 +636,27 @@ func fluentdDriverTest(taskDefinition string, t *testing.T) {
err = SearchStrInDir(fluentdLogPath, "ecsfts", logTag)
assert.NoError(t, err, "failed to find the log tag specified in the task definition")
}

// TestMetadataServiceValidator Tests that the metadata file can be accessed from the

Choose a reason for hiding this comment

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

Can we also add this test for windows?

@@ -48,6 +48,7 @@ const (
// b) Add 'ContainerResourcesProvisioned' as a new 'ContainerStatus' enum
// c) Add 'SteadyStateStatus' field to 'Container' struct
// d) Add 'ENIAttachments' struct
// e) Add 'MetadataUpdated' field to 'api.Container'

Choose a reason for hiding this comment

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

nit: this should be space instead of tab.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

// statuses should amended/appended accordingly.
type MetadataStatus string

const (
Copy link
Contributor

Choose a reason for hiding this comment

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

This is more of a code structure thing. I like to see consts at the top of the file (you'll find that to be the case in rest of this code base as well). Can you move this block to the top of the file?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

if engine.cfg.ContainerMetadataEnabled {
err := engine.metadataManager.Clean(task.Arn)
if err != nil {
seelog.Errorf("Clean task metadata failed for task %s: %v", task, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you please change this to a Warn? I'd prefer Error to be used if it correlates with a customer facing error, which this is not (Applies to the rest of the file(s) as well).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

@aaithal
Copy link
Contributor

aaithal commented Oct 4, 2017

@adnxn an you investigate why appveyor is failing and resolve merge conflicts as well?

// starts up
// In the future the metadata may require multiple stages of update and these
// statuses should amended/appended accordingly.
type MetadataStatus string
Copy link
Contributor

Choose a reason for hiding this comment

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

@adnxn can you address @samuelkarp's comment as well? Also, can this be moved to containermetadata/types.go ?

}

// Acquire the metadata then write it in JSON format to the file
metadata := manager.parseMetadataAtContainerCreate(taskARN, containerName)
Copy link
Contributor

Choose a reason for hiding this comment

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

The logic of parsing, marshaling and writing the metadata file is duplicated between this and the Update method. Please extract that to a method of its own.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

// containing the task-id which we extract by splitting it by "/".
// This function should be eventually be replaced by a standardized ARN parsing
// module
func getTaskIDfromARN(taskARN string) (string, error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We should be able to get rid of this if we use the updated SDK and the arn.Parse() method from aws/aws-sdk-go@1fb10cf

Copy link
Contributor Author

@adnxn adnxn Oct 5, 2017

Choose a reason for hiding this comment

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

fixed. updating sdk here #1006 and added the aws/arn package to this set of changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not including this change since godep is doing this.

}
metadataFileName := filepath.Join(metadataFileDir, metadataFile)

temp, err := ioutilWrap.TempFile(metadataFileDir, "temp_metadata_file")
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you const "temp_metadata_file"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

if engine.cfg.ContainerMetadataEnabled {
err := engine.metadataManager.Clean(task.Arn)
if err != nil {
seelog.Warnf("Clean task metadata failed for task %s: %v", task, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be task.Arn. Also, can you add unit tests for sweepTask and exercise this code path?

Copy link
Contributor Author

@adnxn adnxn Oct 5, 2017

Choose a reason for hiding this comment

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

fixed the task.Arn thing. and the existing happy path test exercises that code path.

huerdong and others added 11 commits October 4, 2017 13:43
all @huerdong commits squashed for manageable commit history in PR
This commit is fix gomock version mismatch and regenerate all mocks to
fix breaking builds with metadata service changes
This change adds logic in the agent to update the metadata file after
the agent restarts and the related unit test.

Note that we added a MetadataFileUpdated flag in the api.Container
struct and this is included with state file's ECSDataVersion 6 bump.

// Get Port bindings from docker configurations
var ports []api.PortBinding
var err error
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: if there's no specific reason to declare this here, can you get rid of it?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

im going to leave this one as it is, the nested branch needs both, and we return ports even if its empty.

}

func (status *MetadataStatus) UnmarshalText(text []byte) error {
var err error
Copy link
Contributor

Choose a reason for hiding this comment

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

You can get rid of this line and return nil at the end of the method.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

oh i see why, fixed.

// statuses should amended/appended accordingly.
type MetadataStatus int32

func (status MetadataStatus) MarshalText() (text []byte, err error) {
Copy link
Contributor

Choose a reason for hiding this comment

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

We have unit test for this and the unmarshal method?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added tests for this.

go func() {
err := engine.metadataManager.Update(dockerContainer.DockerID, task.Arn, container.Name)
if err != nil {
seelog.Warnf("Update metadata file failed for container %s of task %s: %v", container, task, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

minor: you can return here and get rid of else.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

seelog.Warnf("Update metadata file failed for container %s of task %s: %v", container, task, err)
} else {
container.SetMetadataFileUpdated()
seelog.Debugf("Updated metadata file for container %s of task %s", container, task)
Copy link
Contributor

Choose a reason for hiding this comment

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

Here and in the rest of the file, let's log less: task.Arn, container.Name

Copy link
Contributor Author

@adnxn adnxn Oct 9, 2017

Choose a reason for hiding this comment

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

gotcha. cleaned up instances of this in the file.

Copy link
Contributor

@aaithal aaithal left a comment

Choose a reason for hiding this comment

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

mostly looks good. I have some minor comments.

@@ -49,6 +49,7 @@ const (
// c) Add 'SteadyStateStatus' field to 'Container' struct
// d) Add 'ENIAttachments' struct
// e) Deprecate 'SteadyStateDependencies' in favor of 'TransitionDependencySet'
// f) Add 'MetadataUpdated' field to 'api.Container'
ECSDataVersion = 6
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be 7 now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

right, fixed.

)

const (
metadataEnvironmentVariable = "ECS_CONTAINER_METADATA_FILE"
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add documentation for this variable stating that this will be set in the container's host config and this is what customers would use to locate/access metadata.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

added documentation for ECS_CONTAINER_METADATA_FILE in the readme, also we should discuss if we need to include more detailed documentation wrt format of the file and the specific fields.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not including this change in favor of separate docs pr

Copy link
Contributor

Choose a reason for hiding this comment

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

Why not? You can still document what this variable does // metadataEnvironmentVariable is ...

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 didn't realise you meant in the code earlier. fixed.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

didnt realise you meant document in the code earlier. fixed now.


// Acquire the metadata then write it in JSON format to the file
metadata := manager.parseMetadata(dockerContainer, taskARN, containerName)
err = manager.marshalAndWrite(metadata, taskARN, containerName)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: if you aren't doing anything with the error returned, you can just do return manager.marshalAndWrite(metadata, taskARN, containerName) here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense, fixed.

func (manager *metadataManager) Clean(taskARN string) error {
metadataPath, err := getTaskMetadataDir(taskARN, manager.dataDir)
if err != nil {
return fmt.Errorf("clean task %s: %v", taskARN, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

please add more context here: "clean task metadata: unable to get metadata directory for task %s: %v"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

func (manager *metadataManager) marshalAndWrite(metadata Metadata, taskARN string, containerName string) error {
data, err := json.MarshalIndent(metadata, "", "\t")
if err != nil {
return fmt.Errorf("create metadata for task %s container %s: %v", taskARN, containerName, err)
Copy link
Contributor

Choose a reason for hiding this comment

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

same here, needs more context: "create metadata for container %s in task %s: failed to marshal metadata"

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

}

// Write the metadata to file
err = writeToMetadataFile(manager.osWrap, manager.ioutilWrap, data, taskARN, containerName, manager.dataDir)
Copy link
Contributor

Choose a reason for hiding this comment

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

here too, you could just do return writeMetadata...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

makes sense, fixed.

unit tests no manager_test.go no longer depend on error message
format.
README.md Outdated
@@ -181,6 +181,9 @@ configure them as something other than the defaults.
| `ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES` | `["10.0.15.0/24"]` | In `awsvpc` network mode, traffic to these prefixes will be routed via the host bridge instead of the task ENI | `[]` | Not applicable |
| `ECS_ENABLE_CONTAINER_METADATA` | `<true|false>` | Whether to enable creation of a metadata file in the containers. If enabled the agent will inject a file with the container's various metadata and the user can access the container's metadata internally by accessing the environment variable $ECS_CONTAINER_METADATA_FILE. | `false` | `false` |
| `ECS_HOST_DATA_DIR` | `/var/lib/ecs` | The source directory on the host from which ECS_DATADIR is mounted. We use this to determine the source mount path for container metadata files in the case the Agent is run in a container. We do not use this value in Windows because the Agent is not run on a container in Windows. | `/var/lib/ecs` | `Not used` |
| `ECS_CONTAINER_METADATA_FILE` | set by the agent | This is variable is set in
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need to document this in README.md. The variables we have here are the Agent config settings used to tune the Agent. It may make sense to add an example at the end of the readme or something demonstrating how to use the metadata feature.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

okay, i'll add a separate section for this altogether.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

not including this change in favor of separate docs pr

@adnxn adnxn force-pushed the mdservice-dev branch 3 times, most recently from ee953a1 to 347977d Compare October 11, 2017 19:51
Copy link

@richardpen richardpen left a comment

Choose a reason for hiding this comment

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

LGTM except minor comments

README.md Outdated
@@ -179,6 +179,8 @@ configure them as something other than the defaults.
| `ECS_CNI_PLUGINS_PATH` | `/ecs/cni` | The path where the cni binary file is located | `/amazon-ecs-cni-plugins` | Not applicable |
| `ECS_AWSVPC_BLOCK_IMDS` | `true` | Whether to block access to [Instance Metdata](http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-metadata.html) for Tasks started with `awsvpc` network mode | `false` | Not applicable |
| `ECS_AWSVPC_ADDITIONAL_LOCAL_ROUTES` | `["10.0.15.0/24"]` | In `awsvpc` network mode, traffic to these prefixes will be routed via the host bridge instead of the task ENI | `[]` | Not applicable |
| `ECS_ENABLE_CONTAINER_METADATA` | `true` | When `true`, the agent will create a file describing the container's metadata and the file can be located and consumed by using the container enviornment variable `$ECS_CONTAINER_METADATA_FILE` | `false` | `false` |
| `ECS_HOST_DATA_DIR` | `/var/lib/ecs` | The source directory on the host from which ECS_DATADIR is mounted. We use this to determine the source mount path for container metadata files in the case the Agent is run in a container. We do not use this value in Windows because the Agent is not run on a container in Windows. | `/var/lib/ecs` | `Not used` |

Choose a reason for hiding this comment

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

nit: in the case the ECS Agent is running as a container xxxxx because the ECS Agent is not running as a container

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixed.

@@ -317,3 +321,20 @@ func (c *Container) IsInternal() bool {
func (c *Container) IsRunning() bool {
return c.GetKnownStatus().IsRunning()
}

// IsMetadataFileUpdated() returns true if the metadata file has been once the

Choose a reason for hiding this comment

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

can you get rid of the parenthesis in the comment?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yep gone.

Copy link
Contributor

@vsiddharth vsiddharth left a comment

Choose a reason for hiding this comment

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

LGTM 📦 🚀

@adnxn adnxn merged commit 6817a23 into aws:dev Oct 12, 2017
@jhaynes jhaynes mentioned this pull request Oct 31, 2017
@adnxn adnxn deleted the mdservice-dev branch March 14, 2018 17:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants