Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { Result } from '../../shared/telemetry/telemetry'
import { StateMachineNode } from '../explorer/stepFunctionsNodes'
import { telemetry } from '../../shared/telemetry/telemetry'
import { fs } from '../../shared/fs/fs'
import { WorkflowStudioEditorProvider } from '../workflowStudio/workflowStudioEditorProvider'
import { openWorkflowStudioWithDefinition } from '../utils'

export async function downloadStateMachineDefinition(params: {
outputChannel: vscode.OutputChannel
Expand All @@ -35,13 +35,7 @@ export async function downloadStateMachineDefinition(params: {
})

if (params.isPreviewAndRender) {
const doc = await vscode.workspace.openTextDocument({
language: 'asl',
content: stateMachineDetails.definition,
})

const textEditor = await vscode.window.showTextDocument(doc)
await WorkflowStudioEditorProvider.openWithWorkflowStudio(textEditor.document.uri, {
await openWorkflowStudioWithDefinition(stateMachineDetails.definition, {
preserveFocus: true,
viewColumn: vscode.ViewColumn.Beside,
})
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export class ExecutionDetailProvider {
const panel = vscode.window.createWebviewPanel(
ExecutionDetailProvider.viewType,
`Execution: ${executionArn.split(':').pop() || executionArn}`,
vscode.ViewColumn.Beside,
vscode.ViewColumn.One,
{
enableScripts: true,
retainContextWhenHidden: true,
Expand Down Expand Up @@ -96,6 +96,7 @@ export class ExecutionDetailProvider {
* Initializes a WebView panel with execution details.
* @param panel The WebView panel to initialize
* @param executionArn The ARN of the execution to display
* @param startTime Optional start time for the execution
*/
public async initializePanel(panel: vscode.WebviewPanel, executionArn: string, startTime?: string): Promise<void> {
try {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ import {
handleUnsupportedMessage,
apiCallMessageHandler,
} from '../messageHandlers/handleMessageHelpers'
import { parseExecutionArnForStateMachine, openWorkflowStudio, showExecuteStateMachineWebview } from '../utils'
import { getLogger } from '../../shared/logger/logger'

/**
* Handles messages received from the ExecutionDetails webview. Depending on the message type and command,
Expand All @@ -34,6 +36,12 @@ export async function handleMessage(message: Message, context: ExecutionDetailsC
case Command.API_CALL:
void apiCallMessageHandler(message as ApiCallRequestMessage, context)
break
case Command.START_EXECUTION:
void startExecutionMessageHandler(context)
break
case Command.EDIT_STATE_MACHINE:
void editStateMachineMessageHandler(context)
break
default:
void handleUnsupportedMessage(context, message)
break
Expand Down Expand Up @@ -74,3 +82,29 @@ async function initMessageHandler(context: ExecutionDetailsContext) {
} as InitResponseMessage)
}
}

async function startExecutionMessageHandler(context: ExecutionDetailsContext) {
const logger = getLogger('stepfunctions')
try {
// Parsing execution ARN to get state machine info
const parsedArn = parseExecutionArnForStateMachine(context.executionArn)
if (!parsedArn) {
throw new Error(`Invalid execution ARN format: ${context.executionArn}`)
Copy link
Contributor

Choose a reason for hiding this comment

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

nit:
Its better to mention StepFunctions in front of logs as we do have many services in AWS Toolkit. I guess this will ease to debug issues.

}

const { region, stateMachineName, stateMachineArn } = parsedArn

await showExecuteStateMachineWebview({
arn: stateMachineArn,
name: stateMachineName,
region: region,
})
} catch (error) {
logger.error('Start execution failed: %O', error)
}
}

async function editStateMachineMessageHandler(context: ExecutionDetailsContext) {
const params = parseExecutionArnForStateMachine(context.executionArn)
await openWorkflowStudio(params!.stateMachineArn, params!.region)
}
2 changes: 2 additions & 0 deletions packages/core/src/stepFunctions/messageHandlers/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@ export enum Command {
CLOSE_WFS = 'CLOSE_WFS',
API_CALL = 'API_CALL',
UNSUPPORTED_COMMAND = 'UNSUPPORTED_COMMAND',
START_EXECUTION = 'START_EXECUTION',
EDIT_STATE_MACHINE = 'EDIT_STATE_MACHINE',
}

export type FileWatchInfo = {
Expand Down
93 changes: 93 additions & 0 deletions packages/core/src/stepFunctions/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,20 @@ import {
} from 'amazon-states-language-service'
import { fromExtensionManifest } from '../shared/settings'
import { IamRole } from '../shared/clients/iam'
import { WorkflowStudioEditorProvider } from './workflowStudio/workflowStudioEditorProvider'
import { VueWebview } from '../webviews/main'
import { ExecuteStateMachineWebview } from './vue/executeStateMachine/executeStateMachine'
import globals from '../shared/extensionGlobals'

const documentSettings: DocumentLanguageSettings = { comments: 'error', trailingCommas: 'error' }
const languageService = getLanguageService({})

const arnResourceTypeSegmentIndex = 5
const expressExecutionArnSegmentCount = 9
const executionArnSegmentCount = 8
const arnRegionSegmentIndex = 3
const arnAccountIdSegmentIndex = 4
const arnStateMachineNameSegmentIndex = 6

export async function* listStateMachines(
client: StepFunctionsClient
Expand Down Expand Up @@ -107,6 +115,91 @@ export const isExpressExecution = (arn: string): boolean => {
)
}

/**
* Parses an execution ARN to extract state machine information
* @param executionArn The execution ARN to parse
* @returns Object containing region, state machine name, and state machine ARN
*/
export const parseExecutionArnForStateMachine = (executionArn: string) => {
const arnSegments = executionArn.split(':')
if (arnSegments.length === executionArnSegmentCount || arnSegments.length === expressExecutionArnSegmentCount) {
const region = arnSegments[arnRegionSegmentIndex]
const stateMachineName = arnSegments[arnStateMachineNameSegmentIndex]
const stateMachineArn = `arn:aws:states:${region}:${arnSegments[arnAccountIdSegmentIndex]}:stateMachine:${stateMachineName}`

return {
region,
stateMachineName,
stateMachineArn,
}
}
}

/**
* Opens a state machine definition in Workflow Studio
* @param stateMachineArn The ARN of the state machine
* @param region The AWS region
*/
export const openWorkflowStudio = async (stateMachineArn: string, region: string) => {
const client: StepFunctionsClient = new StepFunctionsClient(region)
const stateMachineDetails: StepFunctions.DescribeStateMachineCommandOutput = await client.getStateMachineDetails({
stateMachineArn,
})

await openWorkflowStudioWithDefinition(stateMachineDetails.definition)
}

/**
* Opens a state machine definition in Workflow Studio using pre-fetched definition content
* @param definition The state machine definition content
* @param options Optional webview configuration options
*/
export const openWorkflowStudioWithDefinition = async (
definition: string | undefined,
options?: {
preserveFocus?: boolean
viewColumn?: vscode.ViewColumn
}
) => {
const doc = await vscode.workspace.openTextDocument({
language: 'asl',
content: definition,
})

const textEditor = await vscode.window.showTextDocument(doc)
await WorkflowStudioEditorProvider.openWithWorkflowStudio(textEditor.document.uri, {
preserveFocus: options?.preserveFocus ?? false,
viewColumn: options?.viewColumn ?? vscode.ViewColumn.One,
})
}

/**
* Shows the Execute State Machine webview with the provided state machine data
* @param extensionContext The extension context
* @param outputChannel The output channel for logging
* @param stateMachineData Object containing arn, name, and region of the state machine
* @returns The webview instance
*/
export const showExecuteStateMachineWebview = async (stateMachineData: {
arn: string
name: string
region: string
}) => {
const Panel = VueWebview.compilePanel(ExecuteStateMachineWebview)
const wv = new Panel(globals.context, globals.outputChannel, {
arn: stateMachineData.arn,
name: stateMachineData.name,
region: stateMachineData.region,
})

await wv.show({
title: localize('AWS.executeStateMachine.title', 'Start Execution'),
cssFiles: ['executeStateMachine.css'],
})

return wv
}

const isInvalidJson = (content: string): boolean => {
try {
JSON.parse(content)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { VueWebview } from '../../../webviews/main'
import * as vscode from 'vscode'
import { telemetry } from '../../../shared/telemetry/telemetry'
import { ExecutionDetailProvider } from '../../executionDetails/executionDetailProvider'
import { showExecuteStateMachineWebview } from '../../utils'

interface StateMachine {
arn: string
Expand Down Expand Up @@ -88,18 +89,11 @@ export class ExecuteStateMachineWebview extends VueWebview {
}
}

const Panel = VueWebview.compilePanel(ExecuteStateMachineWebview)

export async function executeStateMachine(context: ExtContext, node: StateMachineNode): Promise<void> {
const wv = new Panel(context.extensionContext, context.outputChannel, {
await showExecuteStateMachineWebview({
arn: node.details.stateMachineArn || '',
name: node.details.name || '',
region: node.regionCode,
})

await wv.show({
title: localize('AWS.executeStateMachine.title', 'Start Execution'),
cssFiles: ['executeStateMachine.css'],
})
telemetry.stepfunctions_executeStateMachineView.emit()
}
Loading
Loading