Skip to content

Code-type codelenses now prompt for a runtime #1112

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 27, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 66 additions & 0 deletions src/lambda/models/samLambdaRuntime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,13 @@
* 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/clients/lambda'
import { Map, Set } from 'immutable'
import * as picker from '../../shared/ui/picker'

export enum RuntimeFamily {
Unknown,
Expand All @@ -13,6 +18,8 @@ export enum RuntimeFamily {
DotNetCore,
}

// 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: Set<Runtime> = Set<Runtime>(['nodejs12.x', 'nodejs10.x', 'nodejs8.10'])
export const pythonRuntimes: Set<Runtime> = Set<Runtime>(['python3.8', 'python3.7', 'python3.6', 'python2.7'])
export const dotNetRuntimes: Set<Runtime> = Set<Runtime>(['dotnetcore2.1'])
Expand All @@ -24,6 +31,9 @@ const DEFAULT_RUNTIMES = Map<RuntimeFamily, Runtime>([

export const samLambdaRuntimes: Set<Runtime> = Set.union([nodeJsRuntimes, pythonRuntimes, dotNetRuntimes])

// Filter out node8 until local debugging is no longer supported, and it can be removed from samLambdaRuntimes
export const samLambdaCreatableRuntimes: Set<Runtime> = samLambdaRuntimes.filter(runtime => runtime !== 'nodejs8.10')

export type DependencyManager = 'cli-package' | 'mod' | 'gradle' | 'pip' | 'npm' | 'maven' | 'bundler'

// TODO: Make this return an array of DependencyManagers when we add runtimes with multiple dependency managers
Expand Down Expand Up @@ -88,3 +98,59 @@ export function getRuntimeFamily(langId: string): RuntimeFamily {
export function getDefaultRuntime(runtime: RuntimeFamily): string | undefined {
return DEFAULT_RUNTIMES.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): Set<Runtime> | undefined {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: probably makes sense to refactor the various runtime lists into a map later. Off-topic for this PR.

pseudocode:

export runtimes = { 
  RuntimeFamily.Node: Set<Runtime>(['nodejs12.x', 'nodejs10.x', 'nodejs8.10']),
  RuntimeFamily.Python: Set<Runtime>(['python3.8', 'python3.7', 'python3.6', 'python2.7']),
  ...,
}

This would eliminate nodeJsRuntimes, pythonRuntimes, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will drop a TODO for this. I'm getting sick and tired of the various wrappers we have around suggested runtimes but I'm afraid that it'll make this PR balloon pretty badly.

switch (family) {
case RuntimeFamily.NodeJS:
return nodeJsRuntimes
case RuntimeFamily.Python:
return pythonRuntimes
case RuntimeFamily.DotNetCore:
return dotNetRuntimes
default:
return undefined
}
}

/**
* 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 {Runtime} params.currRuntime Runtime to set a "Selected Previously" mark to;
* @param {RuntimeFamily} params.runtimeFamily RuntimeFamily that will define the list of runtimes to show (default: samLambdaCreatableRuntimes)
*/
export function createRuntimeQuickPick(params: {
buttons?: vscode.QuickInputButton[]
currRuntime?: Runtime
runtimeFamily?: RuntimeFamily
}): vscode.QuickPick<vscode.QuickPickItem> {
const runtimes = params.runtimeFamily
? getRuntimesForFamily(params.runtimeFamily) ?? samLambdaCreatableRuntimes
: samLambdaCreatableRuntimes

return picker.createQuickPick<vscode.QuickPickItem>({
options: {
ignoreFocusOut: true,
title: localize('AWS.samcli.initWizard.runtime.prompt', 'Select a SAM Application Runtime'),
value: params.currRuntime ? params.currRuntime : '',
},
buttons: [...(params.buttons ?? []), vscode.QuickInputButtons.Back],
items: runtimes
// remove uncreatable runtimes
.filter(value => samLambdaCreatableRuntimes.has(value))
.toArray()
.sort(compareSamLambdaRuntime)
.map(runtime => ({
label: runtime,
alwaysShow: runtime === params.currRuntime,
description:
runtime === params.currRuntime
? localize('AWS.wizard.selectedPreviously', 'Selected Previously')
: '',
})),
})
}
24 changes: 5 additions & 19 deletions src/lambda/wizards/samInitWizard.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {
WizardStep,
WorkspaceFolderQuickPickItem,
} from '../../shared/wizards/multiStepWizard'
import { compareSamLambdaRuntime, samLambdaRuntimes } from '../models/samLambdaRuntime'
import { createRuntimeQuickPick, samLambdaCreatableRuntimes } from '../models/samLambdaRuntime'
import {
eventBridgeStarterAppTemplate,
getSamTemplateWizardOption,
Expand All @@ -54,8 +54,7 @@ export interface CreateNewSamAppWizardContext {
}

export class DefaultCreateNewSamAppWizardContext extends WizardContext implements CreateNewSamAppWizardContext {
// Filter out node8 until local debugging is no longer supported, and it can be removed from samLambdaRuntimes
public readonly lambdaRuntimes = samLambdaRuntimes.filter(runtime => runtime !== 'nodejs8.10')
public readonly lambdaRuntimes = samLambdaCreatableRuntimes
private readonly helpButton = createHelpButton(localize('AWS.command.help', 'View Documentation'))
private readonly currentCredentials: Credentials | undefined
private readonly schemasRegions: Region[]
Expand All @@ -67,22 +66,9 @@ export class DefaultCreateNewSamAppWizardContext extends WizardContext implement
}

public async promptUserForRuntime(currRuntime?: Runtime): Promise<Runtime | undefined> {
const quickPick = picker.createQuickPick<vscode.QuickPickItem>({
options: {
ignoreFocusOut: true,
title: localize('AWS.samcli.initWizard.runtime.prompt', 'Select a SAM Application Runtime'),
value: currRuntime ? currRuntime : '',
},
buttons: [this.helpButton, vscode.QuickInputButtons.Back],
items: this.lambdaRuntimes
.toArray()
.sort(compareSamLambdaRuntime)
.map(runtime => ({
label: runtime,
alwaysShow: runtime === currRuntime,
description:
runtime === currRuntime ? localize('AWS.wizard.selectedPreviously', 'Selected Previously') : '',
})),
const quickPick = createRuntimeQuickPick({
buttons: [this.helpButton],
currRuntime,
})

const choices = await picker.promptUser({
Expand Down
8 changes: 2 additions & 6 deletions src/shared/sam/debugger/awsSamDebugConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import * as vscode from 'vscode'
import * as path from 'path'
import { getDefaultRuntime, RuntimeFamily } from '../../../lambda/models/samLambdaRuntime'
import { Runtime } from 'aws-sdk/clients/lambda'
import { getNormalizedRelativePath } from '../../utilities/pathUtils'
import {
AwsSamDebuggerConfiguration,
Expand Down Expand Up @@ -155,14 +155,10 @@ export function createCodeAwsSamDebugConfig(
folder: vscode.WorkspaceFolder | undefined,
lambdaHandler: string,
projectRoot: string,
runtimeFamily?: RuntimeFamily
runtime: Runtime
): AwsSamDebuggerConfiguration {
const workspaceRelativePath = folder ? getNormalizedRelativePath(folder.uri.fsPath, projectRoot) : projectRoot
const parentDir = path.basename(path.dirname(projectRoot))
const runtime = runtimeFamily ? getDefaultRuntime(runtimeFamily) : undefined
if (!runtime) {
throw new Error('Invalid or missing runtime family')
}

return {
type: AWS_SAM_DEBUG_TYPE,
Expand Down
31 changes: 23 additions & 8 deletions src/shared/sam/debugger/commands/addSamDebugConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@

import * as path from 'path'
import * as vscode from 'vscode'
import { Runtime } from 'aws-sdk/clients/lambda'
import { getExistingConfiguration } from '../../../../lambda/config/templates'
import { getDefaultRuntime, RuntimeFamily } from '../../../../lambda/models/samLambdaRuntime'
import { createRuntimeQuickPick, getDefaultRuntime, RuntimeFamily } from '../../../../lambda/models/samLambdaRuntime'
import { CloudFormationTemplateRegistry } from '../../../cloudformation/templateRegistry'
import { LaunchConfiguration } from '../../../debug/launchConfiguration'
import * as picker from '../../../ui/picker'
import { localize } from '../../../utilities/vsCodeUtils'
import {
AwsSamDebuggerConfiguration,
Expand Down Expand Up @@ -93,13 +95,26 @@ export async function addSamDebugConfiguration(
preloadedConfig
)
} else if (type === CODE_TARGET_TYPE) {
// strip the manifest's URI to the manifest's dir here. More reliable to do this here than converting back and forth between URI/string up the chain.
samDebugConfig = createCodeAwsSamDebugConfig(
workspaceFolder,
resourceName,
path.dirname(rootUri.fsPath),
runtimeFamily
)
const quickPick = createRuntimeQuickPick({
runtimeFamily,
})

const choices = await picker.promptUser({
picker: quickPick,
})
const val = picker.verifySinglePickerOutput(choices)
if (val) {
// strip the manifest's URI to the manifest's dir here. More reliable to do this here than converting back and forth between URI/string up the chain.
samDebugConfig = createCodeAwsSamDebugConfig(
workspaceFolder,
resourceName,
path.dirname(rootUri.fsPath),
val.label as Runtime
)
} else {
// User backed out of runtime selection. Abandon config creation.
return
}
} else {
throw new Error('Unrecognized debug target type')
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -967,7 +967,7 @@ it('ensureRelativePaths', () => {
undefined,
'testName1',
'/test1/project',
lambdaModel.RuntimeFamily.NodeJS
lambdaModel.getDefaultRuntime(lambdaModel.RuntimeFamily.NodeJS) ?? ''
)
assert.strictEqual((codeConfig.invokeTarget as CodeTargetProperties).projectRoot, '/test1/project')
ensureRelativePaths(workspace, codeConfig)
Expand Down