Exemple #1
0
 // 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();
 }
Exemple #2
0
 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>();
 }
Exemple #3
0
        /// <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));
            }
        }