@@ -452,4 +452,141 @@ describe('AwsEcsResourceDetector', () => {
452452 } ) ;
453453 } ) ;
454454 } ) ;
455+
456+ describe ( 'Container ID extraction' , ( ) => {
457+ const testMetadataUri = 'http://169.254.170.2/v4/test' ;
458+ const testHostname = 'test-hostname' ;
459+ let readStub : sinon . SinonStub ;
460+
461+ beforeEach ( ( ) => {
462+ process . env . ECS_CONTAINER_METADATA_URI_V4 = testMetadataUri ;
463+ } ) ;
464+
465+ afterEach ( ( ) => {
466+ sinon . restore ( ) ;
467+ } ) ;
468+
469+ function setupMocks ( cgroupData : string ) {
470+ sinon . stub ( os , 'hostname' ) . returns ( testHostname ) ;
471+ readStub = sinon
472+ . stub ( AwsEcsDetector , 'readFileAsync' as any )
473+ . resolves ( cgroupData ) ;
474+ }
475+
476+ function setupMetadataNock ( ) {
477+ return nock ( 'http://169.254.170.2:80' )
478+ . persist ( false )
479+ . get ( '/v4/test' )
480+ . reply ( 200 , {
481+ ContainerARN : 'arn:aws:ecs:us-west-2:111122223333:container/test' ,
482+ } )
483+ . get ( '/v4/test/task' )
484+ . reply ( 200 , {
485+ TaskARN : 'arn:aws:ecs:us-west-2:111122223333:task/default/test' ,
486+ Family : 'test-family' ,
487+ Revision : '1' ,
488+ Cluster : 'test-cluster' ,
489+ LaunchType : 'FARGATE' ,
490+ } ) ;
491+ }
492+
493+ it ( 'should extract full container ID from new ECS Fargate format' , async ( ) => {
494+ const taskId = 'c23e5f76c09d438aa1824ca4058bdcab' ;
495+ const containerId = '1234567890abcdef' ;
496+ const cgroupData = `/ecs/${ taskId } /${ taskId } -${ containerId } ` ;
497+
498+ setupMocks ( cgroupData ) ;
499+ const nockScope = setupMetadataNock ( ) ;
500+
501+ const resource = detectResources ( { detectors : [ awsEcsDetector ] } ) ;
502+ await resource . waitForAsyncAttributes ?.( ) ;
503+
504+ sinon . assert . calledOnce ( readStub ) ;
505+ assert . ok ( resource ) ;
506+ assertEcsResource ( resource , { } ) ;
507+ assertContainerResource ( resource , {
508+ name : testHostname ,
509+ id : `${ taskId } -${ containerId } ` ,
510+ } ) ;
511+
512+ nockScope . done ( ) ;
513+ } ) ;
514+
515+ it ( 'should handle backward compatibility with legacy format' , async ( ) => {
516+ const legacyContainerId =
517+ 'abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm' ;
518+
519+ setupMocks ( legacyContainerId ) ;
520+ const nockScope = setupMetadataNock ( ) ;
521+
522+ const resource = detectResources ( { detectors : [ awsEcsDetector ] } ) ;
523+ await resource . waitForAsyncAttributes ?.( ) ;
524+
525+ sinon . assert . calledOnce ( readStub ) ;
526+ assert . ok ( resource ) ;
527+ assertEcsResource ( resource , { } ) ;
528+ assertContainerResource ( resource , {
529+ name : testHostname ,
530+ id : 'bcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklm' ,
531+ } ) ;
532+
533+ nockScope . done ( ) ;
534+ } ) ;
535+
536+ it ( 'should extract container ID from Docker format cgroup' , async ( ) => {
537+ const dockerContainerId =
538+ 'a4d00c9dd675d67f866c786181419e1b44832d4696780152e61afd44a3e02856' ;
539+ const cgroupData = `1:blkio:/docker/${ dockerContainerId }
540+ 2:cpu:/docker/${ dockerContainerId }
541+ 3:cpuacct:/docker/${ dockerContainerId } ` ;
542+
543+ setupMocks ( cgroupData ) ;
544+ const nockScope = setupMetadataNock ( ) ;
545+
546+ const resource = detectResources ( { detectors : [ awsEcsDetector ] } ) ;
547+ await resource . waitForAsyncAttributes ?.( ) ;
548+
549+ sinon . assert . calledOnce ( readStub ) ;
550+ assert . ok ( resource ) ;
551+ assertEcsResource ( resource , { } ) ;
552+ assertContainerResource ( resource , {
553+ name : testHostname ,
554+ id : dockerContainerId ,
555+ } ) ;
556+
557+ nockScope . done ( ) ;
558+ } ) ;
559+
560+ it ( 'should extract container ID from mixed ECS and Docker format cgroup' , async ( ) => {
561+ const taskId = '447438d8540d49dca93b4f0a488ebe90' ;
562+ const containerId = `${ taskId } -1364044452` ;
563+ const cgroupData = `11:memory:/ecs/${ taskId } /${ containerId }
564+ 10:devices:/ecs/${ taskId } /${ containerId }
565+ 9:freezer:/ecs/${ taskId } /${ containerId }
566+ 8:blkio:/ecs/${ taskId } /${ containerId }
567+ 7:perf_event:/ecs/${ taskId } /${ containerId }
568+ 6:net_cls,net_prio:/ecs/${ taskId } /${ containerId }
569+ 5:cpuset:/ecs/${ taskId } /${ containerId }
570+ 4:pids:/ecs/${ taskId } /${ containerId }
571+ 3:hugetlb:/ecs/${ taskId } /${ containerId }
572+ 2:cpu,cpuacct:/ecs/${ taskId } /${ containerId }
573+ 1:name=systemd:/ecs/${ taskId } /${ containerId } ` ;
574+
575+ setupMocks ( cgroupData ) ;
576+ const nockScope = setupMetadataNock ( ) ;
577+
578+ const resource = detectResources ( { detectors : [ awsEcsDetector ] } ) ;
579+ await resource . waitForAsyncAttributes ?.( ) ;
580+
581+ sinon . assert . calledOnce ( readStub ) ;
582+ assert . ok ( resource ) ;
583+ assertEcsResource ( resource , { } ) ;
584+ assertContainerResource ( resource , {
585+ name : testHostname ,
586+ id : containerId ,
587+ } ) ;
588+
589+ nockScope . done ( ) ;
590+ } ) ;
591+ } ) ;
455592} ) ;
0 commit comments