예제 #1
0
        private async Task WaitForChangeSetCreate(string stackId, DeployContext context, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            Console.WriteLine("Waiting for changeset creation to complete...");
            var status = ChangeSetStatus.CREATE_PENDING;
            var reason = string.Empty;

            while (status != ChangeSetStatus.CREATE_COMPLETE)
            {
                cancellationToken.ThrowIfCancellationRequested();

                if (status == ChangeSetStatus.FAILED)
                {
                    throw new Exception($"Change set {context.ChangeSetName} failed: {reason}");
                }

                await Task.Delay(1000, cancellationToken);

                var request = new DescribeChangeSetRequest {
                    ChangeSetName = context.ChangeSetName, StackName = stackId
                };
                var response = await cloudformation.DescribeChangeSetAsync(request, cancellationToken);

                status = response.Status;
                reason = response.StatusReason;
            }
        }
예제 #2
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);
        }
예제 #3
0
        /// <summary>
        /// Deploys a cloudformation stack.
        /// </summary>
        /// <param name="context">Context holder for deployment information.</param>
        /// <param name="cancellationToken">Token used to cancel the operation.</param>
        /// <returns>The resulting task.</returns>
        public async Task Deploy(DeployContext context, CancellationToken cancellationToken)
        {
            var stackId = await CreateChangeSet(context, cancellationToken);

            await WaitForChangeSetCreate(stackId, context, cancellationToken);
            await ExecuteChangeSet(stackId, context, cancellationToken);
            await WaitForChangeSetExecute(stackId, context, cancellationToken);
        }
예제 #4
0
 private async Task ExecuteChangeSet(string stackId, DeployContext context, CancellationToken cancellationToken)
 {
     cancellationToken.ThrowIfCancellationRequested();
     var request = new ExecuteChangeSetRequest {
         ChangeSetName = context.ChangeSetName, StackName = stackId
     };
     await cloudformation.ExecuteChangeSetAsync(request, cancellationToken);
 }
예제 #5
0
        private async Task <ChangeSetType> GetChangeSetType(DeployContext context, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            try
            {
                var request = new DescribeStacksRequest {
                    StackName = context.StackName
                };
                var response = await cloudformation.DescribeStacksAsync(request, cancellationToken);

                return(response.Stacks.Any() ? ChangeSetType.UPDATE : ChangeSetType.UPDATE);
            }
            catch
            {
                return(ChangeSetType.CREATE);
            }
        }
예제 #6
0
        private async Task WaitForChangeSetExecute(string stackId, DeployContext context, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();
            Console.WriteLine("Executing changeset...\n");
            var stackStatus = ResourceStatus.CREATE_IN_PROGRESS;
            var lastEventId = (string?)null;

            while (stackStatus != ResourceStatus.CREATE_COMPLETE && stackStatus != ResourceStatus.UPDATE_COMPLETE)
            {
                cancellationToken.ThrowIfCancellationRequested();
                await Task.Delay(1000, cancellationToken);

                var events = await GetStackEvents(lastEventId, stackId, context, cancellationToken);

                foreach (var @event in events)
                {
                    var header = $"[{@event.LogicalResourceId}]: {@event.ResourceStatus}\n";
                    header += string.Join('\0', Enumerable.Repeat('-', header.Length));
                    Console.ForegroundColor = ConsoleColor.Cyan;
                    Console.WriteLine(header);
                    Console.ResetColor();
                    Console.WriteLine(@event.ResourceStatusReason);
                    Console.WriteLine();

                    lastEventId = @event.EventId;
                    if (@event.ResourceType == "AWS::CloudFormation::Stack" && @event.LogicalResourceId == context.StackName)
                    {
                        stackStatus = @event.ResourceStatus;
                    }
                }

                if (stackStatus.ToString().EndsWith("_FAILED") || stackStatus.ToString().EndsWith("ROLLBACK_COMPLETE"))
                {
                    throw new Exception("Deployment failed.");
                }
            }
        }
예제 #7
0
        private async Task <List <StackEvent> > GetStackEvents(string?lastEventId, string stackId, DeployContext context, CancellationToken cancellationToken)
        {
            cancellationToken.ThrowIfCancellationRequested();

            var request = new DescribeStackEventsRequest {
                StackName = stackId
            };
            var response = await cloudformation.DescribeStackEventsAsync(request, cancellationToken);

            var relevantEvents = new List <StackEvent>();

            foreach (var @event in response.StackEvents)
            {
                if (@event.EventId == lastEventId || @event.Timestamp < context.Timestamp)
                {
                    break;
                }

                relevantEvents.Add(@event);
            }

            relevantEvents.Reverse();
            return(relevantEvents);
        }