From f66cc0a84d4fe272138de66f10cc2c050a6ba8ae Mon Sep 17 00:00:00 2001 From: Amogh Rathore Date: Tue, 17 Sep 2024 01:36:01 +0000 Subject: [PATCH 1/3] Check if nsenter is available and bind mount it --- ecs-init/docker/docker_config.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ecs-init/docker/docker_config.go b/ecs-init/docker/docker_config.go index bfc5cf8c792..9c1f7c515cc 100644 --- a/ecs-init/docker/docker_config.go +++ b/ecs-init/docker/docker_config.go @@ -15,8 +15,10 @@ package docker import ( "fmt" + "os" "github.com/aws/amazon-ecs-agent/ecs-init/config" + "github.com/cihub/seelog" ctrdapparmor "github.com/containerd/containerd/pkg/apparmor" godocker "github.com/fsouza/go-dockerclient" ) @@ -46,6 +48,13 @@ func createHostConfig(binds []string) *godocker.HostConfig { "/usr/bin/lsblk:/usr/bin/lsblk", ) + const nsenterPath = "/usr/bin/nsenter" + if _, err := os.Stat(nsenterPath); err == nil { + binds = append(binds, nsenterPath+":"+nsenterPath) + } else { + seelog.Warnf("nsenter not found at %s, skip binding it to Agent container", nsenterPath) + } + logConfig := config.AgentDockerLogDriverConfiguration() var caps []string From 12df81fcecfcfb47aa758584f729b0e531b5fd28 Mon Sep 17 00:00:00 2001 From: Amogh Rathore Date: Tue, 17 Sep 2024 02:20:07 +0000 Subject: [PATCH 2/3] Add tests --- ecs-init/docker/docker_config.go | 21 +++++++++----- ecs-init/docker/docker_config_test.go | 40 +++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 ecs-init/docker/docker_config_test.go diff --git a/ecs-init/docker/docker_config.go b/ecs-init/docker/docker_config.go index 9c1f7c515cc..be5de265690 100644 --- a/ecs-init/docker/docker_config.go +++ b/ecs-init/docker/docker_config.go @@ -47,13 +47,7 @@ func createHostConfig(binds []string) *godocker.HostConfig { iptablesLegacyDir+":"+iptablesLegacyDir+readOnly, "/usr/bin/lsblk:/usr/bin/lsblk", ) - - const nsenterPath = "/usr/bin/nsenter" - if _, err := os.Stat(nsenterPath); err == nil { - binds = append(binds, nsenterPath+":"+nsenterPath) - } else { - seelog.Warnf("nsenter not found at %s, skip binding it to Agent container", nsenterPath) - } + binds = bindNsenterIfAvailable(binds, os.Stat) logConfig := config.AgentDockerLogDriverConfiguration() @@ -89,3 +83,16 @@ func createHostConfig(binds []string) *godocker.HostConfig { return hostConfig } + +// Appends nsenter to provided binds slice if it is found on the host and returns it. +// Returns the input slice otherwise. +func bindNsenterIfAvailable(binds []string, statFn func(string) (os.FileInfo, error)) []string { + const nsenterPath = "/usr/bin/nsenter" + if _, err := statFn(nsenterPath); err == nil { + binds = append(binds, nsenterPath+":"+nsenterPath) + } else { + seelog.Warnf("nsenter not found at %s, skip binding it to Agent container: %v", + nsenterPath, err) + } + return binds +} diff --git a/ecs-init/docker/docker_config_test.go b/ecs-init/docker/docker_config_test.go new file mode 100644 index 00000000000..ac979b1074b --- /dev/null +++ b/ecs-init/docker/docker_config_test.go @@ -0,0 +1,40 @@ +// Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"). You may +// not use this file except in compliance with the License. A copy of the +// License is located at +// +// http://aws.amazon.com/apache2.0/ +// +// or in the "license" file accompanying this file. This file is distributed +// on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either +// express or implied. See the License for the specific language governing +// permissions and limitations under the License. + +package docker + +import ( + "errors" + "os" + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestBindNsenterIfAvailable(t *testing.T) { + t.Run("nsenter not found", func(t *testing.T) { + binds := bindNsenterIfAvailable( + []string{}, + func(s string) (os.FileInfo, error) { return nil, errors.New("not found") }) + assert.Empty(t, binds) + }) + + t.Run("nsenter is found", func(t *testing.T) { + binds := bindNsenterIfAvailable( + []string{}, + func(s string) (os.FileInfo, error) { return nil, nil }) + require.Len(t, binds, 1) + assert.Equal(t, "/usr/bin/nsenter:/usr/bin/nsenter", binds[0]) + }) +} From 1a5748b0dccfd610ca9400275bfba3cfd2da74be Mon Sep 17 00:00:00 2001 From: Amogh Rathore Date: Tue, 17 Sep 2024 16:39:42 +0000 Subject: [PATCH 3/3] Test update --- ecs-init/docker/docker_config.go | 9 +++++---- ecs-init/docker/docker_config_test.go | 8 +++----- ecs-init/docker/docker_test.go | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/ecs-init/docker/docker_config.go b/ecs-init/docker/docker_config.go index be5de265690..d4f4b95549d 100644 --- a/ecs-init/docker/docker_config.go +++ b/ecs-init/docker/docker_config.go @@ -47,7 +47,7 @@ func createHostConfig(binds []string) *godocker.HostConfig { iptablesLegacyDir+":"+iptablesLegacyDir+readOnly, "/usr/bin/lsblk:/usr/bin/lsblk", ) - binds = bindNsenterIfAvailable(binds, os.Stat) + binds = append(binds, getNsenterBinds(os.Stat)...) logConfig := config.AgentDockerLogDriverConfiguration() @@ -84,9 +84,10 @@ func createHostConfig(binds []string) *godocker.HostConfig { return hostConfig } -// Appends nsenter to provided binds slice if it is found on the host and returns it. -// Returns the input slice otherwise. -func bindNsenterIfAvailable(binds []string, statFn func(string) (os.FileInfo, error)) []string { +// Returns nsenter bind as a slice if nsenter is available on the host. +// Returns an empty slice otherwise. +func getNsenterBinds(statFn func(string) (os.FileInfo, error)) []string { + binds := []string{} const nsenterPath = "/usr/bin/nsenter" if _, err := statFn(nsenterPath); err == nil { binds = append(binds, nsenterPath+":"+nsenterPath) diff --git a/ecs-init/docker/docker_config_test.go b/ecs-init/docker/docker_config_test.go index ac979b1074b..a71ef2b291b 100644 --- a/ecs-init/docker/docker_config_test.go +++ b/ecs-init/docker/docker_config_test.go @@ -22,17 +22,15 @@ import ( "github.com/stretchr/testify/require" ) -func TestBindNsenterIfAvailable(t *testing.T) { +func TestGetNsenterBinds(t *testing.T) { t.Run("nsenter not found", func(t *testing.T) { - binds := bindNsenterIfAvailable( - []string{}, + binds := getNsenterBinds( func(s string) (os.FileInfo, error) { return nil, errors.New("not found") }) assert.Empty(t, binds) }) t.Run("nsenter is found", func(t *testing.T) { - binds := bindNsenterIfAvailable( - []string{}, + binds := getNsenterBinds( func(s string) (os.FileInfo, error) { return nil, nil }) require.Len(t, binds, 1) assert.Equal(t, "/usr/bin/nsenter:/usr/bin/nsenter", binds[0]) diff --git a/ecs-init/docker/docker_test.go b/ecs-init/docker/docker_test.go index 270e17becbd..10450ec4b8d 100644 --- a/ecs-init/docker/docker_test.go +++ b/ecs-init/docker/docker_test.go @@ -32,7 +32,7 @@ import ( // Note: Change this value every time when a new bind mount is added to // agent for the tests to pass const ( - defaultExpectedAgentBinds = 20 + defaultExpectedAgentBinds = 21 ) func TestIsAgentImageLoadedListFailure(t *testing.T) {