From b632df3aa4586717ddd08a937e060023c00a2ef4 Mon Sep 17 00:00:00 2001 From: Taro Sato Date: Sun, 16 Oct 2016 21:49:10 -0700 Subject: [PATCH] Generate proper empty value for XML/JSON --- moto/core/responses.py | 31 +++++++++++++++++++++++++------ moto/emr/models.py | 11 +++++++++-- tests/test_emr/test_emr_boto3.py | 13 +++++++------ 3 files changed, 41 insertions(+), 14 deletions(-) diff --git a/moto/core/responses.py b/moto/core/responses.py index 11b83326e..437937207 100644 --- a/moto/core/responses.py +++ b/moto/core/responses.py @@ -1,6 +1,7 @@ from __future__ import unicode_literals import datetime import json +import logging import re from boto.exception import JSONResponseError @@ -17,6 +18,9 @@ from moto.compat import OrderedDict from moto.core.utils import camelcase_to_underscores, method_names_from_class +log = logging.getLogger(__name__) + + def _decode_dict(d): decoded = {} for key, value in d.items(): @@ -544,11 +548,20 @@ def xml_to_json_response(service_spec, operation, xml, result_node=None): od = OrderedDict() for k, v in value.items(): - if k.startswith('@') or v is None: + if k.startswith('@'): + continue + + if k not in spec: + # this can happen when with an older version of + # botocore for which the node in XML template is not + # defined in service spec. + log.warning('Field %s is not defined by the botocore version in use', k) continue if spec[k]['type'] == 'list': - if len(spec[k]['member']) == 1: + if v is None: + od[k] = [] + elif len(spec[k]['member']) == 1: if isinstance(v['member'], list): od[k] = transform(v['member'], spec[k]['member']) else: @@ -560,11 +573,17 @@ def xml_to_json_response(service_spec, operation, xml, result_node=None): else: raise ValueError('Malformatted input') elif spec[k]['type'] == 'map': - key = from_str(v['entry']['key'], spec[k]['key']) - val = from_str(v['entry']['value'], spec[k]['value']) - od[k] = {key: val} + if v is None: + od[k] = {} + else: + key = from_str(v['entry']['key'], spec[k]['key']) + val = from_str(v['entry']['value'], spec[k]['value']) + od[k] = {key: val} else: - od[k] = transform(v, spec[k]) + if v is None: + od[k] = None + else: + od[k] = transform(v, spec[k]) return od dic = xmltodict.parse(xml) diff --git a/moto/emr/models.py b/moto/emr/models.py index acc573698..ece4c9979 100644 --- a/moto/emr/models.py +++ b/moto/emr/models.py @@ -24,12 +24,19 @@ class FakeBootstrapAction(object): class FakeInstanceGroup(object): - def __init__(self, instance_count, instance_role, instance_type, market, name, - id=None, bid_price=None): + def __init__(self, instance_count, instance_role, instance_type, + market='ON_DEMAND', name=None, id=None, bid_price=None): self.id = id or random_instance_group_id() self.bid_price = bid_price self.market = market + if name is None: + if instance_role == 'MASTER': + name = 'master' + elif instance_role == 'CORE': + name = 'slave' + else: + name = 'Task instance group' self.name = name self.num_instances = instance_count self.role = instance_role diff --git a/tests/test_emr/test_emr_boto3.py b/tests/test_emr/test_emr_boto3.py index f389c1900..4e297e620 100644 --- a/tests/test_emr/test_emr_boto3.py +++ b/tests/test_emr/test_emr_boto3.py @@ -194,8 +194,8 @@ def test_describe_job_flow(): jf['LogUri'].should.equal(args['LogUri']) jf['Name'].should.equal(args['Name']) jf['ServiceRole'].should.equal(args['ServiceRole']) - jf.shouldnt.have.key('Steps') - jf.shouldnt.have.key('SupportedProducts') + jf['Steps'].should.equal([]) + jf['SupportedProducts'].should.equal([]) jf['VisibleToAllUsers'].should.equal(True) @@ -254,7 +254,7 @@ def test_run_job_flow(): resp['LogUri'].should.equal(args['LogUri']) resp['VisibleToAllUsers'].should.equal(args['VisibleToAllUsers']) resp['Instances']['NormalizedInstanceHours'].should.equal(0) - resp.shouldnt.have.key('Steps') + resp['Steps'].should.equal([]) @mock_emr @@ -379,10 +379,11 @@ def test_bootstrap_actions(): {'Name': 'bs1', 'ScriptBootstrapAction': { 'Args': ['arg1', 'arg2'], - 'Path': 'path/to/script'}}, + 'Path': 's3://path/to/script'}}, {'Name': 'bs2', 'ScriptBootstrapAction': { - 'Path': 'path/to/anotherscript'}} + 'Args': [], + 'Path': 's3://path/to/anotherscript'}} ] client = boto3.client('emr', region_name='us-east-1') @@ -583,4 +584,4 @@ def test_tags(): client.remove_tags(ResourceId=cluster_id, TagKeys=[t['Key'] for t in input_tags]) resp = client.describe_cluster(ClusterId=cluster_id)['Cluster'] - resp.shouldnt.have.key('Tags') + resp['Tags'].should.equal([])