コード例 #1
0
        private async Task <string> CreateChangeSet(DeployContext context, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var parameters = context.Parameters
                             .Select((entry) => new Parameter {
                ParameterKey = entry.Key, ParameterValue = entry.Value
            })
                             .ToList();

            var tags = context.Tags
                       .Select((entry) => new Tag {
                Key = entry.Key, Value = entry.Value
            })
                       .ToList();

            var request = new CreateChangeSetRequest
            {
                StackName     = context.StackName,
                ChangeSetName = context.ChangeSetName,
                ChangeSetType = await GetChangeSetType(context, cancellationToken),
                Capabilities  = context.Capabilities,
                TemplateURL   = context.TemplateURL,
                Parameters    = parameters,
                Tags          = tags,
            };

            var response = await cloudformation.CreateChangeSetAsync(request, cancellationToken);

            return(response.StackId);
        }
コード例 #2
0
        internal CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request)
        {
            var marshaller   = new CreateChangeSetRequestMarshaller();
            var unmarshaller = CreateChangeSetResponseUnmarshaller.Instance;

            return(Invoke <CreateChangeSetRequest, CreateChangeSetResponse>(request, marshaller, unmarshaller));
        }
コード例 #3
0
        /// <summary>
        /// Initiates the asynchronous execution of the CreateChangeSet operation.
        /// </summary>
        ///
        /// <param name="request">Container for the necessary parameters to execute the CreateChangeSet operation.</param>
        /// <param name="cancellationToken">
        ///     A cancellation token that can be used by other objects or threads to receive notice of cancellation.
        /// </param>
        /// <returns>The task object representing the asynchronous operation.</returns>
        public Task <CreateChangeSetResponse> CreateChangeSetAsync(CreateChangeSetRequest request, System.Threading.CancellationToken cancellationToken = default(CancellationToken))
        {
            var marshaller   = new CreateChangeSetRequestMarshaller();
            var unmarshaller = CreateChangeSetResponseUnmarshaller.Instance;

            return(InvokeAsync <CreateChangeSetRequest, CreateChangeSetResponse>(request, marshaller,
                                                                                 unmarshaller, cancellationToken));
        }
コード例 #4
0
 private async Task <RunningChangeSet> CreateChangeSet(CreateChangeSetRequest request)
 {
     try
     {
         return((await clientFactory.CreateChangeSetAsync(request))
                .Map(x => new RunningChangeSet(new StackArn(x.StackId), new ChangeSetArn(x.Id))));
     }
     catch (AmazonCloudFormationException ex) when(ex.ErrorCode == "AccessDenied")
     {
         throw new PermissionException(
                   @"The AWS account used to perform the operation does not have the required permissions to create the change set.\n" + "Please ensure the current user has the cloudformation:CreateChangeSet permission.\n" + ex.Message + "\n",
                   ex);
     }
 }
コード例 #5
0
 public void CreateCloudFormationOnAWS()
 {
     try
     {
         Log.Info(Program.LogPath, "Creating Cloud Information");
         var describeStacksRequest = new DescribeStacksRequest();
         var changeSetName         = "changeset" + Program.PostfixExpression;
         var changeSetType         = ChangeSetType.CREATE;
         if (CheckStackIsExist(CloudFormationClient, StackName))
         {
             changeSetType = ChangeSetType.UPDATE;
         }
         var createChangeSetRequest = new CreateChangeSetRequest
         {
             ChangeSetName = changeSetName,
             StackName     = StackName,
             //TemplateBody = ServerlessTemplateBody,
             TemplateURL   = TemplateUrl,
             ChangeSetType = changeSetType,
             Capabilities  = new List <string> {
                 "CAPABILITY_IAM"
             },
         };
         var createChangeSetResponse = CloudFormationClient.CreateChangeSet(createChangeSetRequest);
         WaitForChangeSet(CloudFormationClient, StackName, changeSetName);
         var executeChangeSetResponse = CloudFormationClient.ExecuteChangeSet(new ExecuteChangeSetRequest
         {
             ChangeSetName = changeSetName,
             StackName     = StackName,
         });
         WaitForStack(CloudFormationClient, StackName);
         var generatedStack = GetStack(CloudFormationClient, StackName);
         Log.Info(Program.LogPath, "Output URL is : " + generatedStack.Outputs.Find(x => x.OutputKey == "ApiURL").OutputValue);
         Log.Info(Program.LogPath, "Creating Cloud Information Finished");
     }
     catch (Exception ex)
     {
         Log.Error(Program.LogPath.FullName, "Creating Cloud Information  Error :   " + ex.Message);
     }
 }
コード例 #6
0
        private RunningChangeSet CreateChangeSet(CreateChangeSetRequest request)
        {
            try
            {
                return(clientFactory.CreateChangeSet(request)
                       .Map(x => new RunningChangeSet(new StackArn(x.StackId), new ChangeSetArn(x.Id))));
            }
            catch (AmazonCloudFormationException ex)
            {
                if (ex.ErrorCode == "AccessDenied")
                {
                    throw new PermissionException(
                              @"AWS-CLOUDFORMATION-ERROR-0017: The AWS account used to perform the operation does not have " +
                              "the required permissions to create the change set.\n" +
                              ex.Message + "\n" +
                              "For more information visit the [octopus docs](https://g.octopushq.com/AwsCloudFormationDeploy#aws-cloudformation-error-0017)");
                }

                throw new UnknownException(
                          "AWS-CLOUDFORMATION-ERROR-0018: An unrecognised exception was thrown while creating the CloudFormation change set.\n" +
                          "For more information visit https://g.octopushq.com/AwsCloudFormationDeploy#aws-cloudformation-error-0018",
                          ex);
            }
        }
コード例 #7
0
 public async Task <CreateChangeSetResponse> CreateChangeSetWithOptionsAsync(CreateChangeSetRequest request, AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime)
 {
     AlibabaCloud.TeaUtil.Common.ValidateModel(request);
     return(TeaModel.ToObject <CreateChangeSetResponse>(await DoRequestAsync("2015-09-01", "HTTPS", "POST", "AK", "/changeSets", null, request.Headers, null, runtime)));
 }
