-
Notifications
You must be signed in to change notification settings - Fork 149
Improve Event Grid Local Development Experience #3984
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
Changes from 6 commits
Commits
Show all changes
33 commits
Select commit
Hold shift + click to select a range
efa7e82
first working poc
hossam-nasr f8f4558
prompt for fields enclosed by {}
hossam-nasr 9995b87
add button and code lens + clean up and refactor
hossam-nasr 6c48f01
fix rebase
hossam-nasr 9fa9774
more refactor and cleanup
hossam-nasr 8c646aa
fix change in tree
hossam-nasr 7c77ae7
add license comments
hossam-nasr 20cc9e6
import type
hossam-nasr 3a1425d
restructure
hossam-nasr 00089ec
switch to using a wizard
hossam-nasr 1ea43c6
keep the file open and remember the function associated with each file
hossam-nasr 2adbf39
add aka.ms link & add code lens at the bottom
hossam-nasr f043928
switch to using AzExtFsExtra
hossam-nasr e0a3cb0
wrap in try/finally
hossam-nasr 012a593
rename to save and execute
hossam-nasr 8ee991e
revert aka.ms link for now
hossam-nasr 203c151
fix codelens last line
hossam-nasr 9b2eeb7
remove commented out code
hossam-nasr acd4317
add source of event sources
hossam-nasr 79ea4f3
revert styling changes in unrelated file
hossam-nasr b2029b4
remove last line codelens
hossam-nasr 1ceca9e
add licenses
hossam-nasr 4eb5e40
PR nits
hossam-nasr b17f5e8
show info box only once per session
hossam-nasr 907ce44
update to use workspaceState
hossam-nasr 3a93fe6
PR feedback
hossam-nasr 3c055fd
remove weird defaulting
hossam-nasr bdf6a59
telemetry: entry point
hossam-nasr b24e300
telemetry: event source & type
hossam-nasr 774e414
telemetry: whether file was modified
hossam-nasr 4241096
check
hossam-nasr 99333f8
use constants
hossam-nasr e90ead8
Merge branch 'main' into hossamnasr/eventgrid-lde
hossam-nasr File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,14 @@ | ||
| import { CodeLens, CodeLensProvider, Range } from 'vscode'; | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| import { localize } from '../../localize'; | ||
|
|
||
| export class EventGridCodeLensProvider implements CodeLensProvider { | ||
| public provideCodeLenses(): CodeLens[] { | ||
| const sendRequestLens = new CodeLens(new Range(0, 0, 0, 0)); | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| sendRequestLens.command = { | ||
| title: localize('saveSendRequest', 'Save and send request'), | ||
| command: 'azureFunctions.eventGrid.sendMockRequest', | ||
| }; | ||
|
|
||
| return [sendRequestLens]; | ||
| } | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,59 @@ | ||
| export type EventGridSource = | ||
| | 'Microsoft.ApiManagement' | ||
| | 'Microsoft.AppConfiguration' | ||
| | 'Microsoft.AVS' | ||
| | 'Microsoft.Cache' | ||
| | 'Microsoft.Communication' | ||
| | 'Microsoft.ContainerRegistry' | ||
| | 'Microsoft.ContainerService' | ||
| | 'Microsoft.DataBox' | ||
| | 'Microsoft.Devices' | ||
| | 'Microsoft.EventHub' | ||
| | 'Microsoft.HealthcareApis' | ||
| | 'Microsoft.KeyVault' | ||
| | 'Microsoft.MachineLearningServices' | ||
| | 'Microsoft.Maps' | ||
| | 'Microsoft.Media' | ||
| | 'Microsoft.PolicyInsights' | ||
| | 'Microsoft.ResourceNotification' | ||
| | 'Microsoft.Resources' | ||
| | 'Microsoft.ServiceBus' | ||
| | 'Microsoft.SignalRService' | ||
| | 'Microsoft.Storage' | ||
| | 'Microsoft.Web' | ||
| | string; | ||
|
|
||
| export const supportedEventGridSources: EventGridSource[] = [ | ||
| 'Microsoft.ApiManagement', | ||
| 'Microsoft.AppConfiguration', | ||
| 'Microsoft.AVS', | ||
| 'Microsoft.Cache', | ||
| 'Microsoft.Communication', | ||
| 'Microsoft.ContainerRegistry', | ||
| 'Microsoft.ContainerService', | ||
| 'Microsoft.DataBox', | ||
| 'Microsoft.Devices', | ||
| 'Microsoft.EventHub', | ||
| 'Microsoft.HealthcareApis', | ||
| 'Microsoft.KeyVault', | ||
| 'Microsoft.MachineLearningServices', | ||
| 'Microsoft.Maps', | ||
| 'Microsoft.Media', | ||
| 'Microsoft.PolicyInsights', | ||
| 'Microsoft.ResourceNotification', | ||
| 'Microsoft.Resources', | ||
| 'Microsoft.ServiceBus', | ||
| 'Microsoft.SignalRService', | ||
| 'Microsoft.Storage', | ||
| 'Microsoft.Web', | ||
| ]; | ||
|
|
||
| export const supportedEventGridSourceLabels: Map<EventGridSource, string> = new Map([ | ||
| ['Microsoft.Storage', 'Blob Storage'], | ||
| ['Microsoft.EventHub', 'Event Hubs'], | ||
| ['Microsoft.ServiceBus', 'Service Bus'], | ||
| ['Microsoft.ContainerRegistry', 'Container Registry'], | ||
| ['Microsoft.ApiManagement', 'API Management'], | ||
| ['Microsoft.Resources', 'Resources'], | ||
| ['Microsoft.HealthcareApis', 'Health Data Services'], | ||
| ]); |
156 changes: 156 additions & 0 deletions
156
src/commands/executeFunction/executeEventGridFunction.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,156 @@ | ||
| /*--------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||
| *--------------------------------------------------------------------------------------------*/ | ||
|
|
||
| import { IActionContext, IAzureQuickPickItem } from '@microsoft/vscode-azext-utils'; | ||
| import * as fs from 'fs-extra'; | ||
| import * as os from 'os'; | ||
| import * as path from 'path'; | ||
| import * as vscode from 'vscode'; | ||
| import { localize } from '../../localize'; | ||
| import { FunctionTreeItemBase } from '../../tree/FunctionTreeItemBase'; | ||
| import { feedUtils } from '../../utils/feedUtils'; | ||
| import { IFunction } from '../../workspace/LocalFunction'; | ||
| import { EventGridSource, supportedEventGridSourceLabels, supportedEventGridSources } from './eventGridSources'; | ||
| import { executeFunctionWithInput } from './executeFunction'; | ||
|
|
||
| type FileMetadata = { | ||
| name: string; | ||
| path: string; | ||
| sha: string; | ||
| size: number; | ||
| url: string; | ||
| html_url: string; | ||
| git_url: string; | ||
| download_url: string; | ||
| type: string; | ||
| _links: { | ||
| self: string; | ||
| git: string; | ||
| html: string; | ||
| }; | ||
| }; | ||
|
|
||
| const sampleFilesUrl = | ||
| 'https://api.github.com/repos/Azure/azure-rest-api-specs/contents/specification/eventgrid/data-plane/' + | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| '{eventSource}' + | ||
| '/stable/2018-01-01/examples/cloud-events-schema/'; | ||
|
|
||
| export async function executeEventGridFunction(context: IActionContext, node: FunctionTreeItemBase | IFunction): Promise<void> { | ||
| // Prompt for event source | ||
| const eventGridSourcePicks: IAzureQuickPickItem<EventGridSource | undefined>[] = supportedEventGridSources.map((source: EventGridSource) => { | ||
| return { | ||
| label: supportedEventGridSourceLabels.get(source) || source, | ||
| data: source, | ||
| }; | ||
| }); | ||
| const eventSource: EventGridSource = | ||
| ( | ||
| await context.ui.showQuickPick(eventGridSourcePicks, { | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| placeHolder: localize('selectEventSource', 'Select the event source'), | ||
| stepName: 'eventGridSource', | ||
| }) | ||
| ).data ?? 'Microsoft.Storage'; | ||
|
|
||
| // Get sample files for event source | ||
| const samplesUrl = sampleFilesUrl.replace('{eventSource}', eventSource); | ||
| const sampleFiles: FileMetadata[] = await feedUtils.getJsonFeed(context, samplesUrl); | ||
| const fileNames: string[] = sampleFiles.map((fileMetadata) => fileMetadata.name); | ||
|
|
||
| // Prompt for event type | ||
| const eventTypePicks: IAzureQuickPickItem<string | undefined>[] = fileNames.map((name: string) => ({ | ||
| data: name, | ||
| // give human-readable name for event type from file name | ||
| label: name | ||
| .replace(/\.json$/, '') | ||
| .split('_') | ||
| .map((word) => word.charAt(0).toUpperCase() + word.slice(1)) | ||
| .join(' '), | ||
| })); | ||
| const selectedFileName: string = | ||
| ( | ||
| await context.ui.showQuickPick(eventTypePicks, { | ||
| placeHolder: localize('selectEventType', 'Select the event type'), | ||
| stepName: 'eventType', | ||
| }) | ||
| ).data ?? 'blob_created.json'; | ||
|
|
||
| // Get selected contents of sample request | ||
| const selectedFileUrl = sampleFiles.find((fileMetadata) => fileMetadata.name === selectedFileName)?.download_url || sampleFiles[0].download_url; | ||
| const selectedFileContents: {} = await feedUtils.getJsonFeed(context, selectedFileUrl); | ||
|
|
||
| // Prompt for whether to send or modify the sample request | ||
| const shouldModify: boolean = | ||
| ( | ||
| await context.ui.showQuickPick( | ||
| [ | ||
| { | ||
| label: localize('sendSample', 'Send sample request'), | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| data: false, | ||
| }, | ||
| { | ||
| label: localize('modifySample', 'Modify sample request'), | ||
| data: true, | ||
| }, | ||
| ], | ||
| { | ||
| placeHolder: 'Would you like to send the sample request or modify it first?', | ||
| stepName: 'modifyOrSendSample', | ||
| }, | ||
| ) | ||
| ).data || false; | ||
|
|
||
| // Execute function with sample data directly if user chooses not to modify | ||
| if (!shouldModify) { | ||
| return executeFunctionWithInput(context, selectedFileContents, node); | ||
| } | ||
|
|
||
| // Create a temp file with the sample request & open in new window | ||
| const tempFilePath: string = await createTempSampleFile(eventSource, selectedFileName, selectedFileContents); | ||
| const document: vscode.TextDocument = await vscode.workspace.openTextDocument(tempFilePath); | ||
| await vscode.window.showTextDocument(document, { | ||
| preview: false, | ||
| }); | ||
|
|
||
| // Request will be sent when the user clicks on the button or on the codelens link | ||
|
|
||
| // Set a listener to delete the temp file after it's closed | ||
| await new Promise<void>((resolve, reject) => { | ||
| const disposable = vscode.workspace.onDidCloseTextDocument(async (closedDocument) => { | ||
| if (closedDocument.fileName === document.fileName) { | ||
| try { | ||
| await fs.unlink(tempFilePath); | ||
| resolve(); | ||
| } catch (error) { | ||
| reject(error); | ||
| } finally { | ||
| disposable.dispose(); | ||
| } | ||
| } | ||
| }); | ||
| }); | ||
| } | ||
|
|
||
| async function createTempSampleFile(eventSource: string, fileName: string, contents: {}): Promise<string> { | ||
| const samplesDirPath = await createSamplesDirIfNotExists(eventSource); | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| const sampleFileName = fileName.replace(/\.json$/, '.eventgrid.json'); | ||
| const filePath: string = path.join(samplesDirPath, sampleFileName); | ||
|
|
||
| await fs.writeFile(filePath, JSON.stringify(contents, undefined, 2)); | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
|
|
||
| return filePath; | ||
| } | ||
|
|
||
| async function createSamplesDirIfNotExists(eventSource: string): Promise<string> { | ||
| const baseDir: string = vscode.workspace.workspaceFolders?.[0]?.uri?.fsPath || path.join(os.tmpdir(), 'vscode', 'azureFunctions'); | ||
|
|
||
| // Create the path to the directory | ||
| const dirPath = path.join(baseDir, '.vscode', 'eventGridSamples', eventSource); | ||
| // Create the directory if it doesn't already exist | ||
| if (!(await fs.pathExists(dirPath))) { | ||
|
hossam-nasr marked this conversation as resolved.
Outdated
|
||
| await fs.mkdirp(dirPath); | ||
| } | ||
| // Return the path to the directory | ||
| return dirPath; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.