Skip to content

Commit 99a555a

Browse files
nkomonen-amazonVandita2020Vandita Patidarvicheey
authored
feat(lambda): Add Serverless Land feature (aws#6728)
### This is a merge of `feature/serverlessland` in to `master`, but I rebased to keep it clean New feature from the Lambda team: The AWS Toolkit for VS Code now integrates Serverless Land's application pattern library, allowing developers to browse, search, and implement pre-built serverless patterns directly in the IDE. This simplifies and accelerates the process of building serverless applications using VS Code. --- - Treat all work as PUBLIC. Private `feature/x` branches will not be squash-merged at release time. - Your code changes must meet the guidelines in [CONTRIBUTING.md](https://github.com/aws/aws-toolkit-vscode/blob/master/CONTRIBUTING.md#guidelines). - License: I confirm that my contribution is made under the terms of the Apache 2.0 license. --------- Signed-off-by: nkomonen-amazon <[email protected]> Co-authored-by: Vandita Patidar <[email protected]> Co-authored-by: Vandita Patidar <[email protected]> Co-authored-by: vicheey <[email protected]>
1 parent a05780a commit 99a555a

File tree

16 files changed

+1233
-14
lines changed

16 files changed

+1233
-14
lines changed

packages/core/package.nls.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,5 +461,6 @@
461461
"AWS.toolkit.lambda.walkthrough.step1.title": "Iterate locally",
462462
"AWS.toolkit.lambda.walkthrough.step1.description": "Locally test and debug your code.",
463463
"AWS.toolkit.lambda.walkthrough.step2.title": "Deploy to the cloud",
464-
"AWS.toolkit.lambda.walkthrough.step2.description": "Test your application in the cloud from within VS Code. \n\nNote: The AWS CLI and the SAM CLI require AWS Credentials to interact with the cloud. For information on setting up your credentials, see [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). \n\n[Configure credentials](command:aws.toolkit.lambda.walkthrough.credential)"
464+
"AWS.toolkit.lambda.walkthrough.step2.description": "Test your application in the cloud from within VS Code. \n\nNote: The AWS CLI and the SAM CLI require AWS Credentials to interact with the cloud. For information on setting up your credentials, see [Authentication and access credentials](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html). \n\n[Configure credentials](command:aws.toolkit.lambda.walkthrough.credential)",
465+
"AWS.toolkit.lambda.serverlessLand.quickpickTitle": "Create application with Serverless template"
465466
}

packages/core/resources/walkthrough/appBuilder/AppPicker.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,6 @@
2020
</checkbox>
2121
</div>
2222
</checklist>
23-
<checkbox class="theme-picker-link" when-checked="command:aws.lambda.createNewSamApp" checked-on="false">
23+
<checkbox class="theme-picker-link" when-checked="command:aws.toolkit.lambda.createServerlessLandProject" checked-on="false">
2424
See more application example...
2525
</checkbox>

packages/core/src/awsService/appBuilder/activation.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import { ResourceNode } from './explorer/nodes/resourceNode'
2323
import { getSyncWizard, runSync } from '../../shared/sam/sync'
2424
import { getDeployWizard, runDeploy } from '../../shared/sam/deploy'
2525
import { DeployTypeWizard } from './wizards/deployTypeWizard'
26-
26+
import { createNewServerlessLandProject } from './serverlessLand/main'
2727
export const templateToOpenAppComposer = 'aws.toolkit.appComposer.templateToOpenOnStart'
2828