コード例 #8
0
        protected override async Task <bool> PerformActionAsync()
        {
            string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, CommonDefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
            string stackName       = this.GetStringValueOrDefault(this.StackName, LambdaDefinedCommandOptions.ARGUMENT_STACK_NAME, true);
            string s3Bucket        = this.GetStringValueOrDefault(this.S3Bucket, LambdaDefinedCommandOptions.ARGUMENT_S3_BUCKET, true);
            string s3Prefix        = this.GetStringValueOrDefault(this.S3Prefix, LambdaDefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
            string templatePath    = this.GetStringValueOrDefault(this.CloudFormationTemplate, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE, true);

            await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

            if (!Path.IsPathRooted(templatePath))
            {
                templatePath = Path.Combine(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation), templatePath);
            }

            if (!File.Exists(templatePath))
            {
                throw new LambdaToolsException($"Template file {templatePath} cannot be found.", LambdaToolsException.LambdaErrorCode.ServerlessTemplateNotFound);
            }

            // Read in the serverless template and update all the locations for Lambda functions to point to the app bundle that was just uploaded.
            string templateBody = File.ReadAllText(templatePath);

            // Process any template substitutions
            templateBody = LambdaUtilities.ProcessTemplateSubstitions(this.Logger, templateBody, this.GetKeyValuePairOrDefault(this.TemplateSubstitutions, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE_SUBSTITUTIONS, false), Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));


            var options = new DefaultLocationOption
            {
                Configuration       = this.GetStringValueOrDefault(this.Configuration, CommonDefinedCommandOptions.ARGUMENT_CONFIGURATION, false),
                TargetFramework     = this.GetStringValueOrDefault(this.TargetFramework, CommonDefinedCommandOptions.ARGUMENT_FRAMEWORK, false),
                MSBuildParameters   = this.GetStringValueOrDefault(this.MSBuildParameters, CommonDefinedCommandOptions.ARGUMENT_MSBUILD_PARAMETERS, false),
                DisableVersionCheck = this.GetBoolValueOrDefault(this.DisableVersionCheck, LambdaDefinedCommandOptions.ARGUMENT_DISABLE_VERSION_CHECK, false).GetValueOrDefault(),
                Package             = this.GetStringValueOrDefault(this.Package, LambdaDefinedCommandOptions.ARGUMENT_PACKAGE, false)
            };

            var templateProcessor = new TemplateProcessorManager(this.Logger, this.S3Client, s3Bucket, s3Prefix, options);

            templateBody = await templateProcessor.TransformTemplateAsync(templatePath, templateBody);

            // Upload the template to S3 instead of sending it straight to CloudFormation to avoid the size limitation
            string s3KeyTemplate;

            using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(templateBody)))
            {
                s3KeyTemplate = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, stackName + "-" + Path.GetFileName(templatePath), stream);
            }

            var existingStack = await GetExistingStackAsync(stackName);

            this.Logger.WriteLine("Found existing stack: " + (existingStack != null));
            var changeSetName = "Lambda-Tools-" + DateTime.Now.Ticks;

            List <Tag> tagList = null;
            {
                var tags = this.GetKeyValuePairOrDefault(this.Tags, LambdaDefinedCommandOptions.ARGUMENT_FUNCTION_TAGS, false);
                if (tags != null)
                {
                    tagList = new List <Tag>();
                    foreach (var kvp in tags)
                    {
                        tagList.Add(new Tag {
                            Key = kvp.Key, Value = kvp.Value
                        });
                    }
                }
            }

            // Determine if the stack is in a good state to be updated.
            ChangeSetType changeSetType;

            if (existingStack == null || existingStack.StackStatus == StackStatus.REVIEW_IN_PROGRESS || existingStack.StackStatus == StackStatus.DELETE_COMPLETE)
            {
                changeSetType = ChangeSetType.CREATE;
            }
            // If the status was ROLLBACK_COMPLETE that means the stack failed on initial creation
            // and the resources were cleaned up. It is safe to delete the stack so we can recreate it.
            else if (existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
            {
                await DeleteRollbackCompleteStackAsync(existingStack);

                changeSetType = ChangeSetType.CREATE;
            }
            // If the status was ROLLBACK_IN_PROGRESS that means the initial creation is failing.
            // Wait to see if it goes into ROLLBACK_COMPLETE status meaning everything got cleaned up and then delete it.
            else if (existingStack.StackStatus == StackStatus.ROLLBACK_IN_PROGRESS)
            {
                existingStack = await WaitForNoLongerInProgress(existingStack.StackName);

                if (existingStack != null && existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                {
                    await DeleteRollbackCompleteStackAsync(existingStack);
                }

                changeSetType = ChangeSetType.CREATE;
            }
            // If the status was DELETE_IN_PROGRESS then just wait for delete to complete
            else if (existingStack.StackStatus == StackStatus.DELETE_IN_PROGRESS)
            {
                await WaitForNoLongerInProgress(existingStack.StackName);

                changeSetType = ChangeSetType.CREATE;
            }
            // The Stack state is in a normal state and ready to be updated.
            else if (existingStack.StackStatus == StackStatus.CREATE_COMPLETE ||
                     existingStack.StackStatus == StackStatus.UPDATE_COMPLETE ||
                     existingStack.StackStatus == StackStatus.UPDATE_ROLLBACK_COMPLETE)
            {
                changeSetType = ChangeSetType.UPDATE;
                if (tagList == null)
                {
                    tagList = existingStack.Tags;
                }
            }
            // All other states means the Stack is in an inconsistent state.
            else
            {
                this.Logger.WriteLine($"The stack's current state of {existingStack.StackStatus} is invalid for updating");
                return(false);
            }

            CreateChangeSetResponse changeSetResponse;

            try
            {
                var definedParameters  = LambdaUtilities.GetTemplateDefinedParameters(templateBody);
                var templateParameters = GetTemplateParameters(changeSetType == ChangeSetType.UPDATE ? existingStack : null, definedParameters);
                if (templateParameters != null && templateParameters.Any())
                {
                    var setParameters = templateParameters.Where(x => !x.UsePreviousValue);
                    // ReSharper disable once PossibleMultipleEnumeration
                    if (setParameters.Any())
                    {
                        this.Logger.WriteLine("Template Parameters Applied:");
                        foreach (var parameter in setParameters)
                        {
                            Tuple <string, bool> dp = null;
                            if (definedParameters != null)
                            {
                                dp = definedParameters.FirstOrDefault(x => string.Equals(x.Item1, parameter.ParameterKey));
                            }

                            if (dp != null && dp.Item2)
                            {
                                this.Logger.WriteLine($"\t{parameter.ParameterKey}: ****");
                            }
                            else
                            {
                                this.Logger.WriteLine($"\t{parameter.ParameterKey}: {parameter.ParameterValue}");
                            }
                        }
                    }
                }

                var capabilities        = new List <string>();
                var disabledCapabilties = GetStringValuesOrDefault(this.DisabledCapabilities, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_DISABLE_CAPABILITIES, false);

                if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                {
                    capabilities.Add("CAPABILITY_IAM");
                }
                if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_NAMED_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                {
                    capabilities.Add("CAPABILITY_NAMED_IAM");
                }

                if (tagList == null)
                {
                    tagList = new List <Tag>();
                }

                if (tagList.FirstOrDefault(x => string.Equals(x.Key, LambdaConstants.SERVERLESS_TAG_NAME)) == null)
                {
                    tagList.Add(new Tag {
                        Key = LambdaConstants.SERVERLESS_TAG_NAME, Value = "true"
                    });
                }

                var changeSetRequest = new CreateChangeSetRequest
                {
                    StackName     = stackName,
                    Parameters    = templateParameters,
                    ChangeSetName = changeSetName,
                    ChangeSetType = changeSetType,
                    Capabilities  = capabilities,
                    RoleARN       = this.GetStringValueOrDefault(this.CloudFormationRole, LambdaDefinedCommandOptions.ARGUMENT_CLOUDFORMATION_ROLE, false),
                    Tags          = tagList
                };

                if (new FileInfo(templatePath).Length < LambdaConstants.MAX_TEMPLATE_BODY_IN_REQUEST_SIZE)
                {
                    changeSetRequest.TemplateBody = templateBody;
                }
                else
                {
                    changeSetRequest.TemplateURL = this.S3Client.GetPreSignedURL(new S3.Model.GetPreSignedUrlRequest {
                        BucketName = s3Bucket, Key = s3KeyTemplate, Expires = DateTime.Now.AddHours(1)
                    });
                }

                // Create the change set which performs the transformation on the Serverless resources in the template.
                changeSetResponse = await this.CloudFormationClient.CreateChangeSetAsync(changeSetRequest);


                this.Logger.WriteLine("CloudFormation change set created");
            }
            catch (LambdaToolsException)
            {
                throw;
            }
            catch (Exception e)
            {
                throw new LambdaToolsException($"Error creating CloudFormation change set: {e.Message}", LambdaToolsException.LambdaErrorCode.CloudFormationCreateStack, e);
            }

            // The change set can take a few seconds to be reviewed and be ready to be executed.
            if (!await WaitForChangeSetBeingAvailableAsync(changeSetResponse.Id))
            {
                return(false);
            }

            var executeChangeSetRequest = new ExecuteChangeSetRequest
            {
                StackName     = stackName,
                ChangeSetName = changeSetResponse.Id
            };

            // Execute the change set.
            DateTime timeChangeSetExecuted = DateTime.Now;

            try
            {
                await this.CloudFormationClient.ExecuteChangeSetAsync(executeChangeSetRequest);

                if (changeSetType == ChangeSetType.CREATE)
                {
                    this.Logger.WriteLine($"Created CloudFormation stack {stackName}");
                }
                else
                {
                    this.Logger.WriteLine($"Initiated CloudFormation stack update on {stackName}");
                }
            }
            catch (Exception e)
            {
                throw new LambdaToolsException($"Error executing CloudFormation change set: {e.Message}", LambdaToolsException.LambdaErrorCode.CloudFormationCreateChangeSet, e);
            }

            // Wait for the stack to finish unless the user opts out of waiting. The VS Toolkit opts out and
            // instead shows the stack view in the IDE, enabling the user to view progress.
            var shouldWait = GetBoolValueOrDefault(this.WaitForStackToComplete, LambdaDefinedCommandOptions.ARGUMENT_STACK_WAIT, false);

            if (!shouldWait.HasValue || shouldWait.Value)
            {
                var updatedStack = await WaitStackToCompleteAsync(stackName, timeChangeSetExecuted);

                if (updatedStack.StackStatus == StackStatus.CREATE_COMPLETE || updatedStack.StackStatus == StackStatus.UPDATE_COMPLETE)
                {
                    this.Logger.WriteLine($"Stack finished updating with status: {updatedStack.StackStatus}");

                    // Display the output parameters.
                    DisplayOutputs(updatedStack);
                }
                else
                {
                    this.Logger.WriteLine($"Stack update failed with status: {updatedStack.StackStatus} ({updatedStack.StackStatusReason})");
                    return(false);
                }
            }

            return(true);
        }
コード例 #9
0
 public static CreateChangeSetResponse CreateChangeSet(this Func <IAmazonCloudFormation> factory, CreateChangeSetRequest request)
 {
     return(factory().Map(client => client.CreateChangeSet(request)));
 }
コード例 #10
0
 public static Task <CreateChangeSetResponse> CreateChangeSetAsync(this Func <IAmazonCloudFormation> factory, CreateChangeSetRequest request)
 {
     return(factory().CreateChangeSetAsync(request));
 }
コード例 #11
0
 /// <summary>
 ///  创建更改集
 /// </summary>
 /// <param name="request">请求参数信息</param>
 /// <returns>请求结果信息</returns>
 public async Task <CreateChangeSetResponse> CreateChangeSet(CreateChangeSetRequest request)
 {
     return(await new CreateChangeSetExecutor().Client(this).Execute <CreateChangeSetResponse, CreateChangeSetResult, CreateChangeSetRequest>(request).ConfigureAwait(false));
 }
コード例 #12
0
 /// <summary>
 ///  创建更改集
 /// </summary>
 /// <param name="request">请求参数信息</param>
 /// <returns>请求结果信息</returns>
 public CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request)
 {
     return(new CreateChangeSetExecutor().Client(this).Execute <CreateChangeSetResponse, CreateChangeSetResult, CreateChangeSetRequest>(request));
 }
