-
Notifications
You must be signed in to change notification settings - Fork 618
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
Support Docker API v1.24 on windows #783
Conversation
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.
lgtm
docker "github.com/fsouza/go-dockerclient" | ||
) | ||
|
||
type Factory interface { |
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.
lint: // Factory ...
GetClient(version DockerVersion) (dockeriface.Client, error) | ||
|
||
// FindSupportedAPIVersions tests each agent supported API version | ||
// against the docker daemon and returns a slice of supported |
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: Docker
return docker.NewVersionedClient(endpoint, version) | ||
} | ||
|
||
func NewFactory(endpoint string) Factory { |
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.
lint: //NewFactory ...
default: | ||
t.Fatal("Unrecognized version") | ||
client, ok := mockClients[version] | ||
if !ok { |
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 you use assert.True(t, ok)
instead?
if len(versions) != len(expectedVersions) { | ||
t.Errorf("Expected %d versions but got %d", len(expectedVersions), len(versions)) | ||
actualVersions := factory.FindSupportedAPIVersions() | ||
if len(expectedVersions) != len(actualVersions) { |
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 you use assert.Equal(t, exptectedVersions, actualVersions)
or a variation of it?
FluentdDriver LoggingDriver = "fluentd" | ||
AwslogsDriver LoggingDriver = "awslogs" | ||
SplunklogsDriver LoggingDriver = "splunk" | ||
JsonFileDriver LoggingDriver = "json-file" |
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.
While you're here, %s/JsonFileDriver/JSONFileDriver
JournaldDriver LoggingDriver = "journald" | ||
GelfDriver LoggingDriver = "gelf" | ||
FluentdDriver LoggingDriver = "fluentd" | ||
AwslogsDriver LoggingDriver = "awslogs" |
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.
lint for this as well AWSLogsDriver
@@ -19,7 +19,7 @@ Invoke-Expression "${PSScriptRoot}\..\misc\image-cleanup-test-images\build.ps1" | |||
$cwd = (pwd).Path | |||
try { | |||
cd "${PSScriptRoot}" | |||
go test -tags integration -timeout=10m -v ../agent/engine ../agent/stats | |||
go test -tags integration -timeout=15m -v ../agent/engine ../agent/stats |
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 resolve #759 as well?
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 had a chat with @adnxn yesterday. The answer is maybe. I want to see if there is a way to run this test more deterministically.
return client, nil | ||
} | ||
|
||
func (f *factory) FindSupportedAPIVersions() []DockerVersion { |
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 you add a comment for this?
// FindSupportedAPIVersions returns the API versions which are both known to exist for the Docker daemon to which the agent is connected and are supported by the agent.
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 it need to be on both the interface and the function?
newVersionedClient = func(endpoint, version string) (dockeriface.Client, error) { | ||
if endpoint != expectedEndpoint { | ||
t.Errorf("Expected endpoint %s but was %s", expectedEndpoint, endpoint) | ||
} | ||
if version != string(defaultVersion) { | ||
t.Errorf("Expected version %s but was %s", defaultVersion, version) | ||
if version != string(getDefaultVersion()) { |
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.
Since you're in this file...want to change it to use github.com/stretchr/testify/assert
?
assert.Equal(t, string(getDefaultVersion()), version)
func init() { | ||
supportedVersions = []DockerVersion{ | ||
// getKnownAPIVersions returns all of the API versions that we know about. | ||
// It doesn't care if the version is supported by docker or ECS agent |
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.
s/docker/Docker/
Version_1_21, | ||
Version_1_22, | ||
Version_1_23, | ||
Version_1_24, |
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 is 1.24 included on Windows but not Linux? Should this be 1.23 on both instead?
// running with a build tag | ||
func TestTest(t *testing.T) {} | ||
func getDefaultVersion() DockerVersion { | ||
return Version_1_24 |
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 the minimum on Windows is 1.23.
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.
You're right. I didn't do the other things mentioned on #687, I can address that separately
@@ -1,3 +1,4 @@ | |||
// +build windows |
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 have no idea why git thinks you moved a file here...did you intentionally get rid of dummy_test.go
?
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! Dummy Tests don't appear to be needed anymore.
@@ -1,22 +0,0 @@ | |||
// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
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.
How come this file is removed?
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 didn't have trouble running the functional tests when this file was excluded.
@@ -0,0 +1,116 @@ | |||
// Copyright 2014-2015 Amazon.com, Inc. or its affiliates. All Rights Reserved. |
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.
Header: 2017 Amaazon.com
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.
Doh! I'll fix it.
Version_1_25, | ||
Version_1_26, | ||
Version_1_27, | ||
Version_1_28, |
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 there any reason put the 25-28 here, while agent doesn't support?
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! Its for future use cases. In the interface for the factory, we only currently expose what is supported by both agent and docker.
@samuelkarp had mentioned to me that it would be useful to understand all of the API versions that the host's docker daemon supports even if we don't leverage it to the main engine code.
@@ -207,7 +207,7 @@ func (agent *TestAgent) StartAgent() error { | |||
return errors.New("Could not inspect agent container: " + err.Error()) | |||
} | |||
agent.IntrospectionURL = "http://localhost:" + containerMetadata.NetworkSettings.Ports["51678/tcp"][0].HostPort | |||
err = agent.platformIndependentStartAgent() | |||
err = agent.verifyIntrospectionAPI() |
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.
minor: you can just do return agent.verifyIntrospectionAPI()
here.
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 stuff! Some of the comments are me linting stuff. If we could do the getClient
refactor, this would be good to go.
) | ||
|
||
// We replace docker APIs 1.17 - 12.23 on the windows agent | ||
const NUMBER_OF_REPLACED_VERSIONS = 7 |
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.
GoStyle: NumberOfReplacedVersions
. Also, this doesn't need to be global scoped.
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.
Re-factoring allowed me to test this differently: I removed this line
"github.com/aws/amazon-ecs-agent/agent/engine/dockeriface" | ||
) | ||
|
||
const MIN_DOCKER_API_WINDOWS = Version_1_24 |
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.
GoStyle: MinDockerAPIWindows
"github.com/aws/amazon-ecs-agent/agent/engine/dockeriface" | ||
) | ||
|
||
func (f *factory) GetClient(version DockerVersion) (dockeriface.Client, error) { |
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.
// GetClient gets ...
|
||
const MIN_DOCKER_API_WINDOWS = Version_1_24 | ||
|
||
// Override newVersionedClient. We need this because agent makes assumptions |
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.
// GetClient overridses ..
return client, nil | ||
} | ||
|
||
f.lock.Lock() |
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 we should refactor this method to not hold the lock while we do expensive operations like client.Ping()
. Can you instead add get and set methods for the map and acquire the lock only when accessing the lock?
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.
Sounds good. I changed this so that agent detect all API versions on init. This lets me get rid of the lock entirely.
agent/functional_tests/util/utils.go
Outdated
@@ -115,7 +115,7 @@ type AgentOptions struct { | |||
} | |||
|
|||
// PLatform Independent piece of Agent Startup. Gets executed on both linux and Windows. |
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.
While you're here, can you also fix the comment? // verifyIntrospectionAPI verifies ...
@@ -127,7 +127,7 @@ func (agent *TestAgent) StartAgent() error { | |||
} | |||
agent.Process = agentInvoke.Process | |||
agent.IntrospectionURL = "http://localhost:51678" | |||
err = agent.platformIndependentStartAgent() | |||
err = agent.verifyIntrospectionAPI() |
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: can just be return agent.verifyIntrospectionAPI()
misc/windows-deploy/hostsetup.ps1
Outdated
route -p delete 169.254.170.2/32 | ||
# This address will only exist on systems that have already set up the routes | ||
$ip = (Get-NetIPAddress -InterfaceIndex $ifIndex -IPAddress 169.254.170.2 -PrefixLength 32) | ||
if(!($ip)) { |
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.
As a windows noob, I'd really appreciate it if you could add a comment for each line here.
misc/windows-deploy/hostsetup.ps1
Outdated
Add-VMNetworkAdapter -VMNetworkAdapterName "APIPA" -SwitchName nat -ManagementOS | ||
$ifIndex = (Get-NetAdapter -Name "*APIPA*" | Sort-Object | Select ifIndex).ifindex | ||
New-NetIPAddress -InterfaceIndex $ifIndex -IPAddress 169.254.170.2 -PrefixLength 32 | ||
New-NetRoute -DestinationPrefix 172.20.128.0/20 -ifIndex $ifindex |
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 do not think we should hard code the 172.20.128.0/20 here. The value corresponds to the Subnet CIDR under the IPAM section for the default nat network. Essentially, obtained from the output of docker network inspect nat (default network). I am thinking we should discover the value rather than hardcode it here.
misc/windows-deploy/hostsetup.ps1
Outdated
# Enable NAT for container-to-host communication | ||
Add-VMNetworkAdapter -VMNetworkAdapterName "APIPA" -SwitchName nat -ManagementOS | ||
$ifIndex = (Get-NetAdapter -Name "*APIPA*" | Sort-Object | Select ifIndex).ifindex | ||
New-NetIPAddress -InterfaceIndex $ifIndex -IPAddress 169.254.170.2 -PrefixLength 32 |
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 only thing which may require a change around reboots is the piece which involves ifIndex - For instance, what if someone adds a second ENI prior to Windows rebooting and running this startup script. The interface index could change in that situation. I dont know though as to how common this possibility or similar possibilities like this are.
So, to handle reboot case: You can change the script to check if a route of the below from currently exists - using Get-NetRoute -DestinationPrefix 172.20.128.0/20. If it exists, you could delete it first using Remove-NetRoute and then add it using the right interface index which will be discovered as done in line 18 above.
@@ -78,18 +78,7 @@ try { | |||
|
|||
if([System.Environment]::GetEnvironmentVariable("ECS_ENABLE_TASK_IAM_ROLE", "Machine") -eq "true") { | |||
LogMsg "IAM roles environment variable is set." | |||
|
|||
.\loopback.ps1 | |||
.\hostsetup.ps1 |
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 the IAM role test failing issue you mentioned to me with docker 17.03.1-ee-3, get resolved now ?
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.
My comments on the proposed changes below,
@@ -0,0 +1,96 @@ | |||
// +build !integration |
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 !integration
just so that the tests don't run multiple times?
|
||
newVersionedClient = func(endpoint, version string) (dockeriface.Client, error) { | ||
mockClient := mock_dockeriface.NewMockClient(ctrl) | ||
if version == string(MinDockerAPIWindows) { |
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.
Rather than doing this where you assert.Equal(t, expectedClient, actualClient)
, why not assert.Equal(t, MinDockerAPIWindows, version)
?
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 function is called for every client at agent start-up -- assertion that way won't work anymore.
func (f *factory) GetClient(version DockerVersion) (dockeriface.Client, error) { | ||
for _, v := range getWindowsReplaceableVersions() { | ||
if v == version { | ||
version = MinDockerAPIWindows |
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.
break
?
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.
LGTM.
Can you rebase and update go-dockerclient to include fsouza/go-dockerclient#654? |
@samuelkarp 👍 I'm working on that now |
09be263
to
266983f
Compare
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.
Looks good overall. I have a few minor comments.
if ok { | ||
return client, nil | ||
} else { | ||
return nil, errors.New("Client not found for docker version: " + string(version)) |
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.
Error messages should be begin with lowercase. It would also be great to include some context here: "docker client factory: client not found..."
// Validate that agentVersions is a subset of allVersions | ||
for _, agentVersion := range getAgentVersions() { | ||
if !isKnown(agentVersion) { | ||
t.Errorf("Version not found in known Docker Versions: %s", agentVersion) |
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 you use assert.True
here instead?
} | ||
|
||
factory := NewFactory(expectedEndpoint) | ||
actualClient, _ := factory.GetClient(Version_1_19) |
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 you also do assert.NoError(t, err)
by catching the error when it's returned?
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.
Looks good after you address @aaithal's feedback.
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.
* Separates docker API version support for windows * Sets docker API version default to 1.23 for windows
36c4da9
to
1cb0001
Compare
Summary
Enables docker API v1.24 for windows, and sets it as the default version.
Implementation details
Refactored some of the versioning and docker client code.
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
) passNew tests cover the changes: no
Description for the changelog
Moving docker API to 1.24 for windows
Licensing
This contribution is under the terms of the Apache 2.0 License: yes