// these flags control various optimization techniques public InitialisationProcess( IInputFileResolver inputFileResolver = null, IInitialBuildProcess initialBuildProcess = null, IInitialTestProcess initialTestProcess = null, ITestRunner testRunner = null, IAssemblyReferenceResolver assemblyReferenceResolver = null) { _inputFileResolver = inputFileResolver ?? new InputFileResolver(); _initialBuildProcess = initialBuildProcess ?? new InitialBuildProcess(); _initialTestProcess = initialTestProcess ?? new InitialTestProcess(); _testRunner = testRunner; _assemblyReferenceResolver = assemblyReferenceResolver ?? new AssemblyReferenceResolver(); }
public InitialisationProcess( IInputFileResolver inputFileResolver = null, IInitialBuildProcess initialBuildProcess = null, IInitialTestProcess initialTestProcess = null, ITestRunner testRunner = null, IAssemblyReferenceResolver assemblyReferenceResolver = null) { _inputFileResolver = inputFileResolver ?? new InputFileResolver(); _initialBuildProcess = initialBuildProcess ?? new InitialBuildProcess(); _initialTestProcess = initialTestProcess ?? new InitialTestProcess(); _testRunner = testRunner; _assemblyReferenceResolver = assemblyReferenceResolver ?? new AssemblyReferenceResolver(); _logger = ApplicationLogging.LoggerFactory.CreateLogger <InitialisationProcess>(); }
/// <summary> /// Gets the stack parameters for update. /// </summary> /// <param name="resolver">The resolver.</param> /// <param name="stack">The stack.</param> /// <returns>List of <see cref="Parameter"/></returns> private List <Parameter> GetStackParametersForUpdate(IInputFileResolver resolver, Stack stack) { // Sort out the parameters var stackParameters = new List <Parameter>(); // First, get the parameter names that are declared in the stack we are updating. var declaredParameterKeys = TemplateParser.Create(resolver.FileContent).GetParameters().ToList(); // We can only pass in parameters for keys declared in the template we are pushing foreach (var parameter in declaredParameterKeys) { // Where we have a user-supplied parameter that matches the declared keys, add it if (this.parameters.ContainsKey(parameter.Name)) { stackParameters.Add( new Parameter { ParameterKey = parameter.Name, ParameterValue = this.parameters[parameter.Name] }); } else if (stack.Parameters.Any(p => p.ParameterKey == parameter.Name)) { // Stack still has the declared parameter, but user hasn't supplied a new value, // then it's use previous value. stackParameters.Add(new Parameter { ParameterKey = parameter.Name, UsePreviousValue = true }); } } var extraParameters = this.parameters.Keys.Where(k => declaredParameterKeys.All(p => p.Name != k)).ToList(); if (extraParameters.Any()) { this.context.Logger.LogWarning( "The following parameters were supplied which are not required by the template you are applying:\n " + string.Join(", ", extraParameters)); } return(stackParameters); }
/// <summary>Deletes a stack.</summary> /// <param name="invalidRetentionConfirmationFunc"> /// Function to confirm delete if user passed resources to retain when the stack is not in a failed state due to resources that could not be deleted. /// If this parameter is <c>null</c>, or the function returns true, then all resources are deleted. /// </param> /// <param name="queryDeleteStackFunc"> /// Function to confirm whether to delete the stack at all. /// If this parameter is <c>null</c>, or the function returns true, then the delete proceeds. /// </param> /// <returns>Operation result.</returns> public async Task <CloudFormationResult> DeleteStackAsync(Func <bool> invalidRetentionConfirmationFunc = null, Func <bool> queryDeleteStackFunc = null) { var stack = await this.stackOperations.GetStackAsync(this.stackName); var operationalState = await this.stackOperations.GetStackOperationalStateAsync(stack.StackId); var haveRetainResources = this.retainResource != null && this.retainResource.Any(); // Only permit delete if stack is in Ready state if (!new[] { StackOperationalState.Ready, StackOperationalState.DeleteFailed, StackOperationalState.Broken } .Contains(operationalState)) { throw new StackOperationException(stack, operationalState); } if (queryDeleteStackFunc != null && !queryDeleteStackFunc()) { return(new CloudFormationResult { StackArn = stack.StackId, StackOperationResult = StackOperationResult.NoChange }); } if (operationalState != StackOperationalState.DeleteFailed && haveRetainResources && invalidRetentionConfirmationFunc != null) { if (!invalidRetentionConfirmationFunc()) { return(new CloudFormationResult { StackArn = stack.StackId, StackOperationResult = StackOperationResult.NoChange }); } this.retainResource = null; } if (operationalState == StackOperationalState.Broken) { this.context.Logger.LogWarning("Stack is in a failed state from previous operation. Delete may fail."); } // Resolve template from CloudFormation to get description if any this.templateResolver = new TemplateResolver(this.clientFactory, this.context, this.stackName, true, this.forceS3); await this.templateResolver.ResolveFileAsync(null); var parser = TemplateParser.Create(this.templateResolver.FileContent); this.templateDescription = parser.GetTemplateDescription(); // Adds base stack name + 10 chars to each nested stack to estimate logical resource ID of each nested stack this.context.Logger.SetStackNameColumnWidth( parser.GetNestedStackNames(this.stackName).Concat(new[] { this.stackName }) .Max(s => s.Length)); this.context.Logger.SetResourceNameColumnWidth(parser.GetLogicalResourceNames(this.stackName).Max(r => r.Length)); this.context.Logger.LogInformation($"Deleting {this.GetStackNameWithDescription()}"); if (this.retainResource != null && this.retainResource.Any()) { this.context.Logger.LogInformation($"Retaining resources: {string.Join(", ", this.retainResource)}"); } this.context.Logger.LogInformation(string.Empty); this.lastEventTime = await this.GetMostRecentStackEvent(stack.StackId); await this.client.DeleteStackAsync( new DeleteStackRequest { StackName = stack.StackId, ClientRequestToken = this.clientToken, RoleARN = this.roleArn, RetainResources = this.retainResource }); if (this.followOperation) { await this.WaitStackOperationAsync(stack.StackId, true); return(new CloudFormationResult { StackArn = stack.StackId, StackOperationResult = StackOperationResult.StackDeleted }); } return(new CloudFormationResult { StackArn = stack.StackId, StackOperationResult = StackOperationResult.StackDeleteInProgress }); }
/// <summary>Initializes a new instance of the <see cref="CloudFormationRunner"/> class.</summary> /// <param name="clientFactory">Factory for creating AWS service clients</param> /// <param name="stackName">Name of the stack.</param> /// <param name="templateLocation">Template location. Either path or URL.</param> /// <param name="parameters">The parameters.</param> /// <param name="capabilities">The capabilities.</param> /// <param name="context">The Cake context.</param> /// <param name="tags">Stack level tags.</param> /// <param name="followOperation">if set to <c>true</c> [follow operation].</param> /// <param name="waitForInProgressUpdate">if set to <c>true</c> [wait for in progress update].</param> /// <param name="deleteNoopChangeSet">if set to <c>true</c> [delete no-op change set].</param> /// <param name="changesetOnly">if set to <c>true</c> only create change set without updating.</param> /// <param name="resourcesToImportLocation">Resources to import</param> /// <param name="roleArn">Role to assume</param> /// <param name="clientToken">Client token</param> /// <param name="notificationARNs">SNS notification ARNs</param> /// <param name="usePreviousTemplate">Whether to use existing template for update.</param> /// <param name="rollbackConfiguration">The rollback configuration</param> /// <param name="stackPolicyLocation">Location of structure containing a new stack policy body.</param> /// <param name="stackPolicyDuringUpdateLocation">Location of structure containing the temporary overriding stack policy body</param> /// <param name="resourceType">The template resource types that you have permissions to work with for this create stack action.</param> /// <param name="terminationProtection">Whether to enable termination protection on the specified stack.</param> /// <param name="onFailure">Determines what action will be taken if stack creation fails.</param> /// <param name="timeoutInMinutes">The amount of time that can pass before the stack status becomes CREATE_FAILED</param> /// <param name="disableRollback">Set to <c>true</c> to disable rollback of the stack if stack creation failed.</param> /// <param name="retainResource">For stacks in the DELETE_FAILED state, a list of resource logical IDs that are associated with the resources you want to retain.</param> /// <param name="forceS3">If <c>true</c> always upload local templates to S3.</param> /// <param name="includeNestedStacks">Creates a change set for the all nested stacks specified in the template. The default behavior of this action is set to <c>false</c>. To include nested sets in a change set, specify <c>true</c>.</param> /// <remarks>Constructor is private as this class implements the builder pattern. See CloudFormation.Runner.Builder.cs</remarks> internal CloudFormationRunner( IAwsClientFactory clientFactory, string stackName, string templateLocation, IDictionary <string, string> parameters, IEnumerable <Capability> capabilities, ICloudFormationContext context, List <Tag> tags, bool followOperation, bool waitForInProgressUpdate, bool deleteNoopChangeSet, bool changesetOnly, string resourcesToImportLocation, string roleArn, string clientToken, // ReSharper disable once InconsistentNaming List <string> notificationARNs, bool usePreviousTemplate, RollbackConfiguration rollbackConfiguration, string stackPolicyLocation, string stackPolicyDuringUpdateLocation, List <string> resourceType, bool terminationProtection, OnFailure onFailure, int timeoutInMinutes, bool disableRollback, List <string> retainResource, bool forceS3, bool includeNestedStacks) { this.includeNestedStacks = includeNestedStacks; this.forceS3 = forceS3; this.retainResource = retainResource; this.disableRollback = disableRollback; this.timeoutInMinutes = timeoutInMinutes; this.onFailure = onFailure; this.terminationProtection = terminationProtection; this.resourceType = resourceType; this.stackPolicyDuringUpdateLocation = stackPolicyDuringUpdateLocation; this.stackPolicyLocation = stackPolicyLocation; this.rollbackConfiguration = rollbackConfiguration; this.usePreviousTemplate = usePreviousTemplate; this.notificationARNs = notificationARNs; this.clientToken = clientToken; this.roleArn = roleArn; this.resourcesToImportLocation = resourcesToImportLocation; this.clientFactory = clientFactory; this.context = context; this.changesetOnly = changesetOnly; this.templateLocation = templateLocation; this.stackName = stackName ?? throw new ArgumentNullException(nameof(stackName)); this.followOperation = followOperation; this.waitForInProgressUpdate = waitForInProgressUpdate; this.deleteNoopChangeSet = deleteNoopChangeSet; // Cheeky unit test detection if (context.GetType().FullName == "Castle.Proxies.ICloudFormationContextProxy") { // Don't hang around in the wait loop this.waitPollTime = 50; } if (capabilities != null) { this.capabilities = capabilities; } if (parameters != null) { this.parameters = parameters; } if (tags != null) { this.tags = tags; } this.client = this.clientFactory.CreateCloudFormationClient(); this.stackOperations = new CloudFormationOperations(this.clientFactory, this.context); // Get parameters and description from supplied template if any this.templateResolver = new TemplateResolver(this.clientFactory, this.context, this.stackName, this.usePreviousTemplate, this.forceS3); this.templateResolver.ResolveArtifactLocationAsync(this.context, this.templateLocation, this.stackName) .Wait(); if (this.templateResolver.Source != InputFileSource.None) { var parser = TemplateParser.Create(this.templateResolver.FileContent); this.templateDescription = parser.GetTemplateDescription(); // Adds base stack name + 10 chars to each nested stack to estimate logical resource ID of each nested stack this.context.Logger.SetStackNameColumnWidth( parser.GetNestedStackNames(this.stackName).Concat(new[] { this.stackName }) .Max(s => s.Length)); this.context.Logger.SetResourceNameColumnWidth(parser.GetLogicalResourceNames(this.stackName).Max(r => r.Length)); } }