/******************************************************************************* * Copyright 2012-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. * Licensed under the Apache License, Version 2.0 (the "License"). You may not use * this file except in compliance with the License. A copy of the License is located at * * http://aws.amazon.com/apache2.0 * * or in the "license" file accompanying this file. * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR * CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. * ***************************************************************************** * * AWS Tools for Windows (TM) PowerShell (TM) * */ using System; using System.Collections.Generic; using System.Linq; using System.Management.Automation; using System.Text; using Amazon.PowerShell.Common; using Amazon.Runtime; using Amazon.CloudFormation; using Amazon.CloudFormation.Model; namespace Amazon.PowerShell.Cmdlets.CFN { /// /// Creates a list of changes that will be applied to a stack so that you can review the /// changes before executing them. You can create a change set for a stack that doesn't /// exist or an existing stack. If you create a change set for a stack that doesn't exist, /// the change set shows all of the resources that CloudFormation will create. If you /// create a change set for an existing stack, CloudFormation compares the stack's information /// with the information that you submit in the change set and lists the differences. /// Use change sets to understand which resources CloudFormation will create or change, /// and how it will change resources in an existing stack, before you create or update /// a stack. /// /// /// /// To create a change set for a stack that doesn't exist, for the ChangeSetType /// parameter, specify CREATE. To create a change set for an existing stack, /// specify UPDATE for the ChangeSetType parameter. To create /// a change set for an import operation, specify IMPORT for the ChangeSetType /// parameter. After the CreateChangeSet call successfully completes, CloudFormation /// starts creating the change set. To check the status of the change set or to review /// it, use the DescribeChangeSet action. /// /// When you are satisfied with the changes the change set will make, execute the change /// set by using the ExecuteChangeSet action. CloudFormation doesn't make changes /// until you execute the change set. /// /// To create a change set for the entire stack hierarchy, set IncludeNestedStacks /// to True. /// /// [Cmdlet("New", "CFNChangeSet", SupportsShouldProcess = true, ConfirmImpact = ConfirmImpact.Medium)] [OutputType("System.String")] [AWSCmdlet("Calls the AWS CloudFormation CreateChangeSet API operation.", Operation = new[] {"CreateChangeSet"}, SelectReturnType = typeof(Amazon.CloudFormation.Model.CreateChangeSetResponse))] [AWSCmdletOutput("System.String or Amazon.CloudFormation.Model.CreateChangeSetResponse", "This cmdlet returns a System.String object.", "The service call response (type Amazon.CloudFormation.Model.CreateChangeSetResponse) can also be referenced from properties attached to the cmdlet entry in the $AWSHistory stack." )] public partial class NewCFNChangeSetCmdlet : AmazonCloudFormationClientCmdlet, IExecutor { #region Parameter Capability /// /// /// In some cases, you must explicitly acknowledge that your stack template contains certain /// capabilities in order for CloudFormation to create the stack. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [Alias("Capabilities")] public System.String[] Capability { get; set; } #endregion #region Parameter ChangeSetName /// /// /// The name of the change set. The name must be unique among all change sets that are /// associated with the specified stack.A change set name can contain only alphanumeric, case sensitive characters, and hyphens. /// It must start with an alphabetical character and can't exceed 128 characters. /// /// #if !MODULAR [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] #else [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true, Mandatory = true)] [System.Management.Automation.AllowEmptyString] [System.Management.Automation.AllowNull] #endif [Amazon.PowerShell.Common.AWSRequiredParameter] public System.String ChangeSetName { get; set; } #endregion #region Parameter ChangeSetType /// /// /// The type of change set operation. To create a change set for a new stack, specify /// CREATE. To create a change set for an existing stack, specify UPDATE. /// To create a change set for an import operation, specify IMPORT.If you create a change set for a new stack, CloudFormation creates a stack with a /// unique stack ID, but no template or resources. The stack will be in the REVIEW_IN_PROGRESS /// state until you execute the change set.By default, CloudFormation specifies UPDATE. You can't use the UPDATE /// type to create a change set for a new stack or the CREATE type to create /// a change set for an existing stack. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [AWSConstantClassSource("Amazon.CloudFormation.ChangeSetType")] public Amazon.CloudFormation.ChangeSetType ChangeSetType { get; set; } #endregion #region Parameter Description /// /// /// A description to help you identify this change set. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String Description { get; set; } #endregion #region Parameter IncludeNestedStack /// /// /// Creates a change set for the all nested stacks specified in the template. The default /// behavior of this action is set to False. To include nested sets in a /// change set, specify True. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [Alias("IncludeNestedStacks")] public System.Boolean? IncludeNestedStack { get; set; } #endregion #region Parameter NotificationARNs /// /// /// The Amazon Resource Names (ARNs) of Amazon Simple Notification Service (Amazon SNS) /// topics that CloudFormation associates with the stack. To remove all associated notification /// topics, specify an empty list. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String[] NotificationARNs { get; set; } #endregion #region Parameter OnStackFailure /// /// /// Determines what action will be taken if stack creation fails. If this parameter is /// specified, the DisableRollback parameter to the ExecuteChangeSet /// API operation must not be specified. This must be one of these values:For nested stacks, when the OnStackFailure parameter is set to DELETE /// for the change set for the parent stack, any failure in a child stack will cause the /// parent stack creation to fail and all stacks to be deleted. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [AWSConstantClassSource("Amazon.CloudFormation.OnStackFailure")] public Amazon.CloudFormation.OnStackFailure OnStackFailure { get; set; } #endregion #region Parameter Parameter /// /// /// A list of Parameter structures that specify input parameters for the /// change set. For more information, see the Parameter data type. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [Alias("Parameters")] public Amazon.CloudFormation.Model.Parameter[] Parameter { get; set; } #endregion #region Parameter ResourcesToImport /// /// /// The resources to import into your stack. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public Amazon.CloudFormation.Model.ResourceToImport[] ResourcesToImport { get; set; } #endregion #region Parameter ResourceType /// /// /// The template resource types that you have permissions to work with if you execute /// this change set, such as AWS::EC2::Instance, AWS::EC2::*, /// or Custom::MyCustomInstance.If the list of resource types doesn't include a resource type that you're updating, /// the stack update fails. By default, CloudFormation grants permissions to all resource /// types. Identity and Access Management (IAM) uses this parameter for condition keys /// in IAM policies for CloudFormation. For more information, see Controlling /// access with Identity and Access Management in the CloudFormation User Guide. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [Alias("ResourceTypes")] public System.String[] ResourceType { get; set; } #endregion #region Parameter RoleARN /// /// /// The Amazon Resource Name (ARN) of an Identity and Access Management (IAM) role that /// CloudFormation assumes when executing the change set. CloudFormation uses the role's /// credentials to make calls on your behalf. CloudFormation uses this role for all future /// operations on the stack. Provided that users have permission to operate on the stack, /// CloudFormation uses this role even if the users don't have permission to pass it. /// Ensure that the role grants least permission.If you don't specify a value, CloudFormation uses the role that was previously associated /// with the stack. If no role is available, CloudFormation uses a temporary session that /// is generated from your user credentials. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String RoleARN { get; set; } #endregion #region Parameter RollbackConfiguration /// /// /// The rollback triggers for CloudFormation to monitor during stack creation and updating /// operations, and for the specified monitoring period afterwards. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public Amazon.CloudFormation.Model.RollbackConfiguration RollbackConfiguration { get; set; } #endregion #region Parameter StackName /// /// /// The name or the unique ID of the stack for which you are creating a change set. CloudFormation /// generates the change set by comparing this stack's information with the information /// that you submit, such as a modified template or different parameter input values. /// /// #if !MODULAR [System.Management.Automation.Parameter(Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true)] #else [System.Management.Automation.Parameter(Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true, Mandatory = true)] [System.Management.Automation.AllowEmptyString] [System.Management.Automation.AllowNull] #endif [Amazon.PowerShell.Common.AWSRequiredParameter] public System.String StackName { get; set; } #endregion #region Parameter Tag /// /// /// Key-value pairs to associate with this stack. CloudFormation also propagates these /// tags to resources in the stack. You can specify a maximum of 50 tags. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] [Alias("Tags")] public Amazon.CloudFormation.Model.Tag[] Tag { get; set; } #endregion #region Parameter TemplateBody /// /// /// A structure that contains the body of the revised template, with a minimum length /// of 1 byte and a maximum length of 51,200 bytes. CloudFormation generates the change /// set by comparing this template with the template of the stack that you specified.Conditional: You must specify only TemplateBody or TemplateURL. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String TemplateBody { get; set; } #endregion #region Parameter TemplateURL /// /// /// The location of the file that contains the revised template. The URL must point to /// a template (max size: 460,800 bytes) that's located in an Amazon S3 bucket or a Systems /// Manager document. CloudFormation generates the change set by comparing this template /// with the stack that you specified.Conditional: You must specify only TemplateBody or TemplateURL. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String TemplateURL { get; set; } #endregion #region Parameter UsePreviousTemplate /// /// /// Whether to reuse the template that's associated with the stack to create the change /// set. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.Boolean? UsePreviousTemplate { get; set; } #endregion #region Parameter ClientToken /// /// /// A unique identifier for this CreateChangeSet request. Specify this token /// if you plan to retry requests so that CloudFormation knows that you're not attempting /// to create another change set with the same name. You might retry CreateChangeSet /// requests to ensure that CloudFormation successfully received them. /// /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public System.String ClientToken { get; set; } #endregion #region Parameter Select /// /// Use the -Select parameter to control the cmdlet output. The default value is 'Id'. /// Specifying -Select '*' will result in the cmdlet returning the whole service response (Amazon.CloudFormation.Model.CreateChangeSetResponse). /// Specifying the name of a property of type Amazon.CloudFormation.Model.CreateChangeSetResponse will result in that property being returned. /// Specifying -Select '^ParameterName' will result in the cmdlet returning the selected cmdlet parameter value. /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public string Select { get; set; } = "Id"; #endregion #region Parameter PassThru /// /// Changes the cmdlet behavior to return the value passed to the StackName parameter. /// The -PassThru parameter is deprecated, use -Select '^StackName' instead. This parameter will be removed in a future version. /// [System.Obsolete("The -PassThru parameter is deprecated, use -Select '^StackName' instead. This parameter will be removed in a future version.")] [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public SwitchParameter PassThru { get; set; } #endregion #region Parameter Force /// /// This parameter overrides confirmation prompts to force /// the cmdlet to continue its operation. This parameter should always /// be used with caution. /// [System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)] public SwitchParameter Force { get; set; } #endregion protected override void ProcessRecord() { this._AWSSignerType = "v4"; base.ProcessRecord(); var resourceIdentifiersText = FormatParameterValuesForConfirmationMsg(nameof(this.StackName), MyInvocation.BoundParameters); if (!ConfirmShouldProceed(this.Force.IsPresent, resourceIdentifiersText, "New-CFNChangeSet (CreateChangeSet)")) { return; } var context = new CmdletContext(); // allow for manipulation of parameters prior to loading into context PreExecutionContextLoad(context); #pragma warning disable CS0618, CS0612 //A class member was marked with the Obsolete attribute if (ParameterWasBound(nameof(this.Select))) { context.Select = CreateSelectDelegate(Select) ?? throw new System.ArgumentException("Invalid value for -Select parameter.", nameof(this.Select)); if (this.PassThru.IsPresent) { throw new System.ArgumentException("-PassThru cannot be used when -Select is specified.", nameof(this.Select)); } } else if (this.PassThru.IsPresent) { context.Select = (response, cmdlet) => this.StackName; } #pragma warning restore CS0618, CS0612 //A class member was marked with the Obsolete attribute if (this.Capability != null) { context.Capability = new List(this.Capability); } context.ChangeSetName = this.ChangeSetName; #if MODULAR if (this.ChangeSetName == null && ParameterWasBound(nameof(this.ChangeSetName))) { WriteWarning("You are passing $null as a value for parameter ChangeSetName which is marked as required. In case you believe this parameter was incorrectly marked as required, report this by opening an issue at https://github.com/aws/aws-tools-for-powershell/issues."); } #endif context.ChangeSetType = this.ChangeSetType; context.ClientToken = this.ClientToken; context.Description = this.Description; context.IncludeNestedStack = this.IncludeNestedStack; if (this.NotificationARNs != null) { context.NotificationARNs = new List(this.NotificationARNs); } context.OnStackFailure = this.OnStackFailure; if (this.Parameter != null) { context.Parameter = new List(this.Parameter); } if (this.ResourcesToImport != null) { context.ResourcesToImport = new List(this.ResourcesToImport); } if (this.ResourceType != null) { context.ResourceType = new List(this.ResourceType); } context.RoleARN = this.RoleARN; context.RollbackConfiguration = this.RollbackConfiguration; context.StackName = this.StackName; #if MODULAR if (this.StackName == null && ParameterWasBound(nameof(this.StackName))) { WriteWarning("You are passing $null as a value for parameter StackName which is marked as required. In case you believe this parameter was incorrectly marked as required, report this by opening an issue at https://github.com/aws/aws-tools-for-powershell/issues."); } #endif if (this.Tag != null) { context.Tag = new List(this.Tag); } context.TemplateBody = this.TemplateBody; context.TemplateURL = this.TemplateURL; context.UsePreviousTemplate = this.UsePreviousTemplate; // allow further manipulation of loaded context prior to processing PostExecutionContextLoad(context); var output = Execute(context) as CmdletOutput; ProcessOutput(output); } #region IExecutor Members public object Execute(ExecutorContext context) { var cmdletContext = context as CmdletContext; // create request var request = new Amazon.CloudFormation.Model.CreateChangeSetRequest(); if (cmdletContext.Capability != null) { request.Capabilities = cmdletContext.Capability; } if (cmdletContext.ChangeSetName != null) { request.ChangeSetName = cmdletContext.ChangeSetName; } if (cmdletContext.ChangeSetType != null) { request.ChangeSetType = cmdletContext.ChangeSetType; } if (cmdletContext.ClientToken != null) { request.ClientToken = cmdletContext.ClientToken; } if (cmdletContext.Description != null) { request.Description = cmdletContext.Description; } if (cmdletContext.IncludeNestedStack != null) { request.IncludeNestedStacks = cmdletContext.IncludeNestedStack.Value; } if (cmdletContext.NotificationARNs != null) { request.NotificationARNs = cmdletContext.NotificationARNs; } if (cmdletContext.OnStackFailure != null) { request.OnStackFailure = cmdletContext.OnStackFailure; } if (cmdletContext.Parameter != null) { request.Parameters = cmdletContext.Parameter; } if (cmdletContext.ResourcesToImport != null) { request.ResourcesToImport = cmdletContext.ResourcesToImport; } if (cmdletContext.ResourceType != null) { request.ResourceTypes = cmdletContext.ResourceType; } if (cmdletContext.RoleARN != null) { request.RoleARN = cmdletContext.RoleARN; } if (cmdletContext.RollbackConfiguration != null) { request.RollbackConfiguration = cmdletContext.RollbackConfiguration; } if (cmdletContext.StackName != null) { request.StackName = cmdletContext.StackName; } if (cmdletContext.Tag != null) { request.Tags = cmdletContext.Tag; } if (cmdletContext.TemplateBody != null) { request.TemplateBody = cmdletContext.TemplateBody; } if (cmdletContext.TemplateURL != null) { request.TemplateURL = cmdletContext.TemplateURL; } if (cmdletContext.UsePreviousTemplate != null) { request.UsePreviousTemplate = cmdletContext.UsePreviousTemplate.Value; } CmdletOutput output; // issue call var client = Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint); try { var response = CallAWSServiceOperation(client, request); object pipelineOutput = null; pipelineOutput = cmdletContext.Select(response, this); output = new CmdletOutput { PipelineOutput = pipelineOutput, ServiceResponse = response }; } catch (Exception e) { output = new CmdletOutput { ErrorResponse = e }; } return output; } public ExecutorContext CreateContext() { return new CmdletContext(); } #endregion #region AWS Service Operation Call private Amazon.CloudFormation.Model.CreateChangeSetResponse CallAWSServiceOperation(IAmazonCloudFormation client, Amazon.CloudFormation.Model.CreateChangeSetRequest request) { Utils.Common.WriteVerboseEndpointMessage(this, client.Config, "AWS CloudFormation", "CreateChangeSet"); try { #if DESKTOP return client.CreateChangeSet(request); #elif CORECLR return client.CreateChangeSetAsync(request).GetAwaiter().GetResult(); #else #error "Unknown build edition" #endif } catch (AmazonServiceException exc) { var webException = exc.InnerException as System.Net.WebException; if (webException != null) { throw new Exception(Utils.Common.FormatNameResolutionFailureMessage(client.Config, webException.Message), webException); } throw; } } #endregion internal partial class CmdletContext : ExecutorContext { public List Capability { get; set; } public System.String ChangeSetName { get; set; } public Amazon.CloudFormation.ChangeSetType ChangeSetType { get; set; } public System.String ClientToken { get; set; } public System.String Description { get; set; } public System.Boolean? IncludeNestedStack { get; set; } public List NotificationARNs { get; set; } public Amazon.CloudFormation.OnStackFailure OnStackFailure { get; set; } public List Parameter { get; set; } public List ResourcesToImport { get; set; } public List ResourceType { get; set; } public System.String RoleARN { get; set; } public Amazon.CloudFormation.Model.RollbackConfiguration RollbackConfiguration { get; set; } public System.String StackName { get; set; } public List Tag { get; set; } public System.String TemplateBody { get; set; } public System.String TemplateURL { get; set; } public System.Boolean? UsePreviousTemplate { get; set; } public System.Func Select { get; set; } = (response, cmdlet) => response.Id; } } }