424 lines
14 KiB
Python
424 lines
14 KiB
Python
|
from datetime import datetime
|
||
|
|
||
|
from boto.resultset import ResultSet
|
||
|
|
||
|
|
||
|
class Stack(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.creation_time = None
|
||
|
self.description = None
|
||
|
self.disable_rollback = None
|
||
|
self.notification_arns = []
|
||
|
self.outputs = []
|
||
|
self.parameters = []
|
||
|
self.capabilities = []
|
||
|
self.tags = []
|
||
|
self.stack_id = None
|
||
|
self.stack_status = None
|
||
|
self.stack_status_reason = None
|
||
|
self.stack_name = None
|
||
|
self.timeout_in_minutes = None
|
||
|
|
||
|
@property
|
||
|
def stack_name_reason(self):
|
||
|
return self.stack_status_reason
|
||
|
|
||
|
@stack_name_reason.setter
|
||
|
def stack_name_reason(self, value):
|
||
|
self.stack_status_reason = value
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
if name == "Parameters":
|
||
|
self.parameters = ResultSet([('member', Parameter)])
|
||
|
return self.parameters
|
||
|
elif name == "Outputs":
|
||
|
self.outputs = ResultSet([('member', Output)])
|
||
|
return self.outputs
|
||
|
elif name == "Capabilities":
|
||
|
self.capabilities = ResultSet([('member', Capability)])
|
||
|
return self.capabilities
|
||
|
elif name == "Tags":
|
||
|
self.tags = Tag()
|
||
|
return self.tags
|
||
|
elif name == 'NotificationARNs':
|
||
|
self.notification_arns = ResultSet([('member', NotificationARN)])
|
||
|
return self.notification_arns
|
||
|
else:
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == 'CreationTime':
|
||
|
try:
|
||
|
self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||
|
except ValueError:
|
||
|
self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||
|
elif name == "Description":
|
||
|
self.description = value
|
||
|
elif name == "DisableRollback":
|
||
|
if str(value).lower() == 'true':
|
||
|
self.disable_rollback = True
|
||
|
else:
|
||
|
self.disable_rollback = False
|
||
|
elif name == 'StackId':
|
||
|
self.stack_id = value
|
||
|
elif name == 'StackName':
|
||
|
self.stack_name = value
|
||
|
elif name == 'StackStatus':
|
||
|
self.stack_status = value
|
||
|
elif name == "StackStatusReason":
|
||
|
self.stack_status_reason = value
|
||
|
elif name == "TimeoutInMinutes":
|
||
|
self.timeout_in_minutes = int(value)
|
||
|
elif name == "member":
|
||
|
pass
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def delete(self):
|
||
|
return self.connection.delete_stack(stack_name_or_id=self.stack_id)
|
||
|
|
||
|
def describe_events(self, next_token=None):
|
||
|
return self.connection.describe_stack_events(
|
||
|
stack_name_or_id=self.stack_id,
|
||
|
next_token=next_token
|
||
|
)
|
||
|
|
||
|
def describe_resource(self, logical_resource_id):
|
||
|
return self.connection.describe_stack_resource(
|
||
|
stack_name_or_id=self.stack_id,
|
||
|
logical_resource_id=logical_resource_id
|
||
|
)
|
||
|
|
||
|
def describe_resources(self, logical_resource_id=None,
|
||
|
physical_resource_id=None):
|
||
|
return self.connection.describe_stack_resources(
|
||
|
stack_name_or_id=self.stack_id,
|
||
|
logical_resource_id=logical_resource_id,
|
||
|
physical_resource_id=physical_resource_id
|
||
|
)
|
||
|
|
||
|
def list_resources(self, next_token=None):
|
||
|
return self.connection.list_stack_resources(
|
||
|
stack_name_or_id=self.stack_id,
|
||
|
next_token=next_token
|
||
|
)
|
||
|
|
||
|
def update(self):
|
||
|
rs = self.connection.describe_stacks(self.stack_id)
|
||
|
if len(rs) == 1 and rs[0].stack_id == self.stack_id:
|
||
|
self.__dict__.update(rs[0].__dict__)
|
||
|
else:
|
||
|
raise ValueError("%s is not a valid Stack ID or Name" %
|
||
|
self.stack_id)
|
||
|
|
||
|
def get_template(self):
|
||
|
return self.connection.get_template(stack_name_or_id=self.stack_id)
|
||
|
|
||
|
def get_policy(self):
|
||
|
"""
|
||
|
Returns the stack policy for this stack. If it has no policy
|
||
|
then, a null value is returned.
|
||
|
"""
|
||
|
return self.connection.get_stack_policy(self.stack_id)
|
||
|
|
||
|
def set_policy(self, stack_policy_body=None, stack_policy_url=None):
|
||
|
"""
|
||
|
Sets a stack policy for this stack.
|
||
|
|
||
|
:type stack_policy_body: string
|
||
|
:param stack_policy_body: Structure containing the stack policy body.
|
||
|
(For more information, go to ` Prevent Updates to Stack Resources`_
|
||
|
in the AWS CloudFormation User Guide.)
|
||
|
You must pass `StackPolicyBody` or `StackPolicyURL`. If both are
|
||
|
passed, only `StackPolicyBody` is used.
|
||
|
|
||
|
:type stack_policy_url: string
|
||
|
:param stack_policy_url: Location of a file containing the stack
|
||
|
policy. The URL must point to a policy (max size: 16KB) located in
|
||
|
an S3 bucket in the same region as the stack. You must pass
|
||
|
`StackPolicyBody` or `StackPolicyURL`. If both are passed, only
|
||
|
`StackPolicyBody` is used.
|
||
|
"""
|
||
|
return self.connection.set_stack_policy(self.stack_id,
|
||
|
stack_policy_body=stack_policy_body,
|
||
|
stack_policy_url=stack_policy_url)
|
||
|
|
||
|
|
||
|
class StackSummary(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.stack_id = None
|
||
|
self.stack_status = None
|
||
|
self.stack_name = None
|
||
|
self.creation_time = None
|
||
|
self.deletion_time = None
|
||
|
self.template_description = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == 'StackId':
|
||
|
self.stack_id = value
|
||
|
elif name == 'StackStatus':
|
||
|
self.stack_status = value
|
||
|
elif name == 'StackName':
|
||
|
self.stack_name = value
|
||
|
elif name == 'CreationTime':
|
||
|
try:
|
||
|
self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||
|
except ValueError:
|
||
|
self.creation_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||
|
elif name == "DeletionTime":
|
||
|
try:
|
||
|
self.deletion_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||
|
except ValueError:
|
||
|
self.deletion_time = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||
|
elif name == 'TemplateDescription':
|
||
|
self.template_description = value
|
||
|
elif name == "member":
|
||
|
pass
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
|
||
|
class Parameter(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = None
|
||
|
self.key = None
|
||
|
self.value = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "ParameterKey":
|
||
|
self.key = value
|
||
|
elif name == "ParameterValue":
|
||
|
self.value = value
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "Parameter:\"%s\"=\"%s\"" % (self.key, self.value)
|
||
|
|
||
|
|
||
|
class Output(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.description = None
|
||
|
self.key = None
|
||
|
self.value = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "Description":
|
||
|
self.description = value
|
||
|
elif name == "OutputKey":
|
||
|
self.key = value
|
||
|
elif name == "OutputValue":
|
||
|
self.value = value
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "Output:\"%s\"=\"%s\"" % (self.key, self.value)
|
||
|
|
||
|
|
||
|
class Capability(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = None
|
||
|
self.value = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
self.value = value
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "Capability:\"%s\"" % (self.value)
|
||
|
|
||
|
|
||
|
class Tag(dict):
|
||
|
|
||
|
def __init__(self, connection=None):
|
||
|
dict.__init__(self)
|
||
|
self.connection = connection
|
||
|
self._current_key = None
|
||
|
self._current_value = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "Key":
|
||
|
self._current_key = value
|
||
|
elif name == "Value":
|
||
|
self._current_value = value
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
if self._current_key and self._current_value:
|
||
|
self[self._current_key] = self._current_value
|
||
|
self._current_key = None
|
||
|
self._current_value = None
|
||
|
|
||
|
|
||
|
class NotificationARN(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = None
|
||
|
self.value = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
self.value = value
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "NotificationARN:\"%s\"" % (self.value)
|
||
|
|
||
|
|
||
|
class StackResource(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.description = None
|
||
|
self.logical_resource_id = None
|
||
|
self.physical_resource_id = None
|
||
|
self.resource_status = None
|
||
|
self.resource_status_reason = None
|
||
|
self.resource_type = None
|
||
|
self.stack_id = None
|
||
|
self.stack_name = None
|
||
|
self.timestamp = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "Description":
|
||
|
self.description = value
|
||
|
elif name == "LogicalResourceId":
|
||
|
self.logical_resource_id = value
|
||
|
elif name == "PhysicalResourceId":
|
||
|
self.physical_resource_id = value
|
||
|
elif name == "ResourceStatus":
|
||
|
self.resource_status = value
|
||
|
elif name == "ResourceStatusReason":
|
||
|
self.resource_status_reason = value
|
||
|
elif name == "ResourceType":
|
||
|
self.resource_type = value
|
||
|
elif name == "StackId":
|
||
|
self.stack_id = value
|
||
|
elif name == "StackName":
|
||
|
self.stack_name = value
|
||
|
elif name == "Timestamp":
|
||
|
try:
|
||
|
self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||
|
except ValueError:
|
||
|
self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "StackResource:%s (%s)" % (self.logical_resource_id,
|
||
|
self.resource_type)
|
||
|
|
||
|
|
||
|
class StackResourceSummary(object):
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.last_updated_time = None
|
||
|
self.logical_resource_id = None
|
||
|
self.physical_resource_id = None
|
||
|
self.resource_status = None
|
||
|
self.resource_status_reason = None
|
||
|
self.resource_type = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "LastUpdatedTime":
|
||
|
try:
|
||
|
self.last_updated_time = datetime.strptime(
|
||
|
value,
|
||
|
'%Y-%m-%dT%H:%M:%SZ'
|
||
|
)
|
||
|
except ValueError:
|
||
|
self.last_updated_time = datetime.strptime(
|
||
|
value,
|
||
|
'%Y-%m-%dT%H:%M:%S.%fZ'
|
||
|
)
|
||
|
elif name == "LogicalResourceId":
|
||
|
self.logical_resource_id = value
|
||
|
elif name == "PhysicalResourceId":
|
||
|
self.physical_resource_id = value
|
||
|
elif name == "ResourceStatus":
|
||
|
self.resource_status = value
|
||
|
elif name == "ResourceStatusReason":
|
||
|
self.resource_status_reason = value
|
||
|
elif name == "ResourceType":
|
||
|
self.resource_type = value
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "StackResourceSummary:%s (%s)" % (self.logical_resource_id,
|
||
|
self.resource_type)
|
||
|
|
||
|
|
||
|
class StackEvent(object):
|
||
|
valid_states = ("CREATE_IN_PROGRESS", "CREATE_FAILED", "CREATE_COMPLETE",
|
||
|
"DELETE_IN_PROGRESS", "DELETE_FAILED", "DELETE_COMPLETE")
|
||
|
def __init__(self, connection=None):
|
||
|
self.connection = connection
|
||
|
self.event_id = None
|
||
|
self.logical_resource_id = None
|
||
|
self.physical_resource_id = None
|
||
|
self.resource_properties = None
|
||
|
self.resource_status = None
|
||
|
self.resource_status_reason = None
|
||
|
self.resource_type = None
|
||
|
self.stack_id = None
|
||
|
self.stack_name = None
|
||
|
self.timestamp = None
|
||
|
|
||
|
def startElement(self, name, attrs, connection):
|
||
|
return None
|
||
|
|
||
|
def endElement(self, name, value, connection):
|
||
|
if name == "EventId":
|
||
|
self.event_id = value
|
||
|
elif name == "LogicalResourceId":
|
||
|
self.logical_resource_id = value
|
||
|
elif name == "PhysicalResourceId":
|
||
|
self.physical_resource_id = value
|
||
|
elif name == "ResourceProperties":
|
||
|
self.resource_properties = value
|
||
|
elif name == "ResourceStatus":
|
||
|
self.resource_status = value
|
||
|
elif name == "ResourceStatusReason":
|
||
|
self.resource_status_reason = value
|
||
|
elif name == "ResourceType":
|
||
|
self.resource_type = value
|
||
|
elif name == "StackId":
|
||
|
self.stack_id = value
|
||
|
elif name == "StackName":
|
||
|
self.stack_name = value
|
||
|
elif name == "Timestamp":
|
||
|
try:
|
||
|
self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%SZ')
|
||
|
except ValueError:
|
||
|
self.timestamp = datetime.strptime(value, '%Y-%m-%dT%H:%M:%S.%fZ')
|
||
|
else:
|
||
|
setattr(self, name, value)
|
||
|
|
||
|
def __repr__(self):
|
||
|
return "StackEvent %s %s %s" % (self.resource_type,
|
||
|
self.logical_resource_id, self.resource_status)
|