コード例 #13
0
ファイル: Cloudformation.cs プロジェクト: ziphrax/Humidifier
        public static async Task <DeployStackResult> DeployStackAsync(ILogger log, IAmazonCloudFormation cloudformation, long ticks, string stackName, List <Tag> tags, Dictionary <string, string> parameters, string templateBody = null, Uri templateUrl = null, string roleArn = null)
        {
            log.Information("Checking stack: {stackName}", stackName);

            Stack existingStack = await GetExistingStackAsync(cloudformation, stackName).ConfigureAwait(false);

            log.Information("Found existing stack: " + (existingStack != null));

            var changeSetName = stackName + "-" + ticks;
            var param         = parameters.Select(x => new Parameter {
                ParameterKey = x.Key, ParameterValue = x.Value
            }).ToList();

            // Determine if the stack is in a good state to be updated.
            ChangeSetType changeSetType;

            if (existingStack == null || existingStack.StackStatus == StackStatus.REVIEW_IN_PROGRESS || existingStack.StackStatus == StackStatus.DELETE_COMPLETE)
            {
                changeSetType = ChangeSetType.CREATE;
            }
            // If the state was ROLLBACK_COMPLETE that means the stack failed on initial creation and the resources where cleaned up.
            // It is safe to delete the stack so we can recreate it.
            else if (existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
            {
                await DeleteRollbackCompleteStackAsync(log, cloudformation, existingStack).ConfigureAwait(false);

                changeSetType = ChangeSetType.CREATE;
            }
            // If the status was ROLLBACK_IN_PROGRESS that means the initial creation is failing.
            // Wait to see if it goes into ROLLBACK_COMPLETE status meaning everything got cleaned up and then delete it.
            else if (existingStack.StackStatus == StackStatus.ROLLBACK_IN_PROGRESS)
            {
                existingStack = await WaitForNoLongerInProgress(log, cloudformation, existingStack.StackName).ConfigureAwait(false);

                if (existingStack != null && existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                {
                    await DeleteRollbackCompleteStackAsync(log, cloudformation, existingStack).ConfigureAwait(false);
                }

                changeSetType = ChangeSetType.CREATE;
            }
            // If the status was DELETE_IN_PROGRESS then just wait for delete to complete
            else if (existingStack.StackStatus == StackStatus.DELETE_IN_PROGRESS)
            {
                await WaitForNoLongerInProgress(log, cloudformation, existingStack.StackName).ConfigureAwait(false);

                changeSetType = ChangeSetType.CREATE;
            }
            // The Stack state is in a normal state and ready to be updated.
            else if (existingStack.StackStatus == StackStatus.CREATE_COMPLETE ||
                     existingStack.StackStatus == StackStatus.UPDATE_COMPLETE ||
                     existingStack.StackStatus == StackStatus.UPDATE_ROLLBACK_COMPLETE)
            {
                changeSetType = ChangeSetType.UPDATE;
            }
            // All other states means the Stack is in an inconsistent state.
            else
            {
                log.Error($"The stack's current state of {existingStack.StackStatus} is invalid for updating");
                return(DeployStackResult.Failed);
            }

            CreateChangeSetResponse changeSetResponse;

            try
            {
                var changeSetRequest = new CreateChangeSetRequest
                {
                    StackName     = stackName,
                    ChangeSetName = changeSetName,
                    ChangeSetType = changeSetType,
                    Capabilities  = new List <string> {
                        CAPABILITY_NAMED_IAM
                    },
                    Tags       = tags,
                    Parameters = param,
                    RoleARN    = roleArn
                };

                if (templateUrl != null)
                {
                    changeSetRequest.TemplateURL = templateUrl.ToString();
                }
                else
                {
                    changeSetRequest.TemplateBody = templateBody;
                }

                // Create the change set which performs the transformation on the Serverless resources in the template.
                changeSetResponse = await cloudformation.CreateChangeSetAsync(changeSetRequest).ConfigureAwait(false);

                log.Information("CloudFormation change set created. StackName: {stackName}, ChangeSetName: {changeSetName}", stackName, changeSetName);
            }
            catch (Exception e)
            {
                log.Error(e, "Error creating cloudformation change set");
                throw;
            }

            // The change set can take a few seconds to be reviewed and be ready to be executed.
            DeployStackResult waitResult = await WaitForChangeSetBeingAvailableAsync(log, cloudformation, changeSetResponse.Id).ConfigureAwait(false);

            if (waitResult == DeployStackResult.NoChanges || waitResult == DeployStackResult.Failed)
            {
                return(waitResult);
            }

            var executeChangeSetRequest = new ExecuteChangeSetRequest
            {
                StackName     = stackName,
                ChangeSetName = changeSetResponse.Id
            };

            // Execute the change set.
            var timeChangeSetExecuted = DateTime.Now;

            try
            {
                await cloudformation.ExecuteChangeSetAsync(executeChangeSetRequest).ConfigureAwait(false);

                if (changeSetType == ChangeSetType.CREATE)
                {
                    log.Information($"Created CloudFormation stack {stackName}");
                }
                else
                {
                    log.Information($"Initiated CloudFormation stack update on {stackName}");
                }
            }
            catch (Exception e)
            {
                log.Error(e, "Error executing cloudformation change set");
                throw;
            }

            // Wait for the stack to finish
            var updatedStack = await WaitStackToCompleteAsync(log, cloudformation, stackName, timeChangeSetExecuted).ConfigureAwait(false);

            if (updatedStack.StackStatus == StackStatus.CREATE_COMPLETE || updatedStack.StackStatus == StackStatus.UPDATE_COMPLETE)
            {
                log.Information($"Stack finished updating with status: {updatedStack.StackStatus}");

                // Display the output parameters.
                DisplayOutputs(log, updatedStack);
            }
            else
            {
                log.Error($"Stack update failed with status: {updatedStack.StackStatus} ({updatedStack.StackStatusReason})");
                return(DeployStackResult.Failed);
            }

            return(DeployStackResult.Ok);
        }
コード例 #14
0
        static void ApplyCloudFormationChangeSetExample()
        {
            string bucket_Name  = QSS3BucketName;
            string templateName = QSS3KeyPrefix + TdwUtils.cfClassPathBastionChangeSet.Replace("tdw_cf_template\\", "");
            string stack_name   = QSS3KeyPrefix + TdwUtils.cfClassPathBastion.Replace("tdw_cf_template\\", "");

            stack_name = stack_name.Replace("-", "");
            stack_name = stack_name.Replace(".template", "");
            AmazonS3Client s3Client = new AmazonS3Client();

            Amazon.CloudFormation.AmazonCloudFormationClient cfClient = new AmazonCloudFormationClient();

            GetObjectRequest getObjectRequest = new GetObjectRequest
            {
                BucketName = bucket_Name,
                Key        = templateName,
            };

            string data = null;

            using (GetObjectResponse getObjectResponse = s3Client.GetObject(getObjectRequest))
            {
                using (var stream = getObjectResponse.ResponseStream)
                    using (var reader = new StreamReader(stream))
                    {
                        data = reader.ReadToEnd();
                    }
            }

            List <string> CfCapabilities = new List <string>();

            CfCapabilities.Add("CAPABILITY_IAM");

            List <Amazon.CloudFormation.Model.Parameter> parameters = new List <Amazon.CloudFormation.Model.Parameter>();

            parameters.Add(new Parameter
            {
                ParameterKey   = "pEnvTag",
                ParameterValue = "development"
            });

            List <string> notificationArns = new List <string>();

            notificationArns.Add("aws:sns:eu-west-1:009837347446:tdwcftdevmainbastion-LoggingTemplate-1E3KD8XDHOSTY-rSecurityAlarmTopic-1TNN0GI7819UM");

            List <string> resourceTypes = new List <string>();

            resourceTypes.Add("AWS::*");

            List <Amazon.CloudFormation.Model.Tag> tagList = new List <Amazon.CloudFormation.Model.Tag>();

            tagList.Add(new Amazon.CloudFormation.Model.Tag()
            {
                Key = "environment", Value = "development"
            });

            CreateChangeSetRequest cfReq = new CreateChangeSetRequest()
            {
                Capabilities  = CfCapabilities,
                ChangeSetName = "tdwv010001",
                ChangeSetType = ChangeSetType.UPDATE,
                ClientToken   = "fromappsettingsv010001",
                Description   = "Adding kinesis template to tdw stack and parameterizing env parameter",
                //NotificationARNs = notificationArns,
                Parameters = parameters,
                //ResourceTypes = resourceTypes,
                //RoleARN
                StackName    = stack_name,
                Tags         = tagList,
                TemplateBody = data
                               //UsePreviousTemplate = true
            };

            CreateChangeSetResponse cfResp = cfClient.CreateChangeSet(cfReq);
        }
コード例 #15
0
 public CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request)
 {
     AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
     return(CreateChangeSetWithOptions(request, runtime));
 }
コード例 #16
0
 public async Task <CreateChangeSetResponse> CreateChangeSetAsync(CreateChangeSetRequest request)
 {
     AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions();
     return(await CreateChangeSetWithOptionsAsync(request, runtime));
 }
コード例 #17
0
        /// <summary>Updates a stack.</summary>
        /// <param name="confirmationFunc">
        /// A callback that should return <c>true</c> or <c>false</c> as to whether to whether the caller confirms the given change set and therefore to continue with the stack update.
        /// If this parameter is <c>null</c>, then <c>true</c> is assumed.
        /// </param>
        /// <exception cref="StackOperationException">Change set creation failed for reasons other than 'no change'</exception>
        /// <returns>Operation result.</returns>
        public async Task <CloudFormationResult> UpdateStackAsync(Func <DescribeChangeSetResponse, bool> confirmationFunc)
        {
            var stack = await this.stackOperations.GetStackAsync(this.stackName);

            // Check stack state first
            var operationalState = await this.stackOperations.GetStackOperationalStateAsync(stack.StackId);

            // ReSharper disable once SwitchStatementMissingSomeEnumCasesNoDefault
            switch (operationalState)
            {
            case StackOperationalState.Deleting:
            case StackOperationalState.DeleteFailed:

                throw new StackOperationException(stack, operationalState);

            case StackOperationalState.Broken:

                this.context.Logger.LogWarning("Stack is in a failed state from previous operation. Update may fail.");
                break;

            case StackOperationalState.Busy:

                if (this.waitForInProgressUpdate)
                {
                    // Track stack until update completes
                    // Wait for previous update to complete
                    // Time from which to start polling events
                    this.lastEventTime = await this.GetMostRecentStackEvent(stack.StackId);

                    this.context.Logger.LogInformation(
                        "Stack {0} is currently being updated by another process",
                        stack.StackName);
                    this.context.Logger.LogInformation("Following its progress while waiting...\n");
                    stack = await this.WaitStackOperationAsync(stack.StackId, false);

                    this.context.Logger.LogInformation(string.Empty);

                    var currentState = await this.stackOperations.GetStackOperationalStateAsync(stack.StackId);

                    if (currentState != StackOperationalState.Ready)
                    {
                        throw new StackOperationException(stack, currentState);
                    }
                }
                else
                {
                    throw new StackOperationException(stack, StackOperationalState.Busy);
                }

                break;
            }

            // If we get here, stack is in Ready state
            var changeSetName     = CreateChangeSetName();
            var resourcesToImport = await this.GetResourcesToImportAsync();

            var changeSetRequest = new CreateChangeSetRequest
            {
                ChangeSetName         = changeSetName,
                ChangeSetType         = resourcesToImport != null ? ChangeSetType.IMPORT : ChangeSetType.UPDATE,
                Parameters            = this.GetStackParametersForUpdate(this.templateResolver, stack),
                Capabilities          = this.capabilities.Select(c => c.Value).ToList(),
                StackName             = stack.StackId,
                ClientToken           = this.clientToken,
                RoleARN               = this.roleArn,
                NotificationARNs      = this.notificationARNs,
                RollbackConfiguration = this.rollbackConfiguration,
                ResourceTypes         = this.resourceType,
                Tags = this.tags,
                ResourcesToImport = resourcesToImport,
                TemplateBody      = this.templateResolver.ArtifactContent,
                TemplateURL       =
                    this.usePreviousTemplate ? null : this.templateResolver.ArtifactUrl,
                UsePreviousTemplate = this.usePreviousTemplate,
                IncludeNestedStacks = this.includeNestedStacks
            };

            this.context.Logger.LogInformation($"Creating changeset {changeSetName} for {this.GetStackNameWithDescription()}");

            if (this.includeNestedStacks)
            {
                this.context.Logger.LogInformation("IncludeNestedChangesets is enabled. This may take some time...");
            }

            var changesetArn = (await this.client.CreateChangeSetAsync(changeSetRequest)).Id;

            var stat = ChangeSetStatus.CREATE_PENDING;
            var describeChangeSetRequest = new DescribeChangeSetRequest {
                ChangeSetName = changesetArn
            };

            DescribeChangeSetResponse describeChangeSetResponse = null;

            while (!(stat == ChangeSetStatus.CREATE_COMPLETE || stat == ChangeSetStatus.FAILED))
            {
                Thread.Sleep(this.waitPollTime / 2);
                describeChangeSetResponse = await this.client.DescribeChangeSetAsync(describeChangeSetRequest);

                stat = describeChangeSetResponse.Status;
            }

            if (stat == ChangeSetStatus.FAILED)
            {
                // ReSharper disable once PossibleNullReferenceException - we will go round the above loop at least once
                var reason = describeChangeSetResponse.StatusReason;

                if (reason.Contains("Access Denied") && this.usePreviousTemplate)
                {
                    // Likely that lifecycle policy has removed the previous template.
                    throw new
                          StackOperationException("Unable to create changeset: It is probable that the template has been explicitly deleted or removed by lifecycle policy on your bucket. Please retry specifying the path to the template file");
                }

                if (!NoChangeMessages.Any(msg => reason.StartsWith(msg)))
                {
                    throw new StackOperationException($"Unable to create changeset: {reason}");
                }

                this.context.Logger.LogInformation("No changes to stack were detected.");

                if (this.deleteNoopChangeSet)
                {
                    await this.client.DeleteChangeSetAsync(
                        new DeleteChangeSetRequest { ChangeSetName = changesetArn });

                    this.context.Logger.LogInformation($"Deleted changeset {changeSetName}");
                }

                return(new CloudFormationResult
                {
                    ChangesetResponse = this.deleteNoopChangeSet ? null : describeChangeSetResponse,
                    StackArn = stack.StackId,
                    StackOperationResult = StackOperationResult.NoChange
                });
            }

            // If we get here, emit details, then apply the changeset.
            // ReSharper disable once PossibleNullReferenceException - we will go round the above loop at least once
            if (this.includeNestedStacks)
            {
                // Base stack
                this.context.Logger.LogInformation($"Root Stack: {this.stackName}");
                this.context.Logger.LogChangeset(describeChangeSetResponse);

                // Walk all nested stacks and emit changes for each
                await EmitNestedStackChangesets(describeChangeSetResponse);
            }
            else
            {
                this.context.Logger.LogChangeset(describeChangeSetResponse);
            }

            if (this.changesetOnly)
            {
                this.context.Logger.LogInformation(
                    // ReSharper disable once PossibleNullReferenceException - 'response' cannot be null. DescribeChangeSetAsync has been called at least once to make it here.
                    $"Changeset {describeChangeSetResponse.ChangeSetName} created for stack {stack.StackName}");
                this.context.Logger.LogInformation("Not updating stack since CreateChangesetOnly = true");
                return(new CloudFormationResult
                {
                    ChangesetResponse = describeChangeSetResponse,
                    StackArn = stack.StackId,
                    StackOperationResult = StackOperationResult.NoChange
                });
            }

            if (confirmationFunc != null)
            {
                // Confirm the changeset before proceeding
                if (!confirmationFunc(describeChangeSetResponse))
                {
                    return(new CloudFormationResult
                    {
                        ChangesetResponse = describeChangeSetResponse,
                        StackArn = stack.StackId,
                        StackOperationResult = StackOperationResult.NoChange
                    });
                }
            }

            // Check nobody else has jumped in before us
            var currentState2 = await this.stackOperations.GetStackOperationalStateAsync(stack.StackId);

            if (currentState2 != StackOperationalState.Ready)
            {
                throw new StackOperationException(stack, currentState2);
            }

            // Time from which to start polling events
            this.lastEventTime = await this.GetMostRecentStackEvent(stack.StackId);

            this.context.Logger.LogInformation($"Updating {this.GetStackNameWithDescription()}\n");

            if (resourcesToImport != null)
            {
                // Have to do this by changeset
                await this.client.ExecuteChangeSetAsync(new ExecuteChangeSetRequest { ChangeSetName = changesetArn });
            }
            else
            {
                await this.client.UpdateStackAsync(await this.GetUpdateRequestWithPolicyFromChangesetRequestAsync(changeSetRequest));
            }

            if (this.followOperation)
            {
                await this.WaitStackOperationAsync(stack.StackId, true);

                return(new CloudFormationResult
                {
                    ChangesetResponse = describeChangeSetResponse,
                    StackArn = stack.StackId,
                    StackOperationResult = StackOperationResult.StackUpdated
                });
            }

            return(new CloudFormationResult
            {
                ChangesetResponse = describeChangeSetResponse,
                StackArn = stack.StackId,
                StackOperationResult = StackOperationResult.StackUpdateInProgress
            });

            async Task EmitNestedStackChangesets(DescribeChangeSetResponse parentChangeSetResponse)
            {
                // Recursively discover nested stacks and emit changesets for each
                foreach (var nested in parentChangeSetResponse.Changes.Where(
                             c => c.ResourceChange.ResourceType == "AWS::CloudFormation::Stack"))
                {
                    // Locate nested stack's changeset. It's parent ID will be set to the ID in parentChangeSetResponse
                    var summary = (await this.client.ListChangeSetsAsync(
                                       new ListChangeSetsRequest
                    {
                        StackName = nested.ResourceChange.PhysicalResourceId
                    })).Summaries.First(
                        s => s.ParentChangeSetId == parentChangeSetResponse.ChangeSetId);

                    var nestedResponse = await this.client.DescribeChangeSetAsync(
                        new DescribeChangeSetRequest
                    {
                        ChangeSetName = summary.ChangeSetName,
                        StackName     = nested.ResourceChange.PhysicalResourceId
                    });

                    this.context.Logger.LogInformation($"Nested Stack: {nested.ResourceChange.LogicalResourceId}");
                    this.context.Logger.LogChangeset(nestedResponse);
                    await EmitNestedStackChangesets(nestedResponse);
                }
            }
        }
コード例 #18
0
        public override async Task <bool> ExecuteAsync()
        {
            try
            {
                string projectLocation = this.GetStringValueOrDefault(this.ProjectLocation, DefinedCommandOptions.ARGUMENT_PROJECT_LOCATION, false);
                string stackName       = this.GetStringValueOrDefault(this.StackName, DefinedCommandOptions.ARGUMENT_STACK_NAME, true);
                string s3Bucket        = this.GetStringValueOrDefault(this.S3Bucket, DefinedCommandOptions.ARGUMENT_S3_BUCKET, true);
                string s3Prefix        = this.GetStringValueOrDefault(this.S3Prefix, DefinedCommandOptions.ARGUMENT_S3_PREFIX, false);
                string templatePath    = this.GetStringValueOrDefault(this.CloudFormationTemplate, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE, true);

                await Utilities.ValidateBucketRegionAsync(this.S3Client, s3Bucket);

                if (!Path.IsPathRooted(templatePath))
                {
                    templatePath = Path.Combine(Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation), templatePath);
                }

                if (!File.Exists(templatePath))
                {
                    throw new LambdaToolsException($"Template file {templatePath} cannot be found.", LambdaToolsException.ErrorCode.ServerlessTemplateNotFound);
                }


                // Build and bundle up the users project.
                string publishLocation;
                string zipArchivePath = null;
                string package        = this.GetStringValueOrDefault(this.Package, DefinedCommandOptions.ARGUMENT_PACKAGE, false);
                if (string.IsNullOrEmpty(package))
                {
                    string configuration   = this.GetStringValueOrDefault(this.Configuration, DefinedCommandOptions.ARGUMENT_CONFIGURATION, true);
                    string targetFramework = this.GetStringValueOrDefault(this.TargetFramework, DefinedCommandOptions.ARGUMENT_FRAMEWORK, true);
                    LambdaPackager.CreateApplicationBundle(this.DefaultConfig, this.Logger, this.WorkingDirectory, projectLocation, configuration, targetFramework, out publishLocation, ref zipArchivePath);
                    if (string.IsNullOrEmpty(zipArchivePath))
                    {
                        return(false);
                    }
                }
                else
                {
                    if (!File.Exists(package))
                    {
                        throw new LambdaToolsException($"Package {package} does not exist", LambdaToolsException.ErrorCode.InvalidPackage);
                    }
                    if (!string.Equals(Path.GetExtension(package), ".zip", StringComparison.OrdinalIgnoreCase))
                    {
                        throw new LambdaToolsException($"Package {package} must be a zip file", LambdaToolsException.ErrorCode.InvalidPackage);
                    }

                    this.Logger.WriteLine($"Skipping compilation and using precompiled package {package}");
                    zipArchivePath = package;
                }


                // Upload the app bundle to S3
                string s3KeyApplicationBundle;
                using (var stream = new MemoryStream(File.ReadAllBytes(zipArchivePath)))
                {
                    s3KeyApplicationBundle = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, stackName, stream);
                }

                // Read in the serverless template and update all the locations for Lambda functions to point to the app bundle that was just uploaded.
                string templateBody = File.ReadAllText(templatePath);

                // Process any template substitutions
                templateBody = Utilities.ProcessTemplateSubstitions(this.Logger, templateBody, this.GetKeyValuePairOrDefault(this.TemplateSubstitutions, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_TEMPLATE_SUBSTITUTIONS, false), Utilities.DetermineProjectLocation(this.WorkingDirectory, projectLocation));

                templateBody = UpdateCodeLocationInTemplate(templateBody, s3Bucket, s3KeyApplicationBundle);

                // Upload the template to S3 instead of sending it straight to CloudFormation to avoid the size limitation
                string s3KeyTemplate;
                using (var stream = new MemoryStream(System.Text.Encoding.UTF8.GetBytes(templateBody)))
                {
                    s3KeyTemplate = await Utilities.UploadToS3Async(this.Logger, this.S3Client, s3Bucket, s3Prefix, stackName + "-" + Path.GetFileName(templatePath), stream);
                }

                var existingStack = await GetExistingStackAsync(stackName);

                this.Logger.WriteLine("Found existing stack: " + (existingStack != null));
                var changeSetName = "Lambda-Tools-" + DateTime.Now.Ticks;

                // Determine if the stack is in a good state to be updated.
                ChangeSetType changeSetType;
                if (existingStack == null || existingStack.StackStatus == StackStatus.REVIEW_IN_PROGRESS || existingStack.StackStatus == StackStatus.DELETE_COMPLETE)
                {
                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was ROLLBACK_COMPLETE that means the stack failed on initial creation
                // and the resources were cleaned up. It is safe to delete the stack so we can recreate it.
                else if (existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                {
                    await DeleteRollbackCompleteStackAsync(existingStack);

                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was ROLLBACK_IN_PROGRESS that means the initial creation is failing.
                // Wait to see if it goes into ROLLBACK_COMPLETE status meaning everything got cleaned up and then delete it.
                else if (existingStack.StackStatus == StackStatus.ROLLBACK_IN_PROGRESS)
                {
                    existingStack = await WaitForNoLongerInProgress(existingStack.StackName);

                    if (existingStack != null && existingStack.StackStatus == StackStatus.ROLLBACK_COMPLETE)
                    {
                        await DeleteRollbackCompleteStackAsync(existingStack);
                    }

                    changeSetType = ChangeSetType.CREATE;
                }
                // If the status was DELETE_IN_PROGRESS then just wait for delete to complete
                else if (existingStack.StackStatus == StackStatus.DELETE_IN_PROGRESS)
                {
                    await WaitForNoLongerInProgress(existingStack.StackName);

                    changeSetType = ChangeSetType.CREATE;
                }
                // The Stack state is in a normal state and ready to be updated.
                else if (existingStack.StackStatus == StackStatus.CREATE_COMPLETE ||
                         existingStack.StackStatus == StackStatus.UPDATE_COMPLETE ||
                         existingStack.StackStatus == StackStatus.UPDATE_ROLLBACK_COMPLETE)
                {
                    changeSetType = ChangeSetType.UPDATE;
                }
                // All other states means the Stack is in an inconsistent state.
                else
                {
                    this.Logger.WriteLine($"The stack's current state of {existingStack.StackStatus} is invalid for updating");
                    return(false);
                }

                CreateChangeSetResponse changeSetResponse;
                try
                {
                    var templateParameters = GetTemplateParameters(changeSetType == ChangeSetType.UPDATE ? existingStack : null);
                    if (templateParameters?.Count > 0)
                    {
                        var setParameters = templateParameters.Where(x => !x.UsePreviousValue);
                        if (setParameters?.Count() > 0)
                        {
                            this.Logger.WriteLine("Template Parameters Applied:");
                            foreach (var parameter in setParameters)
                            {
                                this.Logger.WriteLine($"\t{parameter.ParameterKey}: {parameter.ParameterValue}");
                            }
                        }
                    }

                    var capabilities        = new List <string>();
                    var disabledCapabilties = GetStringValuesOrDefault(this.DisabledCapabilities, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_DISABLE_CAPABILITIES, false);

                    if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                    {
                        capabilities.Add("CAPABILITY_IAM");
                    }
                    if (disabledCapabilties?.FirstOrDefault(x => string.Equals(x, "CAPABILITY_NAMED_IAM", StringComparison.OrdinalIgnoreCase)) == null)
                    {
                        capabilities.Add("CAPABILITY_NAMED_IAM");
                    }

                    var changeSetRequest = new CreateChangeSetRequest
                    {
                        StackName     = stackName,
                        Parameters    = templateParameters,
                        ChangeSetName = changeSetName,
                        ChangeSetType = changeSetType,
                        Capabilities  = capabilities,
                        RoleARN       = this.GetStringValueOrDefault(this.CloudFormationRole, DefinedCommandOptions.ARGUMENT_CLOUDFORMATION_ROLE, false),
                        Tags          = new List <Tag> {
                            new Tag {
                                Key = Constants.SERVERLESS_TAG_NAME, Value = "true"
                            }
                        }
                    };

                    if (new FileInfo(templatePath).Length < Constants.MAX_TEMPLATE_BODY_IN_REQUEST_SIZE)
                    {
                        changeSetRequest.TemplateBody = templateBody;
                    }
                    else
                    {
                        changeSetRequest.TemplateURL = this.S3Client.GetPreSignedURL(new S3.Model.GetPreSignedUrlRequest {
                            BucketName = s3Bucket, Key = s3KeyTemplate, Expires = DateTime.Now.AddHours(1)
                        });
                    }

                    // Create the change set which performs the transformation on the Serverless resources in the template.
                    changeSetResponse = await this.CloudFormationClient.CreateChangeSetAsync(changeSetRequest);


                    this.Logger.WriteLine("CloudFormation change set created");
                }
                catch (LambdaToolsException)
                {
                    throw;
                }
                catch (Exception e)
                {
                    throw new LambdaToolsException($"Error creating CloudFormation change set: {e.Message}", LambdaToolsException.ErrorCode.CloudFormationCreateStack, e);
                }

                // The change set can take a few seconds to be reviewed and be ready to be executed.
                if (!await WaitForChangeSetBeingAvailableAsync(changeSetResponse.Id, existingStack != null))
                {
                    return(false);
                }

                var executeChangeSetRequest = new ExecuteChangeSetRequest
                {
                    StackName     = stackName,
                    ChangeSetName = changeSetResponse.Id
                };

                // Execute the change set.
                DateTime timeChangeSetExecuted = DateTime.Now;
                ExecuteChangeSetResponse executeChangeSetResponse;
                try
                {
                    executeChangeSetResponse = await this.CloudFormationClient.ExecuteChangeSetAsync(executeChangeSetRequest);

                    if (changeSetType == ChangeSetType.CREATE)
                    {
                        this.Logger.WriteLine($"Created CloudFormation stack {stackName}");
                    }
                    else
                    {
                        this.Logger.WriteLine($"Initiated CloudFormation stack update on {stackName}");
                    }
                }
                catch (Exception e)
                {
                    throw new LambdaToolsException($"Error executing CloudFormation change set: {e.Message}", LambdaToolsException.ErrorCode.CloudFormationCreateChangeSet, e);
                }

                // Wait for the stack to finish unless the user opts out of waiting. The VS Toolkit opts out and
                // instead shows the stack view in the IDE, enabling the user to view progress.
                var shouldWait = GetBoolValueOrDefault(this.WaitForStackToComplete, DefinedCommandOptions.ARGUMENT_STACK_WAIT, false);
                if (!shouldWait.HasValue || shouldWait.Value)
                {
                    var updatedStack = await WaitStackToCompleteAsync(stackName, timeChangeSetExecuted);

                    if (updatedStack.StackStatus == StackStatus.CREATE_COMPLETE || updatedStack.StackStatus == StackStatus.UPDATE_COMPLETE)
                    {
                        this.Logger.WriteLine($"Stack finished updating with status: {updatedStack.StackStatus}");

                        // Display the output parameters.
                        DisplayOutputs(updatedStack);
                    }
                    else
                    {
                        this.Logger.WriteLine($"Stack update failed with status: {updatedStack.StackStatus} ({updatedStack.StackStatusReason})");
                        return(false);
                    }
                }

                if (this.GetBoolValueOrDefault(this.PersistConfigFile, DefinedCommandOptions.ARGUMENT_PERSIST_CONFIG_FILE, false).GetValueOrDefault())
                {
                    this.SaveConfigFile();
                }

                return(true);
            }
            catch (LambdaToolsException e)
            {
                this.Logger.WriteLine(e.Message);
                this.LastToolsException = e;
                return(false);
            }
            catch (Exception e)
            {
                this.Logger.WriteLine($"Unknown error executing AWS Serverless deployment: {e.Message}");
                this.Logger.WriteLine(e.StackTrace);
                return(false);
            }
        }
コード例 #19
0
        /// <summary>
        /// Gets the update request with policy from change set request.
        /// </summary>
        /// <param name="changeSetRequest">The change set request.</param>
        /// <returns>New <see cref="UpdateStackRequest"/></returns>
        private async Task <UpdateStackRequest> GetUpdateRequestWithPolicyFromChangesetRequestAsync(CreateChangeSetRequest changeSetRequest)
        {
            var policyResolver = new StackPolicyResolver(this.clientFactory, this.context);

            var policy = await policyResolver.ResolveArtifactLocationAsync(
                this.context,
                this.stackPolicyLocation,
                this.stackName);

            var updatePolicy = await policyResolver.ResolveArtifactLocationAsync(
                this.context,
                this.stackPolicyDuringUpdateLocation,
                this.stackName);

            return(new UpdateStackRequest
            {
                Parameters = changeSetRequest.Parameters,
                Capabilities = changeSetRequest.Capabilities,
                StackName = changeSetRequest.StackName,
                ClientRequestToken = changeSetRequest.ClientToken,
                RoleARN = changeSetRequest.RoleARN,
                NotificationARNs = changeSetRequest.NotificationARNs,
                RollbackConfiguration = changeSetRequest.RollbackConfiguration,
                ResourceTypes = changeSetRequest.ResourceTypes,
                StackPolicyBody = policy.ArtifactBody,
                StackPolicyURL = policy.ArtifactUrl,
                StackPolicyDuringUpdateBody = updatePolicy.ArtifactBody,
                StackPolicyDuringUpdateURL = updatePolicy.ArtifactUrl,
                Tags = changeSetRequest.Tags,
                TemplateBody = changeSetRequest.TemplateBody,
                TemplateURL = changeSetRequest.TemplateURL,
                UsePreviousTemplate = changeSetRequest.UsePreviousTemplate
            });
        }