forked from aws/aws-toolkit-vscode
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsamLambdaRuntime.ts
More file actions
327 lines (296 loc) · 11 KB
/
samLambdaRuntime.ts
File metadata and controls
327 lines (296 loc) · 11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
/*!
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
* SPDX-License-Identifier: Apache-2.0
*/
import * as nls from 'vscode-nls'
const localize = nls.loadMessageBundle()
import * as vscode from 'vscode'
import { Runtime } from '@aws-sdk/client-lambda'
import { Map as ImmutableMap, Set as ImmutableSet } from 'immutable'
import { isCloud9 } from '../../shared/extensionUtilities'
import { PrompterButtons } from '../../shared/ui/buttons'
import { createQuickPick, DataQuickPickItem, QuickPickPrompter } from '../../shared/ui/pickerPrompter'
import { supportedLambdaRuntimesUrl } from '../../shared/constants'
import { openUrl } from '../../shared/utilities/vsCodeUtils'
export enum RuntimeFamily {
Unknown,
Python,
NodeJS,
DotNet,
Go,
Java,
Ruby,
}
export type RuntimePackageType = 'Image' | 'Zip'
// TODO: Consolidate all of the runtime constructs into a single <Runtime, Set<Runtime>> map
// We should be able to eliminate a fair amount of redundancy with that.
export const nodeJsRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>([
'nodejs24.x' as Runtime,
'nodejs22.x' as Runtime,
'nodejs20.x',
'nodejs18.x',
'nodejs16.x',
'nodejs14.x',
])
export function getNodeMajorVersion(version?: string): number | undefined {
if (!version) {
return undefined
}
const match = version.match(/^nodejs(\d+)\./)
if (match) {
return Number(match[1])
} else {
return undefined
}
}
export const pythonRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>([
'python3.14' as Runtime,
'python3.13' as Runtime,
'python3.12',
'python3.11',
'python3.10',
'python3.9',
'python3.8',
'python3.7',
])
export const goRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>(['go1.x'])
export const javaRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>([
'java17',
'java11',
'java8',
'java8.al2',
'java21',
'java25' as Runtime,
])
export const dotNetRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>(['dotnet6', 'dotnet8'])
export const rubyRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>(['ruby3.2', 'ruby3.3', 'ruby3.4' as Runtime])
// Image runtimes are not a direct subset of valid ZIP lambda types
const dotnet50 = 'dotnet5.0' as Runtime
/**
* Deprecated runtimes can be found at https://docs.aws.amazon.com/lambda/latest/dg/runtime-support-policy.html
* (or whatever shared/constants.supportedLambdaRuntimesUrl is pointing to)
* Add runtimes as they enter Phase 2 deprecation (updating existing functions blocked)
* Don't add unsupported languages for now (e.g. ruby25): no point in telling a user they're deprecated and then telling them we have no support after they update.
*/
export const deprecatedRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>([
'dotnetcore1.0',
'dotnetcore2.0',
'python2.7',
'nodejs',
'nodejs4.3',
'nodejs4.3-edge',
'nodejs6.10',
'nodejs8.10',
'nodejs10.x',
'nodejs12.x',
'ruby2.5',
'ruby2.7',
])
const defaultRuntimes = ImmutableMap<RuntimeFamily, Runtime>([
[RuntimeFamily.NodeJS, 'nodejs24.x' as Runtime],
[RuntimeFamily.Python, 'python3.14' as Runtime],
[RuntimeFamily.DotNet, 'dotnet8'],
[RuntimeFamily.Go, 'go1.x'],
[RuntimeFamily.Java, 'java25' as Runtime],
[RuntimeFamily.Ruby, 'ruby3.4' as Runtime],
])
export const mapFamilyToDebugType = ImmutableMap<RuntimeFamily, string>([
[RuntimeFamily.NodeJS, 'node'],
[RuntimeFamily.Python, 'python'],
[RuntimeFamily.DotNet, 'csharp'],
[RuntimeFamily.Go, 'go'],
[RuntimeFamily.Java, 'java'],
[RuntimeFamily.Ruby, 'ruby'],
[RuntimeFamily.Unknown, 'unknown'],
])
export const samZipLambdaRuntimes: ImmutableSet<Runtime> = ImmutableSet.union([
nodeJsRuntimes,
pythonRuntimes,
dotNetRuntimes,
goRuntimes,
javaRuntimes,
])
export const samArmLambdaRuntimes: ImmutableSet<Runtime> = ImmutableSet<Runtime>([
'python3.9',
'python3.8',
'nodejs22.x' as Runtime,
'nodejs20.x',
'nodejs18.x',
'nodejs16.x',
'nodejs14.x',
'java17',
'java11',
'java8.al2',
])
// Cloud9 supports a subset of runtimes for debugging.
// * .NET is not supported
const cloud9SupportedRuntimes: ImmutableSet<Runtime> = ImmutableSet.union([nodeJsRuntimes, pythonRuntimes])
// only interpreted languages are importable as compiled languages won't provide a useful artifact for editing.
export const samLambdaImportableRuntimes: ImmutableSet<Runtime> = ImmutableSet.union([
nodeJsRuntimes,
pythonRuntimes,
rubyRuntimes,
])
export function samLambdaCreatableRuntimes(cloud9: boolean = isCloud9()): ImmutableSet<Runtime> {
return cloud9 ? cloud9SupportedRuntimes : samZipLambdaRuntimes
}
export function samImageLambdaRuntimes(cloud9: boolean = isCloud9()): ImmutableSet<Runtime> {
// Note: SAM also supports ruby, but Toolkit does not.
return ImmutableSet<Runtime>([...samLambdaCreatableRuntimes(cloud9), ...(cloud9 ? [] : [dotnet50])])
}
export type DependencyManager = 'cli-package' | 'mod' | 'gradle' | 'pip' | 'npm' | 'maven' | 'bundler'
export type Architecture = 'x86_64' | 'arm64'
export function getDependencyManager(runtime: Runtime): DependencyManager[] {
if (deprecatedRuntimes.has(runtime)) {
handleDeprecatedRuntime(runtime)
} else if (nodeJsRuntimes.has(runtime)) {
return ['npm']
} else if (pythonRuntimes.has(runtime)) {
return ['pip']
} else if (dotNetRuntimes.has(runtime) || runtime === dotnet50) {
return ['cli-package']
} else if (goRuntimes.has(runtime)) {
return ['mod']
} else if (javaRuntimes.has(runtime)) {
return ['gradle', 'maven']
}
throw new Error(`Runtime ${runtime} does not have an associated DependencyManager`)
}
export function getFamily(runtime: Runtime): RuntimeFamily {
if (deprecatedRuntimes.has(runtime)) {
handleDeprecatedRuntime(runtime)
} else if (nodeJsRuntimes.has(runtime)) {
return RuntimeFamily.NodeJS
} else if (pythonRuntimes.has(runtime)) {
return RuntimeFamily.Python
} else if (dotNetRuntimes.has(runtime) || runtime === dotnet50) {
return RuntimeFamily.DotNet
} else if (goRuntimes.has(runtime)) {
return RuntimeFamily.Go
} else if (javaRuntimes.has(runtime)) {
return RuntimeFamily.Java
} else if (rubyRuntimes.has(runtime)) {
return RuntimeFamily.Ruby
}
return RuntimeFamily.Unknown
}
function handleDeprecatedRuntime(runtime: Runtime) {
const moreInfo = localize('AWS.generic.message.learnMore', 'Learn More')
void vscode.window
.showErrorMessage(
localize(
'AWS.samcli.deprecatedRuntime',
'Runtime {0} has been deprecated. Update to a currently-supported runtime.',
runtime
),
moreInfo
)
.then((button) => {
if (button === moreInfo) {
void openUrl(vscode.Uri.parse(supportedLambdaRuntimesUrl))
}
})
throw new Error(`Runtime ${runtime} is deprecated, see: ${supportedLambdaRuntimesUrl}`)
}
/**
* Sorts runtimes from lowest value to greatest value, helpful for outputting alphabetized lists of runtimes
* Differs from normal sorting as it numbers into account: e.g. nodeJs8.10 < nodeJs10.x
*/
export function compareSamLambdaRuntime(a: string, b: string): number {
return a.localeCompare(b, 'en', { numeric: true, ignorePunctuation: true })
}
function extractAndCompareRuntime(a: vscode.QuickPickItem, b: vscode.QuickPickItem): number {
return compareSamLambdaRuntime(a.label, b.label)
}
/**
* Maps vscode document languageId to `RuntimeFamily`.
*/
export function getRuntimeFamily(langId: string): RuntimeFamily {
switch (langId) {
case 'typescript':
case 'javascript':
return RuntimeFamily.NodeJS
case 'csharp':
return RuntimeFamily.DotNet
case 'python':
return RuntimeFamily.Python
case 'go':
return RuntimeFamily.Go
case 'java':
return RuntimeFamily.Java
case 'ruby':
return RuntimeFamily.Ruby
default:
return RuntimeFamily.Unknown
}
}
/**
* Provides the default runtime for a given `RuntimeFamily` or undefined if the runtime is invalid.
*/
export function getDefaultRuntime(runtime: RuntimeFamily): Runtime | undefined {
return defaultRuntimes.get(runtime)
}
/**
* Returns a set of runtimes for a specified runtime family or undefined if not found.
* @param family Runtime family to get runtimes for
*/
function getRuntimesForFamily(family: RuntimeFamily): ImmutableSet<Runtime> | undefined {
switch (family) {
case RuntimeFamily.NodeJS:
return nodeJsRuntimes
case RuntimeFamily.Python:
return pythonRuntimes
case RuntimeFamily.DotNet:
return dotNetRuntimes
case RuntimeFamily.Go:
return goRuntimes
case RuntimeFamily.Java:
return javaRuntimes
default:
return undefined
}
}
export interface RuntimeAndPackage {
packageType: RuntimePackageType
runtime: Runtime
}
/**
* Creates a quick pick for a Runtime with the following parameters (all optional)
* @param {Object} params Optional parameters for creating a QuickPick for runtimes:
* @param {vscode.QuickInputButton[]} params.buttons Array of buttons to add to the quick pick;
* @param {RuntimeFamily} params.runtimeFamily RuntimeFamily that will define the list of runtimes to show (default: samLambdaCreatableRuntimes)
*/
export function createRuntimeQuickPick(params: {
showImageRuntimes: boolean
buttons?: PrompterButtons<RuntimeAndPackage>
runtimeFamily?: RuntimeFamily
step?: number
totalSteps?: number
}): QuickPickPrompter<RuntimeAndPackage> {
const zipRuntimes = params.runtimeFamily
? (getRuntimesForFamily(params.runtimeFamily) ?? samLambdaCreatableRuntimes())
: samLambdaCreatableRuntimes()
const zipRuntimeItems = zipRuntimes
// remove uncreatable runtimes
.filter((value) => samLambdaCreatableRuntimes().has(value))
.toArray()
.map((runtime) => ({
data: { runtime, packageType: 'Zip' } as RuntimeAndPackage,
label: runtime,
}))
// internally, after init there is essentially no difference between a ZIP and Image runtime;
// behavior is keyed off of what is specified in the cloudformation template
let imageRuntimeItems: DataQuickPickItem<RuntimeAndPackage>[] = []
if (params.showImageRuntimes) {
imageRuntimeItems = samImageLambdaRuntimes()
.map((runtime) => ({
data: { runtime, packageType: 'Image' } as RuntimeAndPackage,
label: `${runtime} (Image)`,
}))
.toArray()
}
return createQuickPick([...zipRuntimeItems, ...imageRuntimeItems].sort(extractAndCompareRuntime), {
title: localize('AWS.samcli.initWizard.runtime.prompt', 'Select a SAM Application Runtime'),
buttons: params.buttons ?? [],
})
}