/*******************************************************************************
* Copyright 2012-2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Licensed under the Apache License, Version 2.0 (the "License"). You may not use
* this file except in compliance with the License. A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file.
* This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
* *****************************************************************************
*
* AWS Tools for Windows (TM) PowerShell (TM)
*
*/
using System;
using System.Collections.Generic;
using System.Management.Automation;
using System.Text;
using Amazon.PowerShell.Common;
using Amazon.CloudFormation;
using Amazon.CloudFormation.Model;
using Amazon.Runtime;
namespace Amazon.PowerShell.Cmdlets.CFN
{
///
/// Tests a CloudFormation stack to determine if it's in a certain status.
/// The command returns true or false, depending on whether or not the specified stack is in a given status.
///
[Cmdlet("Test", "CFNStack")]
[OutputType("System.Boolean")]
[AWSCmdlet("Tests the status of a stack using the DescribeStacks API operation to retrieve the stack's status.", Operation = new[] { "DescribeStacks" })]
[AWSCmdletOutput("System.Boolean",
"This cmdlet returns a Boolean value.",
"The service call response (type Amazon.CloudFormation.Model.DescribeStacksResponse) can also be referenced from properties attached to the cmdlet entry in the $AWSHistory stack."
)]
public partial class TestCFNStackCmdlet : AmazonCloudFormationClientCmdlet, IExecutor
{
internal static HashSet DefaultCompletionStates = new HashSet(new StackStatusComparer())
{
StackStatus.UPDATE_ROLLBACK_COMPLETE,
StackStatus.CREATE_COMPLETE,
StackStatus.ROLLBACK_COMPLETE,
StackStatus.UPDATE_COMPLETE
};
#region Parameter StackName
///
/// The name or unique stack ID of the of the CloudFormation stack whose status will be monitored.
///
[System.Management.Automation.Parameter(Mandatory = true, Position = 0, ValueFromPipelineByPropertyName = true, ValueFromPipeline = true)]
[Amazon.PowerShell.Common.AWSRequiredParameter]
public System.String StackName { get; set; }
#endregion
#region Parameter Status
///
///
/// The CloudFormation status. You can tab-complete the values for this parameter or view a list of all
/// supported CloudFormation status types in the AWS documentation: https://goo.gl/cpSu29.
///
///
/// If not specified the command checks the stack's status against the states
/// 'UPDATE_ROLLBACK_COMPLETE', 'CREATE_COMPLETE', 'ROLLBACK_COMPLETE' and 'UPDATE_COMPLETE'.
///
///
[System.Management.Automation.Parameter(ValueFromPipelineByPropertyName = true)]
[AWSConstantClassSource("Amazon.CloudFormation.StackStatus")]
public Amazon.CloudFormation.StackStatus[] Status { get; set; }
#endregion
protected override void ProcessRecord()
{
base.ProcessRecord();
var context = new CmdletContext();
// allow for manipulation of parameters prior to loading into context
PreExecutionContextLoad(context);
context.StackName = StackName;
context.Status = ParameterWasBound("Status")
? new HashSet(Status, new StackStatusComparer())
: DefaultCompletionStates;
// allow further manipulation of loaded context prior to processing
PostExecutionContextLoad(context);
var output = Execute(context) as CmdletOutput;
ProcessOutput(output);
}
#region IExecutor Members
public object Execute(ExecutorContext context)
{
var cmdletContext = context as CmdletContext;
CmdletOutput output;
var client = Client ?? CreateClient(_CurrentCredentials, _RegionEndpoint);
try
{
WriteVerbose(string.Format("Testing stack {0} in region {1} is in state(s): {2}",
cmdletContext.StackName,
_RegionEndpoint.SystemName,
StateSetToFormattedString(cmdletContext.Status)));
output = new CmdletOutput
{
PipelineOutput = IsStackInState(client, cmdletContext.StackName, cmdletContext.Status, false)
};
}
catch (Exception e)
{
output = new CmdletOutput { ErrorResponse = e };
}
return output;
}
public ExecutorContext CreateContext()
{
return new CmdletContext();
}
#endregion
internal static bool IsStackInState(IAmazonCloudFormation client, string stackName, HashSet desiredStates, bool throwOnError)
{
try
{
var request = new DescribeStacksRequest { StackName = stackName };
#if DESKTOP
var response = client.DescribeStacks(request);
#elif CORECLR
var response = client.DescribeStacksAsync(request).GetAwaiter().GetResult();
#else
#error "Unknown build edition"
#endif
return IsStackInState(response.Stacks[0].StackStatus, desiredStates);
}
catch (Exception exc)
{
var webException = exc.InnerException as System.Net.WebException;
if (webException != null)
{
throw new Exception(Utils.Common.FormatNameResolutionFailureMessage(client.Config, webException.Message), webException);
}
if (throwOnError)
throw;
}
return false;
}
internal static bool IsStackInState(StackStatus status, HashSet desiredStates)
{
return desiredStates.Contains(status);
}
internal static string StateSetToFormattedString(IEnumerable states)
{
if (states == null)
throw new ArgumentNullException("states");
var sb = new StringBuilder();
foreach (var s in states)
{
if (sb.Length > 0)
sb.Append(",");
sb.Append(s);
}
return sb.ToString();
}
internal class CmdletContext : ExecutorContext
{
public System.String StackName { get; set; }
public HashSet Status { get; set; }
}
internal class StackStatusComparer : IEqualityComparer
{
public bool Equals(StackStatus x, StackStatus y)
{
return string.Compare(x, y, StringComparison.OrdinalIgnoreCase) == 0;
}
public int GetHashCode(StackStatus obj)
{
return obj.GetHashCode();
}
}
}
}