2929
/**
@@ -200,6 +200,11 @@ async function registerAppBuilderCommands(context: ExtContext): Promise<void> {
200200
await runSync('infra', arg, undefined, choices.syncParam)
201201
}
202202
}
203+
}),
204+
Commands.register({ id: 'aws.toolkit.lambda.createServerlessLandProject', autoconnect: false }, async () => {
205+
await telemetry.lambda_createServerlessLandProject.run(async () => {
206+
await createNewServerlessLandProject(context)
207+
})
203208
})
204209
)
205210
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
/*!
2+
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
* SPDX-License-Identifier: Apache-2.0
4+
*/
5+
6+
import * as nls from 'vscode-nls'
7+
const localize = nls.loadMessageBundle()
8+
import * as path from 'path'
9+
import * as vscode from 'vscode'
10+
import { getLogger } from '../../../shared/logger/logger'
11+
import { checklogs } from '../../../shared/localizedText'
12+
import { telemetry } from '../../../shared/telemetry/telemetry'
13+
import { CreateServerlessLandWizardForm, CreateServerlessLandWizard } from './wizard'
14+
import { ExtContext } from '../../../shared/extensions'
15+
import { addFolderToWorkspace } from '../../../shared/utilities/workspaceUtils'
16+
import { ToolkitError } from '../../../shared/errors'
17+
import { fs } from '../../../shared/fs/fs'
18+
import { getPattern } from '../../../shared/utilities/downloadPatterns'
19+
import { MetadataManager } from './metadataManager'
20+
21+
export const readmeFile: string = 'README.md'
22+
const serverlessLandOwner = 'aws-samples'
23+
const serverlessLandRepo = 'serverless-patterns'
24+
25+
/**
26+
* Creates a new Serverless Land project using the provided extension context
27+
* @param extContext Extension context containing AWS credentials and region information
28+
* @returns Promise that resolves when the project creation is complete
29+
*
30+
* This function:
31+
* 1. Validates AWS credentials and regions
32+
* 2. Launches the Serverless Land project creation wizard
33+
* 3. Creates the project structure
34+
* 4. Adds the project folder to the workspace
35+
* 5. Opens the README.md file if available
36+
* 6. Handles errors and emits telemetry
37+
*/
38+
export async function createNewServerlessLandProject(extContext: ExtContext): Promise<void> {
39+
let metadataManager: MetadataManager
40+
41+
try {
42+
metadataManager = MetadataManager.getInstance()
43+
// Launch the project creation wizard
44+
const config = await launchProjectCreationWizard(extContext)
45+
if (!config) {
46+
return
47+
}
48+
const assetName = metadataManager.getAssetName(config.pattern, config.runtime, config.iac)
49+
50+
await downloadPatternCode(config, assetName)
51+
await openReadmeFile(config)
52+
await addFolderToWorkspace(
53+
{
54+
uri: vscode.Uri.joinPath(config.location, config.name),
55+
name: path.basename(config.name),
56+
},
57+
true
58+
)
59+
telemetry.record({
60+
templateName: assetName,
61+
runtimeString: config.runtime,
62+
iac: config.iac,
63+
})
64+
} catch (err) {
65+
getLogger().error(
66+
localize(
67+
'AWS.serverlessland.initWizard.general.error',
68+
'Error creating new Serverless Land Application. {0}',
69+
checklogs()
70+
)
71+
)
72+
getLogger().error('Error creating new Serverless Land Application: %O', err as Error)
73+
}
74+
}
75+
76+
export async function launchProjectCreationWizard(
77+
extContext: ExtContext
78+
): Promise<CreateServerlessLandWizardForm | undefined> {
79+
const awsContext = extContext.awsContext
80+
const credentials = await awsContext.getCredentials()
81+
const defaultRegion = awsContext.getCredentialDefaultRegion()
82+
83+
return new CreateServerlessLandWizard({
84+
credentials,
85+
defaultRegion,
86+
}).run()
87+
}
88+
89+
export async function downloadPatternCode(config: CreateServerlessLandWizardForm, assetName: string): Promise<void> {
90+
const fullAssetName = assetName + '.zip'
91+
const location = vscode.Uri.joinPath(config.location, config.name)
92+
try {
93+
await getPattern(serverlessLandOwner, serverlessLandRepo, fullAssetName, location, true)
94+
} catch (error) {
95+
if (error instanceof ToolkitError) {
96+
throw error
97+
}
98+
throw new ToolkitError(`Failed to download pattern: ${error}`)
99+
}
100+
}
101+
102+
export async function openReadmeFile(config: CreateServerlessLandWizardForm): Promise<void> {
103+
try {
104+
const readmeUri = await getProjectUri(config, readmeFile)
105+
if (!readmeUri) {
106+
getLogger().warn('README.md file not found in the project directory')
107+
return
108+
}
109+
await vscode.commands.executeCommand('workbench.action.focusFirstEditorGroup')
110+
await vscode.commands.executeCommand('markdown.showPreview', readmeUri)
111+
} catch (err) {
112+
getLogger().error(`Error in openReadmeFile: ${err}`)
113+
throw new ToolkitError('Error processing README file')
114+
}
115+
}
116+
117+
export async function getProjectUri(
118+
config: Pick<CreateServerlessLandWizardForm, 'location' | 'name'>,
119+
file: string
120+
): Promise<vscode.Uri | undefined> {
121+
if (!file) {
122+
throw new ToolkitError('expected "file" parameter to have at least one item')
123+
}
124+
const cfnTemplatePath = path.resolve(config.location.fsPath, config.name, file)
125+
if (await fs.exists(cfnTemplatePath)) {
126+
return vscode.Uri.file(cfnTemplatePath)
127+
}
128+
void vscode.window.showWarningMessage(
129+
localize(
130+
'AWS.serverlessLand.initWizard.source.error.notFound',
131+
'Project created successfully, but {0} file not found: {1}',
132+
file!,
133+
cfnTemplatePath!
134+
)
135+
)
136+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{
2+
"patterns": {
3+
"Image Resizing": {
4+
"name": "Resizing image",
5+
"description": "Lambda, S3 • Python, Javascript, Java, .NET • SAM",
6+
"implementation": [
7+
{
8+
"iac": "sam",
9+
"runtime": "python",
10+
"assetName": "s3-lambda-resizing-python"
11+
},
12+
{
13+
"iac": "sam",
14+
"runtime": "javascript",
15+
"assetName": "s3-lambda"
16+
},
17+
{
18+
"iac": "sam",
19+
"runtime": "java",
20+
"assetName": "s3-lambda-resizing-java"
21+
},
22+
{
23+
"iac": "sam",
24+
"runtime": "dotnet",
25+
"assetName": "s3-lambda-dotnet"
26+
}
27+
]
28+
},
29+
"Hello World Lambda with API": {
30+
"name": "Rest API",
31+
"description": "Lambda, API Gateway • Python, Javascript, Java, .NET • SAM",
32+
"implementation": [
33+
{
34+
"iac": "sam",
35+
"runtime": "python",
36+
"assetName": "apigw-rest-api-lambda-python"
37+
},
38+
{
39+
"iac": "sam",
40+
"runtime": "javascript",
41+
"assetName": "apigw-rest-api-lambda-node"
42+
},
43+
{
44+
"iac": "sam",
45+
"runtime": "java",
46+
"assetName": "apigw-rest-api-lambda-java"
47+
},
48+
{
49+
"iac": "sam",
50+
"runtime": "dotnet",
51+
"assetName": "apigw-rest-api-lambda-dotnet"
52+
}
53+
]
54+
},
55+
"Process SQS Records with Lambda": {
56+
"name": "Rest API",
57+
"description": "Lambda, SQS • Python, Javascript, Java, .NET • SAM",
58+
"implementation": [
59+
{
60+
"iac": "sam",
61+
"runtime": "python",
62+
"assetName": "sqs-lambda-python-sam"
63+
},
64+
{
65+
"iac": "sam",
66+
"runtime": "javascript",
67+
"assetName": "sqs-lambda-nodejs-sam"
68+
},
69+
{
70+
"iac": "sam",
71+
"runtime": "java",
72+
"assetName": "sqs-lambda-java-sam"
73+
},
74+
{
75+
"iac": "sam",
76+
"runtime": "dotnet",
77+
"assetName": "sqs-lambda-dotnet-sam"
78+
}
79+
]
80+
}
81+
}
82+
}

0 commit comments

Comments
 (0)