From c60a86c4b90dbede0b063b28d4df9e20cdb01804 Mon Sep 17 00:00:00 2001 From: Cameron Sparr Date: Fri, 26 Jan 2024 11:28:42 -0800 Subject: [PATCH] ecs-init support for old docker engines (pre docker 17.x) and future docker engines (when api 1.25 is deprecated). --- ecs-init/docker/dependencies.go | 101 ++++++++++++++++-- ecs-init/docker/dependencies_test.go | 152 ++++++++++++++++++++++----- ecs-init/docker/docker.go | 6 +- ecs-init/docker/docker_config.go | 7 +- ecs-init/docker/docker_test.go | 98 +++-------------- 5 files changed, 249 insertions(+), 115 deletions(-) diff --git a/ecs-init/docker/dependencies.go b/ecs-init/docker/dependencies.go index 53dc2584361..e1d2efc4b23 100644 --- a/ecs-init/docker/dependencies.go +++ b/ecs-init/docker/dependencies.go @@ -30,14 +30,13 @@ import ( ) const ( - // dockerClientAPIVersion specifies the minimum docker client API version - // required by ECS Init - // Version 1.25 is required for setting Init to true when constructing - // the HostConfig for creating the ECS Agent to enable the Task - // Networking with ENI capability - dockerClientAPIVersion = "1.25" + // enableTaskENIDockerClientAPIVersion is the docker version at which we enable + // the ECS_ENABLE_TASK_ENI env var and set agent's "Init" field to true. + enableTaskENIDockerClientAPIVersion = "1.25" ) +var dockerAPIVersion string + type dockerclient interface { ListImages(opts godocker.ListImagesOptions) ([]godocker.APIImages, error) LoadImage(opts godocker.LoadImageOptions) error @@ -65,13 +64,98 @@ func (client godockerClientFactory) NewVersionedClient(endpoint string, apiVersi return godocker.NewVersionedClient(endpoint, apiVersionString) } +// backupAPIVersions are API versions that have been deprecated on docker engine 25, +// they are only checked if none of the preferredAPIVersions are available. +// This list can be updated with time as docker engine deprecates more API versions. +func backupAPIVersions() []string { + return []string{ + "1.21", + "1.22", + "1.23", + "1.24", + } +} + +// preferredAPIVersions returns the preferred list of docker client API versions. +// When establishing the docker client for ecs-init to use, we will try these API version +// numbers first. +func preferredAPIVersions() []string { + return []string{ + "1.25", + "1.26", + "1.27", + "1.28", + "1.29", + "1.30", + "1.31", + "1.32", + "1.33", + "1.34", + "1.35", + "1.36", + "1.37", + "1.38", + "1.39", + "1.40", + "1.41", + "1.42", + "1.43", + "1.44", + } +} + +// knownAPIVersions returns all known docker API versions, in order from +// oldest to newest. +func knownAPIVersions() []string { + return append(backupAPIVersions(), preferredAPIVersions()...) +} + +// dockerVersionCompare returns 0 if lhs and rhs are equal. +// returns 1 if lhs > rhs +// returns -1 if lhs < rhs +func dockerVersionCompare(lhs, rhs string) int { + if lhs == rhs { + return 0 + } + var lhsI int = -1 + var rhsI int = -1 + for i, v := range knownAPIVersions() { + if lhs == v { + lhsI = i + } + if rhs == v { + rhsI = i + } + } + if lhsI < rhsI { + return -1 + } + return 1 +} + func newDockerClient(dockerClientFactory dockerClientFactory, pingBackoff backoff.Backoff) (dockerclient, error) { + var dockerClient dockerclient + var err error + allAPIVersions := append(preferredAPIVersions(), backupAPIVersions()...) + for _, apiVersion := range allAPIVersions { + dockerClient, err = newVersionedDockerClient(apiVersion, dockerClientFactory, pingBackoff) + if err == nil { + log.Infof("Successfully created docker client with API version %s", apiVersion) + dockerAPIVersion = apiVersion + break + } + log.Infof("Could not create docker client with API version %s: %s", apiVersion, err) + } + return dockerClient, err +} + +func newVersionedDockerClient(apiVersion string, dockerClientFactory dockerClientFactory, pingBackoff backoff.Backoff) (dockerclient, error) { dockerUnixSocketSourcePath, fromEnv := config.DockerUnixSocket() if !fromEnv { dockerUnixSocketSourcePath = "/var/run/docker.sock" } client, err := dockerClientFactory.NewVersionedClient( - config.UnixSocketPrefix+dockerUnixSocketSourcePath, dockerClientAPIVersion) + config.UnixSocketPrefix+dockerUnixSocketSourcePath, apiVersion) if err != nil { return nil, err } @@ -157,6 +241,9 @@ func isNetworkError(err error) bool { func isRetryablePingError(err error) bool { godockerError, ok := err.(*godocker.Error) if ok { + if godockerError.Status == http.StatusBadRequest { + return false + } return godockerError.Status != http.StatusOK } return false diff --git a/ecs-init/docker/dependencies_test.go b/ecs-init/docker/dependencies_test.go index 66a630b77c8..2cf256e7dc2 100644 --- a/ecs-init/docker/dependencies_test.go +++ b/ecs-init/docker/dependencies_test.go @@ -1,6 +1,3 @@ -//go:build test -// +build test - // Copyright 2015-2017 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may @@ -35,6 +32,7 @@ const immediately = time.Duration(-1) var netError = &url.Error{Err: &net.OpError{Op: "read", Net: "unix", Err: io.EOF}} var httpError = &docker.Error{Status: http.StatusInternalServerError, Message: "error"} +var badRequestError = &docker.Error{Status: http.StatusBadRequest, Message: "Bad Request Error"} func TestIsNetworkErrorReturnsTrue(t *testing.T) { assert.True(t, isNetworkError(netError), "Expect isNetworkError to return true if network error passed in") @@ -48,6 +46,10 @@ func TestIsRetryablePingErrorReturnsTrue(t *testing.T) { assert.True(t, isRetryablePingError(httpError), "Expect RetryablePingError to be true if httpError passed in") } +func TestIsRetryableBadRequestErrorReturnsFalse(t *testing.T) { + assert.False(t, isRetryablePingError(badRequestError), "Expect RetryablePingError to be false if 'bad request' client error passed in") +} + func TestIsRetryablePingErrorReturnsFalse(t *testing.T) { assert.False(t, isRetryablePingError(fmt.Errorf("error")), "Expect RetryablePingError to be true if non-http error passed in") } @@ -100,10 +102,33 @@ func TestNewDockerClientDoesnotRetryOnPingNonNetworkError(t *testing.T) { mockClientFactory := NewMockdockerClientFactory(ctrl) mockBackoff := NewMockBackoff(ctrl) - gomock.InOrder( - mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), gomock.Any()).Return(mockDockerClient, nil), - mockDockerClient.EXPECT().Ping().Return(fmt.Errorf("error")), - ) + calls := []*gomock.Call{} + for _, apiVersion := range append(preferredAPIVersions(), backupAPIVersions()...) { + t.Logf("Expecting NewVersionedClient call with docker api version %s", apiVersion) + calls = append(calls, mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), apiVersion).Return(mockDockerClient, nil)) + calls = append(calls, mockDockerClient.EXPECT().Ping().Return(fmt.Errorf("error"))) + } + gomock.InOrder(calls...) + + _, err := newDockerClient(mockClientFactory, mockBackoff) + assert.Error(t, err, "Expect error when creating docker client with no retry") +} + +func TestNewDockerClientDoesNotRetryOnHTTPBadRequestError(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + mockDockerClient := NewMockdockerclient(ctrl) + mockClientFactory := NewMockdockerClientFactory(ctrl) + mockBackoff := NewMockBackoff(ctrl) + + calls := []*gomock.Call{} + for _, apiVersion := range append(preferredAPIVersions(), backupAPIVersions()...) { + t.Logf("Expecting NewVersionedClient call with docker api version %s", apiVersion) + calls = append(calls, mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), apiVersion).Return(mockDockerClient, nil)) + calls = append(calls, mockDockerClient.EXPECT().Ping().Return(badRequestError)) + } + gomock.InOrder(calls...) _, err := newDockerClient(mockClientFactory, mockBackoff) assert.Error(t, err, "Expect error when creating docker client with no retry") @@ -117,14 +142,17 @@ func TestNewDockerClientGivesUpRetryingOnPingNetworkError(t *testing.T) { mockClientFactory := NewMockdockerClientFactory(ctrl) mockBackoff := NewMockBackoff(ctrl) - gomock.InOrder( - mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), gomock.Any()).Return(mockDockerClient, nil), - mockDockerClient.EXPECT().Ping().Return(netError), - mockBackoff.EXPECT().ShouldRetry().Return(true), - mockBackoff.EXPECT().Duration().Return(immediately), - mockDockerClient.EXPECT().Ping().Return(netError), - mockBackoff.EXPECT().ShouldRetry().Return(false), - ) + calls := []*gomock.Call{} + for _, apiVersion := range append(preferredAPIVersions(), backupAPIVersions()...) { + t.Logf("Expecting NewVersionedClient call with docker api version %s", apiVersion) + calls = append(calls, mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), apiVersion).Return(mockDockerClient, nil)) + calls = append(calls, mockDockerClient.EXPECT().Ping().Return(netError)) + calls = append(calls, mockBackoff.EXPECT().ShouldRetry().Return(true)) + calls = append(calls, mockBackoff.EXPECT().Duration().Return(immediately)) + calls = append(calls, mockDockerClient.EXPECT().Ping().Return(netError)) + calls = append(calls, mockBackoff.EXPECT().ShouldRetry().Return(false)) + } + gomock.InOrder(calls...) _, err := newDockerClient(mockClientFactory, mockBackoff) assert.Error(t, err, "Expect error when creating docker client with no retry") @@ -137,20 +165,20 @@ func TestNewDockerClientGivesUpRetryingOnUnavailableSocket(t *testing.T) { mockClientFactory := NewMockdockerClientFactory(ctrl) mockBackoff := NewMockBackoff(ctrl) - realDockerClient, dockerClientErr := godockerClientFactory{}.NewVersionedClient("unix:///a/bad/docker.sock", dockerClientAPIVersion) + realDockerClient, dockerClientErr := godockerClientFactory{}.NewVersionedClient("unix:///a/bad/docker.sock", "1.25") require.False(t, dockerClientErr != nil, "there should be no errors trying to set up a docker client (intentionally bad with nonexistent socket path") - gomock.InOrder( - // We use the real client to ensure we're classifying errors - // correctly as returned by the upstream's error handling. - mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), gomock.Any()).Return(realDockerClient, dockerClientErr), + calls := []*gomock.Call{} + for _, apiVersion := range append(preferredAPIVersions(), backupAPIVersions()...) { + t.Logf("Expecting NewVersionedClient call with docker api version %s", apiVersion) + calls = append(calls, mockClientFactory.EXPECT().NewVersionedClient(gomock.Any(), apiVersion).Return(realDockerClient, nil)) // "bad connection", retries - mockBackoff.EXPECT().ShouldRetry().Return(true), - mockBackoff.EXPECT().Duration().Return(immediately), - // Give up - mockBackoff.EXPECT().ShouldRetry().Return(false), - ) + calls = append(calls, mockBackoff.EXPECT().ShouldRetry().Return(true)) + calls = append(calls, mockBackoff.EXPECT().Duration().Return(immediately)) + calls = append(calls, mockBackoff.EXPECT().ShouldRetry().Return(false)) + } + gomock.InOrder(calls...) _, err := newDockerClient(mockClientFactory, mockBackoff) require.Error(t, err, "expect an error when creating docker client") @@ -160,3 +188,77 @@ func TestNewDockerClientGivesUpRetryingOnUnavailableSocket(t *testing.T) { _, isExpectedError := err.(*url.Error) assert.True(t, isExpectedError, "expect net.OpError wrapped by url.Error") } + +func TestDockerVersionCompare(t *testing.T) { + testCases := []struct { + lhs string + rhs string + expectedResult int + }{ + { + lhs: "1.21", + rhs: "1.24", + expectedResult: -1, + }, + { + lhs: "1.21", + rhs: "1.25", + expectedResult: -1, + }, + { + lhs: "1.21", + rhs: "1.44", + expectedResult: -1, + }, + { + lhs: "1.21", + rhs: "1.21", + expectedResult: 0, + }, + { + lhs: "1.25", + rhs: "1.25", + expectedResult: 0, + }, + { + lhs: "1.35", + rhs: "1.35", + expectedResult: 0, + }, + { + lhs: "1.44", + rhs: "1.44", + expectedResult: 0, + }, + { + lhs: "1.24", + rhs: "1.22", + expectedResult: 1, + }, + { + lhs: "1.25", + rhs: "1.22", + expectedResult: 1, + }, + { + lhs: "1.34", + rhs: "1.25", + expectedResult: 1, + }, + { + lhs: "1.44", + rhs: "1.21", + expectedResult: 1, + }, + { + lhs: "1.44", + rhs: "1.26", + expectedResult: 1, + }, + } + for _, tc := range testCases { + actualResult := dockerVersionCompare(tc.lhs, tc.rhs) + testName := fmt.Sprintf("lhs=%s rhs=%s expectedResult=%d", tc.lhs, tc.rhs, tc.expectedResult) + assert.Equal(t, tc.expectedResult, actualResult, testName) + } +} diff --git a/ecs-init/docker/docker.go b/ecs-init/docker/docker.go index a2d836795b4..c4a9b3de630 100644 --- a/ecs-init/docker/docker.go +++ b/ecs-init/docker/docker.go @@ -59,7 +59,7 @@ const ( minBackoffDuration = time.Second // maxBackoffDuration specifies the maximum backoff duration for ping to // return a success response from docker socket - maxBackoffDuration = 5 * time.Second + maxBackoffDuration = 3 * time.Second // backoffJitterMultiple specifies the backoff jitter multiplier // coefficient when pinging the docker socket backoffJitterMultiple = 0.2 @@ -327,6 +327,10 @@ func (c *client) getContainerConfig(envVarsFromFiles map[string]string) *godocke // Task networking is not supported when not running on EC2. Explicitly disable since it's enabled by default. envVariables["ECS_ENABLE_TASK_ENI"] = "false" } + if dockerVersionCompare(dockerAPIVersion, enableTaskENIDockerClientAPIVersion) < 0 { + // Task networking is not supported before docker API version 1.25 + envVariables["ECS_ENABLE_TASK_ENI"] = "false" + } if !isPathValid(config.MountDirectoryEBS(), true) { // EBS Task Attach (EBSTA) is not supported for external instances diff --git a/ecs-init/docker/docker_config.go b/ecs-init/docker/docker_config.go index 7a43f9a8974..bfc5cf8c792 100644 --- a/ecs-init/docker/docker_config.go +++ b/ecs-init/docker/docker_config.go @@ -62,7 +62,12 @@ func createHostConfig(binds []string) *godocker.HostConfig { NetworkMode: networkMode, UsernsMode: usernsMode, CapAdd: caps, - Init: true, + } + + // Task ENI feature requires agent to be "init" process, so set it if docker API + // version is new enough for this feature. + if dockerVersionCompare(dockerAPIVersion, enableTaskENIDockerClientAPIVersion) >= 0 { + hostConfig.Init = true } if ctrdapparmor.HostSupports() { diff --git a/ecs-init/docker/docker_test.go b/ecs-init/docker/docker_test.go index 0fa1a11802f..270e17becbd 100644 --- a/ecs-init/docker/docker_test.go +++ b/ecs-init/docker/docker_test.go @@ -1,6 +1,3 @@ -//go:build test -// +build test - // Copyright 2015-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may @@ -31,16 +28,13 @@ import ( "github.com/stretchr/testify/assert" ) -// expectedAgentBinds is the total number of agent host config binds. +// defaultExpectedAgentBinds is the total number of agent host config binds. // Note: Change this value every time when a new bind mount is added to // agent for the tests to pass const ( - expectedAgentBindsUnspecifiedPlatform = 20 - expectedAgentBindsSuseUbuntuPlatform = 18 + defaultExpectedAgentBinds = 20 ) -var expectedAgentBinds = expectedAgentBindsUnspecifiedPlatform - func TestIsAgentImageLoadedListFailure(t *testing.T) { mockCtrl := gomock.NewController(t) defer mockCtrl.Finish() @@ -203,7 +197,7 @@ func TestStartAgentNoEnvFile(t *testing.T) { mockFS.EXPECT().ReadFile(config.InstanceConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockFS.EXPECT().ReadFile(config.AgentConfigFile()).Return(nil, errors.New("test error")).AnyTimes() mockDocker.EXPECT().CreateContainer(gomock.Any()).Do(func(opts godocker.CreateContainerOptions) { - validateCommonCreateContainerOptions(opts, t) + validateCommonCreateContainerOptions(t, opts, defaultExpectedAgentBinds) }).Return(&godocker.Container{ ID: containerID, }, nil) @@ -221,7 +215,11 @@ func TestStartAgentNoEnvFile(t *testing.T) { } } -func validateCommonCreateContainerOptions(opts godocker.CreateContainerOptions, t *testing.T) { +func validateCommonCreateContainerOptions( + t *testing.T, + opts godocker.CreateContainerOptions, + expectedAgentBinds int, +) { if opts.Name != "ecs-agent" { t.Errorf("Expected container Name to be %s but was %s", "ecs-agent", opts.Name) } @@ -252,17 +250,7 @@ func validateCommonCreateContainerOptions(opts godocker.CreateContainerOptions, hostCfg := opts.HostConfig - // for hosts that do not have cert directories explicity mounted, ignore - // host cert directory configuration. - // TODO (adnxn): ideally, these should be behind build flags. - // https://github.com/aws/amazon-ecs-init/issues/131 - if certDir := config.HostPKIDirPath(); certDir == "" { - expectedAgentBinds = expectedAgentBindsSuseUbuntuPlatform - } - - if len(hostCfg.Binds) != expectedAgentBinds { - t.Errorf("Expected exactly %d elements to be in Binds, but was %d", expectedAgentBinds, len(hostCfg.Binds)) - } + assert.Len(t, hostCfg.Binds, expectedAgentBinds) binds := make(map[string]struct{}) for _, binding := range hostCfg.Binds { binds[binding] = struct{}{} @@ -317,9 +305,7 @@ func validateCommonCreateContainerOptions(opts godocker.CreateContainerOptions, } func expectKey(key string, input map[string]struct{}, t *testing.T) { - if _, ok := input[key]; !ok { - t.Errorf("Expected %s to be defined", key) - } + assert.Contains(t, input, key) } func TestStartAgentEnvFile(t *testing.T) { @@ -341,7 +327,7 @@ func TestStartAgentEnvFile(t *testing.T) { mockFS.EXPECT().ReadFile(config.InstanceConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockFS.EXPECT().ReadFile(config.AgentConfigFile()).Return([]byte(envFile), nil).AnyTimes() mockDocker.EXPECT().CreateContainer(gomock.Any()).Do(func(opts godocker.CreateContainerOptions) { - validateCommonCreateContainerOptions(opts, t) + validateCommonCreateContainerOptions(t, opts, defaultExpectedAgentBinds) cfg := opts.Config envVariables := make(map[string]struct{}) @@ -378,11 +364,11 @@ func TestStartAgentWithGPUConfig(t *testing.T) { envFile := "\nECS_ENABLE_GPU_SUPPORT=true\n" containerID := "container id" + expectedAgentBinds := defaultExpectedAgentBinds expectedAgentBinds += 1 defer func() { MatchFilePatternForGPU = FilePatternMatchForGPU - expectedAgentBinds = expectedAgentBindsUnspecifiedPlatform }() MatchFilePatternForGPU = func(pattern string) ([]string, error) { return []string{"/dev/nvidia0", "/dev/nvidia1"}, nil @@ -394,7 +380,7 @@ func TestStartAgentWithGPUConfig(t *testing.T) { mockFS.EXPECT().ReadFile(config.InstanceConfigFile()).Return([]byte(envFile), nil).AnyTimes() mockFS.EXPECT().ReadFile(config.AgentConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockDocker.EXPECT().CreateContainer(gomock.Any()).Do(func(opts godocker.CreateContainerOptions) { - validateCommonCreateContainerOptions(opts, t) + validateCommonCreateContainerOptions(t, opts, expectedAgentBinds) var found bool for _, bind := range opts.HostConfig.Binds { if bind == gpu.GPUInfoDirPath+":"+gpu.GPUInfoDirPath { @@ -452,7 +438,7 @@ func TestStartAgentWithGPUConfigNoDevices(t *testing.T) { mockFS.EXPECT().ReadFile(config.InstanceConfigFile()).Return([]byte(envFile), nil).AnyTimes() mockFS.EXPECT().ReadFile(config.AgentConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockDocker.EXPECT().CreateContainer(gomock.Any()).Do(func(opts godocker.CreateContainerOptions) { - validateCommonCreateContainerOptions(opts, t) + validateCommonCreateContainerOptions(t, opts, defaultExpectedAgentBinds) cfg := opts.Config envVariables := make(map[string]struct{}) @@ -837,12 +823,12 @@ func TestStartAgentWithExecBinds(t *testing.T) { hostResourcesRootDir + ":" + containerResourcesRootDir + readOnly, hostConfigDir + ":" + containerConfigDir, } - expectedAgentBinds += len(expectedExecBinds) + expectedAgentBinds := defaultExpectedAgentBinds + expectedAgentBinds += len(expectedExecBinds) // bind mount for the config folder is already included in expectedAgentBinds since it's always added expectedExecBinds = append(expectedExecBinds, hostConfigDir+":"+containerConfigDir) defer func() { - expectedAgentBinds = expectedAgentBindsUnspecifiedPlatform isPathValid = defaultIsPathValid }() @@ -852,7 +838,7 @@ func TestStartAgentWithExecBinds(t *testing.T) { mockFS.EXPECT().ReadFile(config.InstanceConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockFS.EXPECT().ReadFile(config.AgentConfigFile()).Return(nil, errors.New("not found")).AnyTimes() mockDocker.EXPECT().CreateContainer(gomock.Any()).Do(func(opts godocker.CreateContainerOptions) { - validateCommonCreateContainerOptions(opts, t) + validateCommonCreateContainerOptions(t, opts, expectedAgentBinds) // verify that exec binds are added assert.Subset(t, opts.HostConfig.Binds, expectedExecBinds) @@ -985,56 +971,6 @@ func TestDefaultIsPathValid(t *testing.T) { } } -func TestGetCredentialsFetcherSocketBind(t *testing.T) { - testCases := []struct { - name string - credentialsFetcherHostFromEnv string - credentialsFetcherHostFromConfigFile string - expectedBind string - }{ - { - name: "No Credentials Fetcher host from env", - credentialsFetcherHostFromEnv: "", - credentialsFetcherHostFromConfigFile: "dummy", - expectedBind: "/var/credentials-fetcher/socket/credentials_fetcher.sock:/var/credentials-fetcher/socket/credentials_fetcher.sock", - }, - { - name: "Invalid Credentials Fetcher host from env", - credentialsFetcherHostFromEnv: "invalid", - credentialsFetcherHostFromConfigFile: "dummy", - expectedBind: "/var/credentials-fetcher/socket/credentials_fetcher.sock:/var/credentials-fetcher/socket/credentials_fetcher.sock", - }, - { - name: "Credentials Fetcher from env, no Credentials Fetcher from config file", - credentialsFetcherHostFromEnv: "unix:///var/credentials-fetcher/socket/credentials_fetcher.sock", - credentialsFetcherHostFromConfigFile: "", - expectedBind: "/var/credentials-fetcher/socket/credentials_fetcher.sock:/var/credentials-fetcher/socket/credentials_fetcher.sock", - }, - { - name: "Credentials Fetcher from env, invalid Credentials Fetcher from config file", - credentialsFetcherHostFromEnv: "unix:///var/credentials-fetcher/socket/credentials_fetcher.sock", - credentialsFetcherHostFromConfigFile: "invalid", - expectedBind: "/var/credentials-fetcher/socket/credentials_fetcher.sock:/var/credentials-fetcher/socket/credentials_fetcher.sock", - }, - { - name: "Credentials Fetcher host from env, Credentials Fetcher from config file", - credentialsFetcherHostFromEnv: "unix:///var/credentials-fetcher/socket/credentials_fetcher.sock.1", - credentialsFetcherHostFromConfigFile: "unix:///var/credentials-fetcher/socket/credentials_fetcher.sock.1", - expectedBind: "/var/credentials-fetcher/socket/credentials_fetcher.sock.1:/var/credentials-fetcher/socket/credentials_fetcher.sock.1", - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - os.Setenv("CREDENTIALS_FETCHER_HOST", tc.credentialsFetcherHostFromEnv) - defer os.Unsetenv("CREDENTIALS_FETCHER_HOST") - - bind, _ := getCredentialsFetcherSocketBind() - assert.Equal(t, tc.expectedBind, bind) - }) - } -} - func TestInstanceDomainJoined(t *testing.T) { execCommand = fakeExecCommand execLookPath = func(name string) (string, error) {