1+ const { execSync } = require ( 'child_process' ) ;
2+ const path = require ( 'path' ) ;
3+ const os = require ( 'os' ) ;
4+ const fs = require ( 'fs' ) ;
5+ const { PassThrough } = require ( 'stream' ) ;
6+ const { logger, parseBool, getToken, normalizePath } = require ( path . join ( __dirname , '_common' , 'CommonTools.js' ) ) ;
7+
8+ const inputFilenameAndPath = process . env . INPUT_FILEPATHANDNAME ;
9+
10+ // this routine is intended to provide information about the agent on which it is running
11+ //
12+ // 1. platform
13+ // 2. whoami
14+ // 3. current working directory
15+ // 4. Powershell version(s)
16+ // 5. BCContainerHelper existence / version
17+ // 6. Docker existence / version
18+ // 7. Docker image list
19+
20+ ( async ( ) => {
21+ let outputFilenameAndPath ;
22+
23+ if ( inputFilenameAndPath && inputFilenameAndPath . trim ( ) !== '' ) {
24+ outputFilenameAndPath = normalizePath ( inputFilenameAndPath ) ;
25+ const pathInfo = path . parse ( outputFilenameAndPath ) ;
26+
27+ if ( ! pathInfo . base || ! pathInfo . dir ) {
28+ logger . warn ( `Invalid file path supplied: '${ outputFilenameAndPath } '. Skipping file production.` ) ;
29+ outputFilenameAndPath = undefined ;
30+ }
31+ }
32+
33+ logger . info ( 'Invoking EGEnumerateEnvironment with the following parameters:' ) ;
34+ logger . info ( 'FilePathAndName:' . padStart ( 2 ) . padEnd ( 30 ) + `${ outputFilenameAndPath } ` ) ;
35+ logger . info ( '' ) ;
36+
37+ // 0. setup
38+ const logColWidth = 30 ;
39+
40+ // 1. platform
41+ logger . info ( '[platform]:' . padEnd ( logColWidth ) + `${ os . platform ( ) } ` ) ;
42+
43+ // 2. whoami
44+ let textOut ;
45+ try {
46+ let whoami = execSync ( 'whoami' , { encoding : 'utf8' } ) ;
47+ textOut = whoami . toString ( ) . trim ( ) ;
48+ if ( textOut . length > 0 ) {
49+ logger . info ( '[whoami]: ' . padEnd ( logColWidth ) + `${ textOut } ` ) ;
50+ } else {
51+ logger . info ( '[whoami]:' . padEnd ( logColWidth ) + 'Apparently a ghost; nothing returned' ) ;
52+ }
53+ } catch ( err ) {
54+ logger . error ( `[whoami]: Encountered an error while executing a 'whoami'` ) ;
55+ logger . error ( `[whoami]: Error: ${ err } ` ) ;
56+ }
57+
58+ // 3. current working directory
59+ logger . info ( '[current working directory]:' . padEnd ( logColWidth ) + `${ process . cwd ( ) } ` ) ;
60+
61+ // 4. Powershell version(s)
62+ let psVersion ;
63+ let pwshVersion ;
64+ if ( os . platform ( ) === "win32" ) {
65+ try {
66+ psVersion = execSync (
67+ `powershell -NoProfile -Command "$v = $PSVersionTable.PSVersion; Write-Output ('' + $v.Major + '.' + $v.Minor + '.' + $v.Build + '.' + $v.Revision)"` ,
68+ { encoding : 'utf8' }
69+ ) . trim ( ) ;
70+ logger . info ( '[powershell version]:' . padEnd ( logColWidth ) + `${ psVersion } ` ) ;
71+ } catch ( err ) {
72+ logger . error ( `[powershell version]: Encountered an error while executing a 'powerhsell version'` ) ;
73+ logger . error ( `[powershell version]: Error: ${ err } ` ) ;
74+ }
75+ } else {
76+ psVersion = "[not installed; Linux environment]" ;
77+ logger . info ( '[powershell version]:' . padEnd ( logColWidth ) + `${ psVersion } ` ) ;
78+ }
79+
80+ try {
81+ const isLinux = process . platform === 'linux' ;
82+
83+ const psCommandRaw = '$PSVersionTable.PSVersion.ToString()' ;
84+ const psCommand = isLinux
85+ ? psCommandRaw . replace ( / ( [ " \\ $ ` ] ) / g, '\\$1' ) // escape for bash
86+ : psCommandRaw ; // don't escape on Windows
87+ const fullCommand = `pwsh -NoProfile -Command "${ psCommand } "` ;
88+ //const quotedCommand = `"${psCommand.replace(/"/g, '\\"')}"`;
89+ pwshVersion = execSync ( fullCommand , { encoding : 'utf8' } ) . trim ( ) ;
90+ logger . info ( '[pwsh version]:' . padEnd ( logColWidth ) + `${ pwshVersion } ` ) ;
91+ } catch ( err ) {
92+ logger . error ( `[pwsh version]: Encountered an error while executing a 'pwsh version'` ) ;
93+ logger . error ( `[pwsh version]: Error: ${ err } ` ) ;
94+ }
95+
96+ // 5. BCContainerHelper existence / version
97+ let result ;
98+ let BCContainerHelperPresent = false ;
99+
100+ if ( os . platform ( ) === "win32" ) {
101+ try {
102+ const psCommand = `$modulePath = Get-Module -ListAvailable BCContainerHelper | Select-Object -First 1 -ExpandProperty Path; if ($modulePath) { $psd1 = $modulePath -replace '\\[^\\\\]+$', '.psd1'; if (Test-Path $psd1) { $lines = Get-Content $psd1 -Raw; if ($lines -match 'ModuleVersion\\s*=\\s*[\\"\\'']?([0-9\\.]+)[\\"\\'']?') { Write-Output $matches[1]; } else { Write-Output '[version not found]'; } } else { Write-Output '[not installed]'; } } else { Write-Output '[not installed]'; }` ;
103+
104+ result = execSync ( `powershell.exe -NoProfile -Command "${ psCommand . replace ( / \n / g, ' ' ) . replace ( / " / g, '\\"' ) } "` , { encoding : 'utf8' , stdio : [ 'pipe' , 'pipe' , 'pipe' ] } ) . trim ( ) ;
105+ if ( result === "" ) { result = '[not installed]' }
106+ if ( result && result != "" ) {
107+ logger . info ( '[BCContainerHelper version]:' . padEnd ( logColWidth ) + `${ result } ` ) ;
108+ BCContainerHelperPresent = true ;
109+ }
110+ BCContainerHelperPresent = true ;
111+ } catch ( err ) {
112+ logger . error ( `[BCContainerHelper]: Failed to query module: ${ err . message } ` ) ;
113+ logger . info ( err ) ;
114+ }
115+ } else {
116+ result = "[not installed; Linux environment]" ;
117+ logger . info ( '[BCContainerHelper version]:' . padEnd ( logColWidth ) + `${ result } ` ) ;
118+ }
119+
120+ // 6. Docker existence / version
121+ let DockerPresent = false ;
122+ let DockerVersionResult ;
123+ try {
124+ DockerResult = execSync ( 'docker version --format "{{.Client.Version}}"' , { stdio : [ 'pipe' , 'pipe' , 'pipe' ] } ) ;
125+ if ( DockerResult === "" ) { DockerVersionResult = '[not installed]' }
126+ else { DockerVersionResult = DockerResult . toString ( ) . trim ( ) ; }
127+ if ( DockerVersionResult && DockerVersionResult != "" ) {
128+ logger . info ( '[dockerversion]:' . padEnd ( logColWidth ) + `${ DockerVersionResult } ` ) ;
129+ DockerPresent = true ;
130+ }
131+ } catch ( err ) {
132+ const msg = err . message || '' ;
133+ const stderr = err . stderr ?. toString ( ) || '' ;
134+
135+ const combined = `${ msg } \n${ stderr } ` ;
136+ const normalized = combined . toLowerCase ( ) ;
137+ if (
138+ normalized . includes ( "'docker' is not recognized" ) || // Windows case
139+ normalized . includes ( "command not found" ) || // Linux case
140+ normalized . includes ( "no such file or directory" ) // fallback
141+ ) {
142+ DockerVersionResult = '[not installed]' ;
143+ if ( DockerVersionResult && DockerVersionResult != "" ) {
144+ logger . info ( '[dockerversion]:' . padEnd ( logColWidth ) + `${ DockerVersionResult } ` ) ;
145+ }
146+ } else {
147+ logger . error ( `[dockerversion]: Unexpected error: ${ combined } ` ) ;
148+ }
149+ }
150+
151+ // 7. Docker image list
152+ let DockerPsObject ;
153+ if ( DockerPresent ) {
154+ try {
155+ const psResult = execSync ( 'docker ps -a --no-trunc --format "{{json .}}"' , { encoding : 'utf8' , stdio : [ 'pipe' , 'pipe' , 'pipe' ] } ) ;
156+ const lines = psResult . trim ( ) . split ( '\n' ) ;
157+ DockerPsObject = lines . filter ( line => line && line . trim ( ) . startsWith ( '{' ) && line . trim ( ) . endsWith ( '}' ) ) . map ( line => JSON . parse ( line ) ) ;
158+
159+ if ( DockerPsObject . length > 0 ) {
160+ logger . info ( '[dockerimage]:' . padEnd ( logColWidth ) + '**Name**' . padEnd ( logColWidth ) + '**Status**' ) ;
161+ DockerPsObject . forEach ( ( image , idx ) => {
162+ if ( image && image . name != "" ) {
163+ logger . info ( '[dockerimage]:' . padEnd ( logColWidth ) + `${ image . Names } ` . padEnd ( logColWidth ) + `${ image . Status } ` ) ;
164+ }
165+ } ) ;
166+ } else {
167+ logger . info ( '[dockerimage]:' . padEnd ( logColWidth ) + '[no images]' ) ;
168+ }
169+ } catch ( err ) {
170+ const msg = err . message || '' ;
171+ const stderr = err . stderr ?. toString ( ) || '' ;
172+
173+ const combined = `${ msg } \n${ stderr } ` ;
174+ logger . error ( `[dockerimage]: Unexpected error: ${ combined } ` ) ;
175+ }
176+ } else {
177+ logger . info ( '[dockerimage]:' . padEnd ( logColWidth ) + '[not installed]' ) ;
178+ }
179+
180+ // Deal with the file if requested (note it has already been parsed at the top of this routine)
181+ if ( outputFilenameAndPath ) {
182+
183+ let dockerList = [ ] ;
184+ try {
185+ dockerList = DockerPsObject . filter ( img => img && img . Names ) . map ( img => ( { name : img . Names , status : img . Status } ) ) ;
186+ } catch {
187+ dockerList = [ ] ;
188+ }
189+
190+ let candidateFile = {
191+ platform : os . platform ( ) ,
192+ whoami : textOut ,
193+ workingDirectory : process . cwd ( ) ,
194+ powershellVersion : psVersion ,
195+ pscoreVersion : pwshVersion ,
196+ bcContainerVersion : result ,
197+ dockerVersion : DockerVersionResult ,
198+ dockerImages : dockerList
199+ }
200+
201+ let candidateFileString = JSON . stringify ( candidateFile ) ;
202+ fs . writeFileSync ( outputFilenameAndPath , candidateFileString ) ;
203+
204+ logger . info ( '' ) ;
205+ logger . info ( `Produced file at: ${ outputFilenameAndPath } ` ) ;
206+ }
207+ } ) ( ) ;
0 commit comments