Exemplo n.º 1
0
        /// <summary>
        /// Gets the most recent stack event.
        /// </summary>
        /// <param name="stackId">The stack identifier.</param>
        /// <returns>Timestamp of most recent event</returns>
        private async Task <DateTime> GetMostRecentStackEvent(string stackId)
        {
            // CF returns events in descending chronological order
            var response = await PollyHelper.ExecuteWithPolly(
                () => this.client.DescribeStackEventsAsync(
                    new DescribeStackEventsRequest {
                StackName = stackId
            }));

            return(response.StackEvents.Any()
                       ? response.StackEvents.First().Timestamp
                       : DateTime.MinValue);
        }
Exemplo n.º 2
0
        /// <summary>Waits for a stack operation. to compete, sending stack event messages to the log.</summary>
        /// <param name="stackArn">  ARN or name of stack to wait on.</param>
        /// <param name="throwOnFailure">if set to <c>true</c> [throw on failure].</param>
        /// <returns>The stack being waited on.</returns>
        private async Task <Stack> WaitStackOperationAsync(string stackArn, bool throwOnFailure)
        {
            var describeStacksRequest = new DescribeStacksRequest {
                StackName = stackArn
            };

            while (true)
            {
                Thread.Sleep(this.waitPollTime);
                var stack = (await PollyHelper.ExecuteWithPolly(
                                 () => this.client.DescribeStacksAsync(describeStacksRequest))).Stacks.First();

                // Have we finished?
                var isComplete = stack.StackStatus.Value.EndsWith("COMPLETE") ||
                                 stack.StackStatus.Value.EndsWith("FAILED");

                // Get events and render them
                var events = (await GetEventsAsync(stackArn)).OrderBy(e => e.Timestamp).ToList();

                if (events.Any())
                {
                    // Most recent event is last
                    this.lastEventTime = events.Last().Timestamp;

                    // Now output them oldest first
                    foreach (var evt in events.OrderBy(e => e.Timestamp))
                    {
                        this.context.Logger.LogStackEvent(evt);
                    }
                }

                if (isComplete)
                {
                    // Operation finished
                    if (Regex.IsMatch(stack.StackStatus.Value, "(ROLLBACK|FAILED)") && throwOnFailure)
                    {
                        throw new StackOperationException(stack);
                    }

                    // We done
                    return(stack);
                }
            }

            // Local recursive function to collect events from nested stacks
            async Task <IEnumerable <StackEvent> > GetEventsAsync(string stackArnLocal)
            {
                string nextToken = null;
                var    allEvents = new List <StackEvent>();

                // Get events for this stack
                do
                {
                    var response = await PollyHelper.ExecuteWithPolly(
                        () => this.client.DescribeStackEventsAsync(
                            new DescribeStackEventsRequest
                    {
                        // ReSharper disable once AccessToModifiedClosure
                        StackName = stackArnLocal, NextToken = nextToken
                    }));

                    nextToken = response.NextToken;
                    allEvents.AddRange(response.StackEvents.Where(e => e.Timestamp > this.lastEventTime));

                    if (response.StackEvents.Any() && response.StackEvents.Last().Timestamp <= this.lastEventTime)
                    {
                        // Break here as remaining events will be older.
                        nextToken = null;
                    }
                }while (nextToken != null);

                // Enumerate any nested stack resources and recurse into each
                foreach (var nested in (await PollyHelper.ExecuteWithPolly(
                                            () => this.client.DescribeStackResourcesAsync(
                                                new DescribeStackResourcesRequest {
                    StackName = stackArnLocal
                })))
                         .StackResources.Where(
                             r => r.ResourceType == "AWS::CloudFormation::Stack" &&
                             !string.IsNullOrEmpty(r.PhysicalResourceId)))
                {
                    allEvents.AddRange(await GetEventsAsync(nested.PhysicalResourceId));
                }

                return(allEvents);
            }
        }