def format_stack_summary(s): """ Reformat engine output into the AWS "StackSummary" format """ # Map the engine-api format to the AWS StackSummary datatype keymap = { engine_api.STACK_CREATION_TIME: 'CreationTime', engine_api.STACK_UPDATED_TIME: 'LastUpdatedTime', engine_api.STACK_ID: 'StackId', engine_api.STACK_NAME: 'StackName', engine_api.STACK_STATUS_DATA: 'StackStatusReason', engine_api.STACK_TMPL_DESCRIPTION: 'TemplateDescription', } result = api_utils.reformat_dict_keys(keymap, s) action = s[engine_api.STACK_ACTION] status = s[engine_api.STACK_STATUS] result['StackStatus'] = '_'.join((action, status)) # AWS docs indicate DeletionTime is ommitted for current stacks # This is still TODO(unknown) in the engine, we don't keep data for # stacks after they are deleted if engine_api.STACK_DELETION_TIME in s: result['DeletionTime'] = s[engine_api.STACK_DELETION_TIME] return self._id_format(result)
def format_stack_event(e): """ Reformat engine output into the AWS "StackEvent" format """ keymap = { engine_api.EVENT_ID: 'EventId', engine_api.EVENT_RES_NAME: 'LogicalResourceId', engine_api.EVENT_RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.EVENT_RES_PROPERTIES: 'ResourceProperties', engine_api.EVENT_RES_STATUS: 'ResourceStatus', engine_api.EVENT_RES_STATUS_DATA: 'ResourceStatusReason', engine_api.EVENT_RES_TYPE: 'ResourceType', engine_api.EVENT_STACK_ID: 'StackId', engine_api.EVENT_STACK_NAME: 'StackName', engine_api.EVENT_TIMESTAMP: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, e) action = e[engine_api.EVENT_RES_ACTION] status = e[engine_api.EVENT_RES_STATUS] if action and status: result['ResourceStatus'] = '_'.join((action, status)) else: result['ResourceStatus'] = status result['ResourceProperties'] = json.dumps(result[ 'ResourceProperties']) return self._id_format(result)
def format_stack_outputs(o): keymap = { engine_api.OUTPUT_DESCRIPTION: 'Description', engine_api.OUTPUT_KEY: 'OutputKey', engine_api.OUTPUT_VALUE: 'OutputValue', } return api_utils.reformat_dict_keys(keymap, o)
def format_resource_summary(r): """ Reformat engine output into the AWS "StackResourceSummary" format """ keymap = { engine_api.RES_UPDATED_TIME: 'LastUpdatedTimestamp', engine_api.RES_NAME: 'LogicalResourceId', engine_api.RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.RES_STATUS: 'ResourceStatus', engine_api.RES_STATUS_DATA: 'ResourceStatusReason', engine_api.RES_TYPE: 'ResourceType', } return api_utils.reformat_dict_keys(keymap, r)
def format_resource_summary(r): """Reformat engine output to AWS "StackResourceSummary" format.""" keymap = { rpc_api.RES_UPDATED_TIME: "LastUpdatedTimestamp", rpc_api.RES_NAME: "LogicalResourceId", rpc_api.RES_PHYSICAL_ID: "PhysicalResourceId", rpc_api.RES_STATUS_DATA: "ResourceStatusReason", rpc_api.RES_TYPE: "ResourceType", } result = api_utils.reformat_dict_keys(keymap, r) result["ResourceStatus"] = self._resource_status(r) return result
def format_stack_resource(r): """Reformat engine output into AWS "StackResource" format.""" keymap = { rpc_api.RES_DESCRIPTION: "Description", rpc_api.RES_NAME: "LogicalResourceId", rpc_api.RES_PHYSICAL_ID: "PhysicalResourceId", rpc_api.RES_STATUS_DATA: "ResourceStatusReason", rpc_api.RES_TYPE: "ResourceType", rpc_api.RES_STACK_ID: "StackId", rpc_api.RES_STACK_NAME: "StackName", rpc_api.RES_UPDATED_TIME: "Timestamp", } result = api_utils.reformat_dict_keys(keymap, r) result["ResourceStatus"] = self._resource_status(r) return self._id_format(result)
def format_resource_detail(r): # Reformat engine output into the AWS "StackResourceDetail" format keymap = { rpc_api.RES_DESCRIPTION: "Description", rpc_api.RES_UPDATED_TIME: "LastUpdatedTimestamp", rpc_api.RES_NAME: "LogicalResourceId", rpc_api.RES_METADATA: "Metadata", rpc_api.RES_PHYSICAL_ID: "PhysicalResourceId", rpc_api.RES_STATUS_DATA: "ResourceStatusReason", rpc_api.RES_TYPE: "ResourceType", rpc_api.RES_STACK_ID: "StackId", rpc_api.RES_STACK_NAME: "StackName", } result = api_utils.reformat_dict_keys(keymap, r) result["ResourceStatus"] = self._resource_status(r) return self._id_format(result)
def format_resource_detail(r): # Reformat engine output into the AWS "StackResourceDetail" format keymap = { engine_api.RES_DESCRIPTION: 'Description', engine_api.RES_UPDATED_TIME: 'LastUpdatedTimestamp', engine_api.RES_NAME: 'LogicalResourceId', engine_api.RES_METADATA: 'Metadata', engine_api.RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.RES_STATUS_DATA: 'ResourceStatusReason', engine_api.RES_TYPE: 'ResourceType', engine_api.RES_STACK_ID: 'StackId', engine_api.RES_STACK_NAME: 'StackName', } result = api_utils.reformat_dict_keys(keymap, r) result['ResourceStatus'] = self._resource_status(r) return self._id_format(result)
def format_stack_resource(r): """ Reformat engine output into the AWS "StackResource" format """ keymap = { engine_api.RES_DESCRIPTION: 'Description', engine_api.RES_NAME: 'LogicalResourceId', engine_api.RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.RES_STATUS: 'ResourceStatus', engine_api.RES_STATUS_DATA: 'ResourceStatusReason', engine_api.RES_TYPE: 'ResourceType', engine_api.RES_STACK_ID: 'StackId', engine_api.RES_STACK_NAME: 'StackName', engine_api.RES_UPDATED_TIME: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, r) return self._id_format(result)
def format_stack(s): """ Reformat engine output into the AWS "StackSummary" format """ keymap = { engine_api.STACK_CAPABILITIES: 'Capabilities', engine_api.STACK_CREATION_TIME: 'CreationTime', engine_api.STACK_DESCRIPTION: 'Description', engine_api.STACK_DISABLE_ROLLBACK: 'DisableRollback', engine_api.STACK_NOTIFICATION_TOPICS: 'NotificationARNs', engine_api.STACK_PARAMETERS: 'Parameters', engine_api.STACK_ID: 'StackId', engine_api.STACK_NAME: 'StackName', engine_api.STACK_STATUS_DATA: 'StackStatusReason', engine_api.STACK_TIMEOUT: 'TimeoutInMinutes', } if s[engine_api.STACK_UPDATED_TIME] is not None: keymap[engine_api.STACK_UPDATED_TIME] = 'LastUpdatedTime' result = api_utils.reformat_dict_keys(keymap, s) action = s[engine_api.STACK_ACTION] status = s[engine_api.STACK_STATUS] result['StackStatus'] = '_'.join((action, status)) # Reformat outputs, these are handled separately as they are # only present in the engine output for a completely created # stack result['Outputs'] = [] if engine_api.STACK_OUTPUTS in s: for o in s[engine_api.STACK_OUTPUTS]: result['Outputs'].append(format_stack_outputs(o)) # Reformat Parameters dict-of-dict into AWS API format # This is a list-of-dict with nasty "ParameterKey" : key # "ParameterValue" : value format. result['Parameters'] = [{'ParameterKey': k, 'ParameterValue': v} for (k, v) in result['Parameters'].items()] return self._id_format(result)
def format_stack_resource(r): """ Reformat engine output into the AWS "StackResource" format """ keymap = { rpc_api.RES_DESCRIPTION: 'Description', rpc_api.RES_NAME: 'LogicalResourceId', rpc_api.RES_PHYSICAL_ID: 'PhysicalResourceId', rpc_api.RES_STATUS_DATA: 'ResourceStatusReason', rpc_api.RES_TYPE: 'ResourceType', rpc_api.RES_STACK_ID: 'StackId', rpc_api.RES_STACK_NAME: 'StackName', rpc_api.RES_UPDATED_TIME: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, r) result['ResourceStatus'] = self._resource_status(r) return self._id_format(result)
def format_resource_detail(r): """ Reformat engine output into the AWS "StackResourceDetail" format """ keymap = { engine_api.RES_DESCRIPTION: 'Description', engine_api.RES_UPDATED_TIME: 'LastUpdatedTimestamp', engine_api.RES_NAME: 'LogicalResourceId', engine_api.RES_METADATA: 'Metadata', engine_api.RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.RES_STATUS: 'ResourceStatus', engine_api.RES_STATUS_DATA: 'ResourceStatusReason', engine_api.RES_TYPE: 'ResourceType', engine_api.RES_STACK_ID: 'StackId', engine_api.RES_STACK_NAME: 'StackName', } result = api_utils.reformat_dict_keys(keymap, r) return self._id_format(result)
def format_stack_event(e): """ Reformat engine output into the AWS "StackEvent" format """ keymap = { engine_api.EVENT_ID: 'EventId', engine_api.EVENT_RES_NAME: 'LogicalResourceId', engine_api.EVENT_RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.EVENT_RES_PROPERTIES: 'ResourceProperties', engine_api.EVENT_RES_STATUS: 'ResourceStatus', engine_api.EVENT_RES_STATUS_DATA: 'ResourceStatusData', engine_api.EVENT_RES_TYPE: 'ResourceType', engine_api.EVENT_STACK_ID: 'StackId', engine_api.EVENT_STACK_NAME: 'StackName', engine_api.EVENT_TIMESTAMP: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, e) return self._stackid_addprefix(result)
def format_stack(s): """ Reformat engine output into the AWS "StackSummary" format """ keymap = { engine_api.STACK_CAPABILITIES: 'Capabilities', engine_api.STACK_CREATION_TIME: 'CreationTime', engine_api.STACK_DESCRIPTION: 'Description', engine_api.STACK_DISABLE_ROLLBACK: 'DisableRollback', engine_api.STACK_UPDATED_TIME: 'LastUpdatedTime', engine_api.STACK_NOTIFICATION_TOPICS: 'NotificationARNs', engine_api.STACK_PARAMETERS: 'Parameters', engine_api.STACK_ID: 'StackId', engine_api.STACK_NAME: 'StackName', engine_api.STACK_STATUS_DATA: 'StackStatusReason', engine_api.STACK_TIMEOUT: 'TimeoutInMinutes', } result = api_utils.reformat_dict_keys(keymap, s) action = s[engine_api.STACK_ACTION] status = s[engine_api.STACK_STATUS] result['StackStatus'] = '_'.join((action, status)) # Reformat outputs, these are handled separately as they are # only present in the engine output for a completely created # stack result['Outputs'] = [] if engine_api.STACK_OUTPUTS in s: for o in s[engine_api.STACK_OUTPUTS]: result['Outputs'].append(format_stack_outputs(o)) # Reformat Parameters dict-of-dict into AWS API format # This is a list-of-dict with nasty "ParameterKey" : key # "ParameterValue" : value format. result['Parameters'] = [{ 'ParameterKey': k, 'ParameterValue': v } for (k, v) in result['Parameters'].items()] return self._id_format(result)
def format_stack_event(e): """Reformat engine output into AWS "StackEvent" format.""" keymap = { rpc_api.EVENT_ID: "EventId", rpc_api.EVENT_RES_NAME: "LogicalResourceId", rpc_api.EVENT_RES_PHYSICAL_ID: "PhysicalResourceId", rpc_api.EVENT_RES_PROPERTIES: "ResourceProperties", rpc_api.EVENT_RES_STATUS_DATA: "ResourceStatusReason", rpc_api.EVENT_RES_TYPE: "ResourceType", rpc_api.EVENT_STACK_ID: "StackId", rpc_api.EVENT_STACK_NAME: "StackName", rpc_api.EVENT_TIMESTAMP: "Timestamp", } result = api_utils.reformat_dict_keys(keymap, e) action = e[rpc_api.EVENT_RES_ACTION] status = e[rpc_api.EVENT_RES_STATUS] result["ResourceStatus"] = "_".join((action, status)) result["ResourceProperties"] = jsonutils.dumps(result["ResourceProperties"]) return self._id_format(result)
def format_metric_alarm(a): """ Reformat engine output into the AWS "MetricAlarm" format """ keymap = { engine_api.WATCH_ACTIONS_ENABLED: 'ActionsEnabled', engine_api.WATCH_ALARM_ACTIONS: 'AlarmActions', engine_api.WATCH_TOPIC: 'AlarmArn', engine_api.WATCH_UPDATED_TIME: 'AlarmConfigurationUpdatedTimestamp', engine_api.WATCH_DESCRIPTION: 'AlarmDescription', engine_api.WATCH_NAME: 'AlarmName', engine_api.WATCH_COMPARISON: 'ComparisonOperator', engine_api.WATCH_DIMENSIONS: 'Dimensions', engine_api.WATCH_PERIODS: 'EvaluationPeriods', engine_api.WATCH_INSUFFICIENT_ACTIONS: 'InsufficientDataActions', engine_api.WATCH_METRIC_NAME: 'MetricName', engine_api.WATCH_NAMESPACE: 'Namespace', engine_api.WATCH_OK_ACTIONS: 'OKActions', engine_api.WATCH_PERIOD: 'Period', engine_api.WATCH_STATE_REASON: 'StateReason', engine_api.WATCH_STATE_REASON_DATA: 'StateReasonData', engine_api.WATCH_STATE_UPDATED_TIME: 'StateUpdatedTimestamp', engine_api.WATCH_STATE_VALUE: 'StateValue', engine_api.WATCH_STATISTIC: 'Statistic', engine_api.WATCH_THRESHOLD: 'Threshold', engine_api.WATCH_UNIT: 'Unit' } # AWS doesn't return StackId in the main MetricAlarm # structure, so we add StackId as a dimension to all responses a[engine_api.WATCH_DIMENSIONS].append( {'StackId': a[engine_api.WATCH_STACK_ID]}) # Reformat dimensions list into AWS API format a[engine_api.WATCH_DIMENSIONS] = self._reformat_dimensions( a[engine_api.WATCH_DIMENSIONS]) return api_utils.reformat_dict_keys(keymap, a)
def format_metric_alarm(a): """ Reformat engine output into the AWS "MetricAlarm" format """ keymap = { engine_api.WATCH_ACTIONS_ENABLED: 'ActionsEnabled', engine_api.WATCH_ALARM_ACTIONS: 'AlarmActions', engine_api.WATCH_TOPIC: 'AlarmArn', engine_api.WATCH_UPDATED_TIME: 'AlarmConfigurationUpdatedTimestamp', engine_api.WATCH_DESCRIPTION: 'AlarmDescription', engine_api.WATCH_NAME: 'AlarmName', engine_api.WATCH_COMPARISON: 'ComparisonOperator', engine_api.WATCH_DIMENSIONS: 'Dimensions', engine_api.WATCH_PERIODS: 'EvaluationPeriods', engine_api.WATCH_INSUFFICIENT_ACTIONS: 'InsufficientDataActions', engine_api.WATCH_METRIC_NAME: 'MetricName', engine_api.WATCH_NAMESPACE: 'Namespace', engine_api.WATCH_OK_ACTIONS: 'OKActions', engine_api.WATCH_PERIOD: 'Period', engine_api.WATCH_STATE_REASON: 'StateReason', engine_api.WATCH_STATE_REASON_DATA: 'StateReasonData', engine_api.WATCH_STATE_UPDATED_TIME: 'StateUpdatedTimestamp', engine_api.WATCH_STATE_VALUE: 'StateValue', engine_api.WATCH_STATISTIC: 'Statistic', engine_api.WATCH_THRESHOLD: 'Threshold', engine_api.WATCH_UNIT: 'Unit'} # AWS doesn't return StackId in the main MetricAlarm # structure, so we add StackId as a dimension to all responses a[engine_api.WATCH_DIMENSIONS].append({'StackId': a[engine_api.WATCH_STACK_ID] }) # Reformat dimensions list into AWS API format a[engine_api.WATCH_DIMENSIONS] = self._reformat_dimensions( a[engine_api.WATCH_DIMENSIONS]) return api_utils.reformat_dict_keys(keymap, a)
def format_stack_event(e): """Reformat engine output into AWS "StackEvent" format.""" keymap = { rpc_api.EVENT_ID: 'EventId', rpc_api.EVENT_RES_NAME: 'LogicalResourceId', rpc_api.EVENT_RES_PHYSICAL_ID: 'PhysicalResourceId', rpc_api.EVENT_RES_PROPERTIES: 'ResourceProperties', rpc_api.EVENT_RES_STATUS_DATA: 'ResourceStatusReason', rpc_api.EVENT_RES_TYPE: 'ResourceType', rpc_api.EVENT_STACK_ID: 'StackId', rpc_api.EVENT_STACK_NAME: 'StackName', rpc_api.EVENT_TIMESTAMP: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, e) action = e[rpc_api.EVENT_RES_ACTION] status = e[rpc_api.EVENT_RES_STATUS] result['ResourceStatus'] = '_'.join((action, status)) result['ResourceProperties'] = jsonutils.dumps(result[ 'ResourceProperties']) return self._id_format(result)
def format_stack_event(e): """ Reformat engine output into the AWS "StackEvent" format """ keymap = { engine_api.EVENT_ID: 'EventId', engine_api.EVENT_RES_NAME: 'LogicalResourceId', engine_api.EVENT_RES_PHYSICAL_ID: 'PhysicalResourceId', engine_api.EVENT_RES_PROPERTIES: 'ResourceProperties', engine_api.EVENT_RES_STATUS: 'ResourceStatus', engine_api.EVENT_RES_STATUS_DATA: 'ResourceStatusReason', engine_api.EVENT_RES_TYPE: 'ResourceType', engine_api.EVENT_STACK_ID: 'StackId', engine_api.EVENT_STACK_NAME: 'StackName', engine_api.EVENT_TIMESTAMP: 'Timestamp', } result = api_utils.reformat_dict_keys(keymap, e) result['ResourceProperties'] = json.dumps( result['ResourceProperties']) return self._stackid_format(result)
def format_stack_outputs(o): keymap = { rpc_api.OUTPUT_DESCRIPTION: "Description", rpc_api.OUTPUT_KEY: "OutputKey", rpc_api.OUTPUT_VALUE: "OutputValue", } def replacecolon(d): return dict(map(lambda k_v: (k_v[0].replace(":", "."), k_v[1]), d.items())) def transform(attrs): """Recursively replace all `:` with `.` in dict keys. After that they are not interpreted as xml namespaces. """ new = replacecolon(attrs) for key, value in new.items(): if isinstance(value, dict): new[key] = transform(value) return new return api_utils.reformat_dict_keys(keymap, transform(o))
def format_stack(s): """Reformat engine output into the AWS "StackSummary" format.""" keymap = { rpc_api.STACK_CAPABILITIES: "Capabilities", rpc_api.STACK_CREATION_TIME: "CreationTime", rpc_api.STACK_DESCRIPTION: "Description", rpc_api.STACK_DISABLE_ROLLBACK: "DisableRollback", rpc_api.STACK_NOTIFICATION_TOPICS: "NotificationARNs", rpc_api.STACK_PARAMETERS: "Parameters", rpc_api.STACK_ID: "StackId", rpc_api.STACK_NAME: "StackName", rpc_api.STACK_STATUS_DATA: "StackStatusReason", rpc_api.STACK_TIMEOUT: "TimeoutInMinutes", } if s[rpc_api.STACK_UPDATED_TIME] is not None: keymap[rpc_api.STACK_UPDATED_TIME] = "LastUpdatedTime" result = api_utils.reformat_dict_keys(keymap, s) action = s[rpc_api.STACK_ACTION] status = s[rpc_api.STACK_STATUS] result["StackStatus"] = "_".join((action, status)) # Reformat outputs, these are handled separately as they are # only present in the engine output for a completely created # stack result["Outputs"] = [] if rpc_api.STACK_OUTPUTS in s: for o in s[rpc_api.STACK_OUTPUTS]: result["Outputs"].append(format_stack_outputs(o)) # Reformat Parameters dict-of-dict into AWS API format # This is a list-of-dict with nasty "ParameterKey" : key # "ParameterValue" : value format. result["Parameters"] = [{"ParameterKey": k, "ParameterValue": v} for (k, v) in result["Parameters"].items()] return self._id_format(result)
def format_stack_outputs(o): keymap = { engine_api.OUTPUT_DESCRIPTION: 'Description', engine_api.OUTPUT_KEY: 'OutputKey', engine_api.OUTPUT_VALUE: 'OutputValue', } def replacecolon(d): return dict(map(lambda (k, v): (k.replace(':', '.'), v), d.items())) def transform(attrs): """ Recursively replace all : with . in dict keys so that they are not interpreted as xml namespaces. """ new = replacecolon(attrs) for key, value in new.items(): if isinstance(value, dict): new[key] = transform(value) return new return api_utils.reformat_dict_keys(keymap, transform(o))
def format_stack_summary(s): """ Reformat engine output into the AWS "StackSummary" format """ # Map the engine-api format to the AWS StackSummary datatype keymap = { engine_api.STACK_CREATION_TIME: 'CreationTime', engine_api.STACK_UPDATED_TIME: 'LastUpdatedTime', engine_api.STACK_ID: 'StackId', engine_api.STACK_NAME: 'StackName', engine_api.STACK_STATUS: 'StackStatus', engine_api.STACK_STATUS_DATA: 'StackStatusReason', engine_api.STACK_TMPL_DESCRIPTION: 'TemplateDescription', } result = api_utils.reformat_dict_keys(keymap, s) # AWS docs indicate DeletionTime is ommitted for current stacks # This is still TODO in the engine, we don't keep data for # stacks after they are deleted if engine_api.STACK_DELETION_TIME in s: result['DeletionTime'] = s[engine_api.STACK_DELETION_TIME] return self._stackid_format(result)
def test_reformat_dict_keys(self): keymap = {"foo": "bar"} data = {"foo": 123} expected = {"bar": 123} result = api_utils.reformat_dict_keys(keymap, data) self.assertEqual(result, expected)
def test_reformat_dict_keys_missing(self): keymap = {"foo": "bar", "foo2": "bar2"} data = {"foo": 123} expected = {"bar": 123} result = api_utils.reformat_dict_keys(keymap, data) self.assertEqual(expected, result)
def test_reformat_dict_keys(self): keymap = {"foo": "bar"} data = {"foo": 123} expected = {"bar": 123} result = api_utils.reformat_dict_keys(keymap, data) self.assertEqual(expected, result)
def test_reformat_dict_keys_missing(self): keymap = {"foo": "bar", "foo2": "bar2"} data = {"foo": 123} expected = {"bar": 123} result = api_utils.reformat_dict_keys(keymap, data) self.assertEqual(result, expected)