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); }
internal CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request) { var marshaller = new CreateChangeSetRequestMarshaller(); var unmarshaller = CreateChangeSetResponseUnmarshaller.Instance; return(Invoke <CreateChangeSetRequest, CreateChangeSetResponse>(request, marshaller, unmarshaller)); }
/// <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)); }
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); } }
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); } }
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); } }
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))); }
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); }
public static CreateChangeSetResponse CreateChangeSet(this Func <IAmazonCloudFormation> factory, CreateChangeSetRequest request) { return(factory().Map(client => client.CreateChangeSet(request))); }
public static Task <CreateChangeSetResponse> CreateChangeSetAsync(this Func <IAmazonCloudFormation> factory, CreateChangeSetRequest request) { return(factory().CreateChangeSetAsync(request)); }
/// <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)); }
/// <summary> /// 创建更改集 /// </summary> /// <param name="request">请求参数信息</param> /// <returns>请求结果信息</returns> public CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request) { return(new CreateChangeSetExecutor().Client(this).Execute <CreateChangeSetResponse, CreateChangeSetResult, CreateChangeSetRequest>(request)); }
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); }
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); }
public CreateChangeSetResponse CreateChangeSet(CreateChangeSetRequest request) { AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); return(CreateChangeSetWithOptions(request, runtime)); }
public async Task <CreateChangeSetResponse> CreateChangeSetAsync(CreateChangeSetRequest request) { AlibabaCloud.TeaUtil.Models.RuntimeOptions runtime = new AlibabaCloud.TeaUtil.Models.RuntimeOptions(); return(await CreateChangeSetWithOptionsAsync(request, runtime)); }
/// <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); } } }
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); } }
/// <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 }); }