6
6
import * as semver from 'semver'
7
7
import * as vscode from 'vscode'
8
8
import * as packageJson from '../../../package.json'
9
- import * as os from 'os'
10
9
import { getLogger } from '../logger/logger'
11
10
import { onceChanged } from '../utilities/functionUtils'
12
11
import { ChildProcess } from '../utilities/processUtils'
13
12
import globals , { isWeb } from '../extensionGlobals'
14
13
import * as devConfig from '../../dev/config'
14
+ import * as os from 'os'
15
15
16
16
/**
17
17
* Returns true if the current build is running on CI (build server).
@@ -124,6 +124,35 @@ export function isRemoteWorkspace(): boolean {
124
124
return vscode . env . remoteName === 'ssh-remote'
125
125
}
126
126
127
+ /**
128
+ * Parses an os-release file according to the freedesktop.org standard.
129
+ *
130
+ * @param content The content of the os-release file
131
+ * @returns A record of key-value pairs from the os-release file
132
+ *
133
+ * @see https://www.freedesktop.org/software/systemd/man/latest/os-release.html
134
+ */
135
+ function parseOsRelease ( content : string ) : Record < string , string > {
136
+ const result : Record < string , string > = { }
137
+
138
+ for ( let line of content . split ( '\n' ) ) {
139
+ line = line . trim ( )
140
+ // Skip empty lines and comments
141
+ if ( ! line || line . startsWith ( '#' ) ) {
142
+ continue
143
+ }
144
+
145
+ const eqIndex = line . indexOf ( '=' )
146
+ if ( eqIndex > 0 ) {
147
+ const key = line . slice ( 0 , eqIndex )
148
+ const value = line . slice ( eqIndex + 1 ) . replace ( / ^ [ " ' ] | [ " ' ] $ / g, '' )
149
+ result [ key ] = value
150
+ }
151
+ }
152
+
153
+ return result
154
+ }
155
+
127
156
/**
128
157
* Checks if the current environment has SageMaker-specific environment variables
129
158
* @returns true if SageMaker environment variables are detected
@@ -146,36 +175,83 @@ export function hasSageMakerEnvVars(): boolean {
146
175
/**
147
176
* Checks if the current environment is running on Amazon Linux 2.
148
177
*
149
- * This function attempts to detect if we're running in a container on an AL2 host
150
- * by checking both the OS release and container-specific indicators.
178
+ * This function detects the container/runtime OS, not the host OS.
179
+ * In containerized environments, we check the container's OS identity.
180
+ *
181
+ * Detection Process (in order):
182
+ * 1. Returns false for web environments (browser-based)
183
+ * 2. Returns false for SageMaker environments (even if container is AL2)
184
+ * 3. Checks `/etc/os-release` with fallback to `/usr/lib/os-release`
185
+ * - Standard Linux OS identification files per freedesktop.org spec
186
+ * - Looks for `ID="amzn"` and `VERSION_ID="2"` for AL2
187
+ * - This correctly identifies AL2 containers regardless of host OS
188
+ *
189
+ * This approach ensures correct detection in:
190
+ * - Containerized environments (detects container OS, not host)
191
+ * - AL2 containers on any host OS (Ubuntu, AL2023, etc.)
192
+ * - Web/browser environments (returns false)
193
+ * - SageMaker environments (returns false)
151
194
*
152
- * Example: `5.10.220-188.869.amzn2int.x86_64` or `5.10.236-227.928.amzn2.x86_64` (Cloud Dev Machine)
195
+ * Note: We intentionally do NOT check kernel version as it reflects the host OS,
196
+ * not the container OS. AL2 containers should be treated as AL2 environments
197
+ * regardless of whether they run on AL2, Ubuntu, or other host kernels.
198
+ *
199
+ * References:
200
+ * - https://docs.aws.amazon.com/linux/al2/ug/ident-amazon-linux-specific.html
201
+ * - https://docs.aws.amazon.com/linux/al2/ug/ident-os-release.html
202
+ * - https://www.freedesktop.org/software/systemd/man/latest/os-release.html
153
203
*/
154
204
export function isAmazonLinux2 ( ) {
205
+ // Skip AL2 detection for web environments
206
+ // In web mode, we're running in a browser, not on AL2
207
+ if ( isWeb ( ) ) {
208
+ return false
209
+ }
210
+
155
211
// First check if we're in a SageMaker environment, which should not be treated as AL2
156
- // even if the underlying host is AL2
212
+ // even if the underlying container is AL2
157
213
if ( hasSageMakerEnvVars ( ) ) {
158
214
return false
159
215
}
160
216
161
- // Check if we're in a container environment that's not AL2
162
- if ( process . env . container === 'docker' || process . env . DOCKER_HOST || process . env . DOCKER_BUILDKIT ) {
163
- // Additional check for container OS - if we can determine it's not AL2
164
- try {
165
- const fs = require ( 'fs' )
166
- if ( fs . existsSync ( '/etc/os-release' ) ) {
167
- const osRelease = fs . readFileSync ( '/etc/os-release' , 'utf8' )
168
- if ( ! osRelease . includes ( 'Amazon Linux 2' ) && ! osRelease . includes ( 'amzn2' ) ) {
169
- return false
217
+ // Only proceed with file checks on Linux platforms
218
+ if ( process . platform !== 'linux' ) {
219
+ return false
220
+ }
221
+
222
+ // Check the container/runtime OS identity via os-release files
223
+ // This correctly identifies AL2 containers regardless of host OS
224
+ try {
225
+ const fs = require ( 'fs' )
226
+ // Check /etc/os-release with fallback to /usr/lib/os-release as per freedesktop.org spec
227
+ const osReleasePaths = [ '/etc/os-release' , '/usr/lib/os-release' ]
228
+
229
+ for ( const osReleasePath of osReleasePaths ) {
230
+ if ( fs . existsSync ( osReleasePath ) ) {
231
+ try {
232
+ const osReleaseContent = fs . readFileSync ( osReleasePath , 'utf8' )
233
+ const osRelease = parseOsRelease ( osReleaseContent )
234
+
235
+ // Check if this is Amazon Linux 2
236
+ // We trust os-release as the authoritative source for container OS identity
237
+ return osRelease . VERSION_ID === '2' && osRelease . ID === 'amzn'
238
+ } catch ( e ) {
239
+ // Continue to next path if parsing fails
240
+ getLogger ( ) . error ( `Parsing os-release file ${ osReleasePath } failed: ${ e } ` )
170
241
}
171
242
}
172
- } catch ( e ) {
173
- // If we can't read the file, fall back to the os.release() check
174
243
}
244
+ } catch ( e ) {
245
+ // If we can't read the files, we cannot determine AL2 status
246
+ getLogger ( ) . error ( `Checking os-release files failed: ${ e } ` )
175
247
}
176
248
177
- // Standard check for AL2 in the OS release string
178
- return ( os . release ( ) . includes ( '.amzn2int.' ) || os . release ( ) . includes ( '.amzn2.' ) ) && process . platform === 'linux'
249
+ // Fall back to kernel version check if os-release files are unavailable or failed
250
+ // This is needed for environments where os-release might not be accessible
251
+ const kernelRelease = os . release ( )
252
+ const hasAL2Kernel = kernelRelease . includes ( '.amzn2int.' ) || kernelRelease . includes ( '.amzn2.' )
253
+
254
+ return hasAL2Kernel
179
255
}
180
256
181
257
/**
@@ -217,9 +293,9 @@ export function getExtRuntimeContext(): {
217
293
extensionHost : ExtensionHostLocation
218
294
} {
219
295
const extensionHost =
220
- // taken from https://github.com/microsoft/vscode/blob/7c9e4bb23992c63f20cd86bbe7a52a3aa4bed89d/extensions/github-authentication/src/githubServer.ts#L121 to help determine which auth flows
221
- // should be used
222
- typeof navigator === 'undefined'
296
+ // Check if we're in a Node.js environment (desktop/remote) vs web worker
297
+ // Updated to be compatible with Node.js v22 which includes navigator global
298
+ typeof process === 'object' && process . versions ?. node
223
299
? globals . context . extension . extensionKind === vscode . ExtensionKind . UI
224
300
? 'local'
225
301
: 'remote'
0 commit comments