44 */
55
66import { commands , env , Uri , window , workspace , Range , Selection , TextEditorRevealType , ProgressLocation } from 'vscode'
7- import { commandKey , extractErrorMessage , findParameterDescriptionPosition } from '../utils'
7+ import { commandKey , extractErrorMessage , findParameterDescriptionPosition , isStackInTransientState } from '../utils'
88import { LanguageClient } from 'vscode-languageclient/node'
99import { Command } from 'vscode-languageclient/node'
1010import * as yaml from 'js-yaml'
@@ -25,15 +25,14 @@ import {
2525 getOnStackFailure ,
2626 getIncludeNestedStacks ,
2727 getImportExistingResources ,
28+ getDeploymentMode ,
2829 shouldUploadToS3 ,
2930 getS3Bucket ,
3031 getS3Key ,
3132 shouldSaveFlagsToFile ,
3233 getFilePath ,
3334} from '../ui/inputBox'
34- import { setContext } from '../../../shared/vscode/setContext'
3535import { DiffWebviewProvider } from '../ui/diffWebviewProvider'
36- import { StackResourcesWebviewProvider } from '../ui/stackResourcesWebviewProvider'
3736import { showErrorMessage } from '../ui/message'
3837import { getLastValidation , setLastValidation , Validation } from '../stacks/actions/validationWorkflow'
3938import {
@@ -49,21 +48,23 @@ import {
4948 TemplateParameter ,
5049 ResourceToImport ,
5150 ChangeSetReference ,
51+ DeploymentMode ,
5252} from '../stacks/actions/stackActionRequestType'
53- import { StackInfo } from '../stacks/actions/stackActionRequestType'
5453import { ResourceNode } from '../explorer/nodes/resourceNode'
5554import { ResourcesManager } from '../resources/resourcesManager'
5655import { RelatedResourcesManager } from '../relatedResources/relatedResourcesManager'
5756import { DocumentManager } from '../documents/documentManager'
5857import { CfnEnvironmentManager } from '../cfn-init/cfnEnvironmentManager'
5958
6059import { StackOverviewWebviewProvider } from '../ui/stackOverviewWebviewProvider'
61- import { StackEventsWebviewProvider } from '../ui/stackEventsWebviewProvider'
6260import { StackOutputsWebviewProvider } from '../ui/stackOutputsWebviewProvider'
61+ import { StackResourcesWebviewProvider } from '../ui/stackResourcesWebviewProvider'
62+ import { StackViewCoordinator } from '../ui/stackViewCoordinator'
6363import { ResourceContextValue } from '../explorer/contextValue'
6464import { getLogger } from '../../../shared/logger/logger'
6565import { CloudFormationExplorer } from '../explorer/explorer'
6666import { StacksNode } from '../explorer/nodes/stacksNode'
67+ import { StackNode } from '../explorer/nodes/stackNode'
6768import { ResourcesNode } from '../explorer/nodes/resourcesNode'
6869import { ResourceTypeNode } from '../explorer/nodes/resourceTypeNode'
6970import { StackChangeSetsNode } from '../explorer/nodes/stackChangeSetsNode'
@@ -72,7 +73,6 @@ import { CfnInitUiInterface } from '../cfn-init/cfnInitUiInterface'
7273import { ChangeSetDeletion } from '../stacks/actions/changeSetDeletionWorkflow'
7374import { fs } from '../../../shared/fs/fs'
7475import { convertParametersToRecord , convertTagsToRecord } from '../cfn-init/utils'
75- import { StackNode } from '../explorer/nodes/stackNode'
7676import { DescribeStackRequest } from '../stacks/actions/stackActionProtocol'
7777
7878export function validateDeploymentCommand (
@@ -127,12 +127,12 @@ export function deployTemplateFromStacksMenuCommand() {
127127 } )
128128}
129129
130- export function executeChangeSetCommand ( client : LanguageClient ) {
130+ export function executeChangeSetCommand ( client : LanguageClient , coordinator : StackViewCoordinator ) {
131131 return commands . registerCommand (
132132 commandKey ( 'api.executeChangeSet' ) ,
133133 async ( stackName : string , changeSetName : string ) => {
134134 try {
135- const deployment = new Deployment ( stackName , changeSetName , client )
135+ const deployment = new Deployment ( stackName , changeSetName , client , coordinator )
136136
137137 await deployment . deploy ( )
138138 } catch ( error ) {
@@ -174,9 +174,7 @@ export function viewChangeSetCommand(client: LanguageClient, diffProvider: DiffW
174174 stackName : params . stackName ,
175175 } )
176176
177- void setContext ( 'aws.cloudformation.stacks.diffVisible' , true )
178-
179- diffProvider . updateData ( params . stackName , describeChangeSetResult . changes , params . changeSetName , true )
177+ void diffProvider . updateData ( params . stackName , describeChangeSetResult . changes , params . changeSetName , true )
180178 void commands . executeCommand ( commandKey ( 'diff.focus' ) )
181179 } catch ( error ) {
182180 showErrorMessage ( `Error viewing change set: ${ extractErrorMessage ( error ) } ` )
@@ -259,6 +257,18 @@ type OptionalFlagSelection = ChangeSetOptionalFlags & {
259257 shouldSaveOptions ?: boolean
260258}
261259
260+ function shouldPromptForDeploymentMode (
261+ stackDetails : Stack | undefined ,
262+ importExistingResources : boolean | undefined ,
263+ includeNestedStacks : boolean | undefined ,
264+ onStackFailure : OnStackFailure | undefined
265+ ) : boolean {
266+ const isCreate = ! stackDetails
267+ const hasDisableRollback = onStackFailure === OnStackFailure . DO_NOTHING
268+
269+ return ! isCreate && ! importExistingResources && ! includeNestedStacks && ! hasDisableRollback
270+ }
271+
262272export async function promptForOptionalFlags (
263273 fileFlags ?: ChangeSetOptionalFlags ,
264274 stackDetails ?: Stack
@@ -281,29 +291,60 @@ export async function promptForOptionalFlags(
281291 includeNestedStacks : fileFlags ?. includeNestedStacks ,
282292 tags : fileFlags ?. tags ,
283293 importExistingResources : fileFlags ?. importExistingResources ,
294+ // default to REVERT_DRIFT if possible because it's generally useful
295+ deploymentMode :
296+ fileFlags ?. deploymentMode ??
297+ ( shouldPromptForDeploymentMode (
298+ stackDetails ,
299+ fileFlags ?. importExistingResources ,
300+ fileFlags ?. includeNestedStacks ,
301+ fileFlags ?. onStackFailure
302+ )
303+ ? DeploymentMode . REVERT_DRIFT
304+ : undefined ) ,
284305 shouldSaveOptions : false ,
285306 }
286307
287308 break
288- case OptionalFlagMode . Input :
309+ case OptionalFlagMode . Input : {
310+ const onStackFailure = fileFlags ?. onStackFailure ?? ( await getOnStackFailure ( ! ! stackDetails ) )
311+ const includeNestedStacks = fileFlags ?. includeNestedStacks ?? ( await getIncludeNestedStacks ( ) )
312+ const importExistingResources = fileFlags ?. importExistingResources ?? ( await getImportExistingResources ( ) )
313+
314+ let deploymentMode = fileFlags ?. deploymentMode
315+ if (
316+ ! deploymentMode &&
317+ shouldPromptForDeploymentMode (
318+ stackDetails ,
319+ importExistingResources ,
320+ includeNestedStacks ,
321+ onStackFailure
322+ )
323+ ) {
324+ deploymentMode = await getDeploymentMode ( )
325+ }
326+
289327 optionalFlags = {
290- onStackFailure : fileFlags ?. onStackFailure ?? ( await getOnStackFailure ( ) ) ,
291- includeNestedStacks : fileFlags ?. includeNestedStacks ?? ( await getIncludeNestedStacks ( ) ) ,
328+ onStackFailure,
329+ includeNestedStacks,
292330 tags : fileFlags ?. tags ?? ( await getTags ( stackDetails ?. Tags ) ) ,
293- importExistingResources : fileFlags ?. importExistingResources ?? ( await getImportExistingResources ( ) ) ,
331+ importExistingResources,
332+ deploymentMode,
294333 }
295334
296335 if ( ! fileFlags && Object . values ( optionalFlags ) . some ( ( val ) => val !== undefined ) ) {
297336 optionalFlags . shouldSaveOptions = true
298337 }
299338
300339 break
340+ }
301341 case OptionalFlagMode . DevFriendly :
302342 optionalFlags = {
303343 onStackFailure : OnStackFailure . DO_NOTHING ,
304344 includeNestedStacks : true ,
305345 tags : fileFlags ?. tags ?? ( await getTags ( stackDetails ?. Tags ) ) ,
306346 importExistingResources : true ,
347+ deploymentMode : undefined ,
307348 }
308349
309350 if ( ! fileFlags && optionalFlags . tags ) {
@@ -341,6 +382,7 @@ export async function promptToSaveToFile(
341382 'on-stack-failure' : optionalFlags ?. onStackFailure ,
342383 'include-nested-stacks' : optionalFlags ?. includeNestedStacks ,
343384 'import-existing-resources' : optionalFlags ?. importExistingResources ,
385+ 'deployment-mode' : optionalFlags ?. deploymentMode ,
344386 }
345387
346388 // Determine file type and format accordingly
@@ -590,23 +632,17 @@ async function getTemplateParameters(client: LanguageClient, templateUri: string
590632 }
591633}
592634
593- export const SelectResourceTypeCommand : Command = {
594- title : 'Select Resource Types' ,
595- command : commandKey ( 'api.selectResourceTypes' ) ,
596- arguments : [ ] ,
597- }
598-
599- export function selectResourceTypesCommand ( resourcesManager : ResourcesManager ) {
635+ export function addResourceTypesCommand ( resourcesManager : ResourcesManager ) {
600636 return commands . registerCommand (
601- commandKey ( 'api.selectResourceTypes ' ) ,
637+ commandKey ( 'api.addResourceTypes ' ) ,
602638 async ( ) => await resourcesManager . selectResourceTypes ( )
603639 )
604640}
605641
606- export function addResourceTypesCommand ( resourcesManager : ResourcesManager ) {
642+ export function removeResourceTypeCommand ( resourcesManager : ResourcesManager ) {
607643 return commands . registerCommand (
608- commandKey ( 'api.addResourceTypes ' ) ,
609- async ( ) => await resourcesManager . selectResourceTypes ( )
644+ commandKey ( 'removeResourceType ' ) ,
645+ async ( node : ResourceTypeNode ) => await resourcesManager . removeResourceType ( node . typeName )
610646 )
611647}
612648
@@ -684,24 +720,6 @@ export function refreshResourceListCommand(resourcesManager: ResourcesManager, e
684720 } )
685721}
686722
687- export function viewStackDiffCommand ( ) {
688- return commands . registerCommand ( commandKey ( 'stacks.viewDiff' ) , ( ) => {
689- void setContext ( 'aws.cloudformation.stacks.diffVisible' , true )
690- void commands . executeCommand ( commandKey ( 'diff.focus' ) )
691- } )
692- }
693-
694- export function viewStackDetailCommand ( resourcesProvider : StackResourcesWebviewProvider ) {
695- return commands . registerCommand ( commandKey ( 'stacks.viewDetail' ) , async ( node ?: any ) => {
696- void setContext ( 'aws.cloudformation.stacks.detailVisible' , true )
697-
698- const stackName = node ?. stackName || 'Unknown Stack'
699-
700- await resourcesProvider . updateData ( stackName )
701- void commands . executeCommand ( commandKey ( 'detail.focus' ) )
702- } )
703- }
704-
705723export function focusDiffCommand ( ) {
706724 return commands . registerCommand ( commandKey ( 'diff.focus' ) , ( ) => {
707725 void commands . executeCommand ( 'workbench.view.extension.cfn-diff' )
@@ -714,7 +732,7 @@ export function getStackManagementInfoCommand(resourcesManager: ResourcesManager
714732 } )
715733}
716734
717- export function extractToParameterPositionCursorCommand ( ) {
735+ export function extractToParameterPositionCursorCommand ( client : LanguageClient ) {
718736 return commands . registerCommand (
719737 'aws.cloudformation.extractToParameter.positionCursor' ,
720738 async (
@@ -725,9 +743,12 @@ export function extractToParameterPositionCursorCommand() {
725743 actionType ?: string
726744 ) => {
727745 try {
728- // Track code action acceptance if tracking parameters provided
746+ // Track code action acceptance on the server if tracking parameters provided
729747 if ( trackingCommand && actionType ) {
730- await commands . executeCommand ( trackingCommand , actionType )
748+ await client . sendRequest ( 'workspace/executeCommand' , {
749+ command : trackingCommand ,
750+ arguments : [ actionType ] ,
751+ } )
731752 }
732753
733754 const uri = Uri . parse ( documentUri )
@@ -846,23 +867,37 @@ export function loadMoreChangeSetsCommand(explorer: CloudFormationExplorer) {
846867 } )
847868}
848869
849- export function showStackOverviewCommand ( overviewProvider : StackOverviewWebviewProvider ) {
850- return commands . registerCommand ( commandKey ( 'api.showStackOverview' ) , async ( stack : StackInfo ) => {
851- await overviewProvider . showStackOverview ( stack )
852- } )
853- }
870+ export function viewStackCommand (
871+ coordinator : StackViewCoordinator ,
872+ overviewProvider : StackOverviewWebviewProvider ,
873+ outputsProvider : StackOutputsWebviewProvider ,
874+ resourcesProvider : StackResourcesWebviewProvider
875+ ) {
876+ return commands . registerCommand ( commandKey ( 'stack.view' ) , async ( node ?: StackNode ) => {
877+ let stackName : string | undefined
854878
855- export function showStackEventsCommand ( eventsProvider : StackEventsWebviewProvider ) {
856- return commands . registerCommand ( commandKey ( 'stack.events.show' ) , async ( stackName : string ) => {
857- await eventsProvider . showStackEvents ( stackName )
858- await commands . executeCommand ( commandKey ( 'stack.events.focus' ) )
859- } )
860- }
879+ if ( node ?. stack . StackName ) {
880+ stackName = node . stack . StackName
881+ } else {
882+ stackName = await getStackName ( )
883+ if ( ! stackName ) {
884+ return
885+ }
886+ }
887+
888+ await coordinator . setStack ( stackName )
889+
890+ await overviewProvider . showStackOverview ( stackName )
891+
892+ const stackStatus = coordinator . currentStackStatus
893+
894+ await resourcesProvider . updateData ( stackName )
895+
896+ if ( stackStatus && ! isStackInTransientState ( stackStatus ) ) {
897+ await outputsProvider . showOutputs ( stackName )
898+ }
861899
862- export function showStackOutputsCommand ( outputsProvider : StackOutputsWebviewProvider ) {
863- return commands . registerCommand ( commandKey ( 'stack.outputs.show' ) , async ( stackName : string ) => {
864- await outputsProvider . showOutputs ( stackName )
865- await commands . executeCommand ( commandKey ( 'stack.outputs.focus' ) )
900+ await commands . executeCommand ( commandKey ( 'stack.overview.focus' ) )
866901 } )
867902}
868903
0 commit comments