@@ -35,6 +35,7 @@ import (
3535 ec2testutil "github.com/aws/amazon-ecs-agent/agent/utils/test/ec2util"
3636
3737 "github.com/docker/docker/api/types"
38+ dockercontainer "github.com/docker/docker/api/types/container"
3839 "github.com/golang/mock/gomock"
3940 "github.com/stretchr/testify/assert"
4041 "github.com/stretchr/testify/require"
@@ -192,6 +193,90 @@ func TestRecordContainerReferenceInspectError(t *testing.T) {
192193 }
193194}
194195
196+ func TestRecordContainerReferenceStoresManagedEnvKeysOnImageState (t * testing.T ) {
197+ envVars := []string {"PATH=/usr/local/bin" , "AWS_DEFAULT_REGION=us-east-1" }
198+ tests := []struct {
199+ name string
200+ config * dockercontainer.Config
201+ wantEnvKeys map [string ]bool
202+ }{
203+ {
204+ name : "image config with region env var — key stored on image state" ,
205+ config : & dockercontainer.Config {Env : envVars },
206+ wantEnvKeys : map [string ]bool {"AWS_DEFAULT_REGION" : true },
207+ },
208+ {
209+ name : "nil image config — ManagedEnvKeys nil on image state" ,
210+ config : nil ,
211+ wantEnvKeys : nil ,
212+ },
213+ }
214+
215+ for _ , tt := range tests {
216+ t .Run (tt .name , func (t * testing.T ) {
217+ ctrl := gomock .NewController (t )
218+ defer ctrl .Finish ()
219+ client := mock_dockerapi .NewMockDockerClient (ctrl )
220+
221+ imageManager := NewImageManager (defaultTestConfig (), client , dockerstate .NewTaskEngineState ())
222+ imageManager .SetDataClient (data .NewNoopClient ())
223+
224+ container := & apicontainer.Container {
225+ Name : "testContainer" ,
226+ Image : "testContainerImage" ,
227+ }
228+ client .EXPECT ().InspectImage (container .Image ).Return (& types.ImageInspect {
229+ ID : "sha256:qwerty" ,
230+ Config : tt .config ,
231+ }, nil )
232+
233+ err := imageManager .RecordContainerReference (container )
234+ assert .NoError (t , err )
235+
236+ imageState , ok := imageManager .GetImageStateFromImageName (container .Image )
237+ assert .True (t , ok )
238+ assert .Equal (t , tt .wantEnvKeys , imageState .GetManagedEnvKeys ())
239+ })
240+ }
241+ }
242+
243+ // TestRecordContainerReferencePreservesManagedEnvKeysOnRestart verifies that when a container
244+ // already has an ImageID set (e.g. on agent restart from saved state), RecordContainerReference
245+ // does not re-inspect the image — the ManagedEnvKeys are already persisted on ImageState.
246+ func TestRecordContainerReferencePreservesManagedEnvKeysOnRestart (t * testing.T ) {
247+ ctrl := gomock .NewController (t )
248+ defer ctrl .Finish ()
249+ client := mock_dockerapi .NewMockDockerClient (ctrl )
250+
251+ imageManager := NewImageManager (defaultTestConfig (), client , dockerstate .NewTaskEngineState ())
252+ imageManager .SetDataClient (data .NewNoopClient ())
253+
254+ const imageID = "sha256:qwerty"
255+ existingKeys := map [string ]bool {"AWS_DEFAULT_REGION" : true }
256+
257+ // Seed the image state with persisted ManagedEnvKeys (as if loaded from state file).
258+ sourceImageState := & image.ImageState {
259+ Image : & image.Image {ImageID : imageID },
260+ ManagedEnvKeys : existingKeys ,
261+ }
262+ imageManager .(* dockerImageManager ).addImageState (sourceImageState )
263+
264+ container := & apicontainer.Container {
265+ Name : "testContainer" ,
266+ Image : "testContainerImage" ,
267+ ImageID : imageID , // pre-populated, as it would be after agent restart
268+ }
269+
270+ // No InspectImage call expected — keys are already persisted.
271+ err := imageManager .RecordContainerReference (container )
272+ assert .NoError (t , err )
273+
274+ // Verify the keys are still on the image state.
275+ imageState , ok := imageManager .GetImageStateFromImageName (container .Image )
276+ assert .True (t , ok )
277+ assert .Equal (t , existingKeys , imageState .GetManagedEnvKeys ())
278+ }
279+
195280func TestRecordContainerReferenceWithNoImageName (t * testing.T ) {
196281 ctrl := gomock .NewController (t )
197282 defer ctrl .Finish ()
@@ -282,7 +367,7 @@ func TestAddContainerReferenceToExistingImageState(t *testing.T) {
282367 sourceImageState1 .AddImageName ("testContainerImage" )
283368 imageManager .addImageState (sourceImageState )
284369 imageManager .addImageState (sourceImageState1 )
285- if ! imageManager .addContainerReferenceToExistingImageState (container ) {
370+ if ! imageManager .addContainerReferenceToExistingImageState (container , nil ) {
286371 t .Error ("Error in adding container to an already existing image state" )
287372 }
288373 if ! reflect .DeepEqual (sourceImageState .Containers [0 ], container ) {
@@ -371,7 +456,7 @@ func TestAddContainerReferenceToExistingImageStateNoState(t *testing.T) {
371456 Image : "testContainerImage" ,
372457 ImageID : "sha256:qwerty" ,
373458 }
374- if imageManager .addContainerReferenceToExistingImageState (container ) {
459+ if imageManager .addContainerReferenceToExistingImageState (container , nil ) {
375460 t .Error ("Error adding container to an incorrect existing image state" )
376461 }
377462}
@@ -390,7 +475,7 @@ func TestAddContainerReferenceToNewImageState(t *testing.T) {
390475 Image : "testContainerImage" ,
391476 ImageID : imageID ,
392477 }
393- imageManager .addContainerReferenceToNewImageState (container , imageSize )
478+ imageManager .addContainerReferenceToNewImageState (container , imageSize , nil )
394479 _ , ok := imageManager .getImageState (imageID )
395480 if ! ok {
396481 t .Error ("Error adding container reference to new image state" )
@@ -426,7 +511,7 @@ func TestAddContainerReferenceToNewImageStateAddedState(t *testing.T) {
426511 sourceImageState1 .AddImageName ("testContainerImage" )
427512 imageManager .addImageState (sourceImageState )
428513 imageManager .addImageState (sourceImageState1 )
429- imageManager .addContainerReferenceToNewImageState (container , imageSize )
514+ imageManager .addContainerReferenceToNewImageState (container , imageSize , nil )
430515 if ! reflect .DeepEqual (sourceImageState .Containers [0 ], container ) {
431516 t .Error ("Incorrect container added to an already existing image state" )
432517 }
0 commit comments