예제 #1
0
    def test_diff_with_changes(self):

        # Setup

        new = {"A": "AA", "B": "BBBB", "D": "DD"}
        old = {"A": "AA", "B": "BB", "C": "CC"}

        # Execute

        target = patch.OperationListBuilder()
        target.diff('/', old, new)
        result = target.get()

        # Verify

        expected = [{
            'op': patch.OperationListBuilder.OP_REPLACE,
            'path': '/B',
            'value': 'BBBB'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/D',
            'value': 'DD'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/C'
        }]

        result_dict = {e['path']: e for e in result}
        expected_dict = {e['path']: e for e in expected}

        print 'EXPECTED', expected_dict
        print 'ACTUAL  ', result_dict

        self.assertEquals(expected_dict, result_dict)
def get_rest_api_stage_update_patch_operations(current_stage, props):

    builder = patch.OperationListBuilder()

    if current_stage.get('cacheClusterEnabled',
                         False) != props.CacheClusterEnabled:
        builder.replace('/cacheClusterEnabled', props.CacheClusterEnabled)

    if current_stage.get('cacheClusterSize', '') != props.CacheClusterSize:
        builder.replace('/cacheClusterSize', props.CacheClusterSize)

    builder.diff('/variables/', current_stage.get('variables', {}),
                 props.StageVariables)

    # TODO: support MethodSettings. https://issues.labcollab.net/browse/LMBR-32185
    #
    # See https://docs.aws.amazon.com/apigateway/api-reference/resource/stage/#methodSettings
    # for the paths needed to update these values. Note that the paths for these values have
    # the form /a~1b~1c/GET (slashes in the resource path replaced by ~1, and GET is any HTTP
    # verb).
    #
    # We can't remove individual values, we can only replace them with default values if they
    # aren't specified. However, if a path/method exists in current_stage but not in props, then
    # all the settings should be removed using a path like /a~1b~1c/GET.
    #
    # The wildcards may need some special handling.

    return builder.get()
예제 #3
0
    def test_diff_nested_with_no_changes(self):

        # Setup

        new = {"Top": {"A": "AA", "B": "BB", "Nested": {"P": "PP"}}}
        old = {"Top": {"A": "AA", "B": "BB", "Nested": {"P": "PP"}}}

        # Execute

        target = patch.OperationListBuilder()
        target.diff('/', old, new)
        result = target.get()

        # Verify

        self.assertEquals(result, [])
예제 #4
0
    def test_diff_nested_with_changes(self):

        # Setup

        new = {
            "Top": {
                "A": "AA",
                "B": "BBBB",
                "D": "DD",
                "Nested": {
                    "P": "PP",
                    "Q": "QQQQ",
                    "S": "SS"
                }
            },
            "NewTop": {
                "W": "WW",
                "X": "XXXX",
                "Z": "ZZ"
            }
        }

        old = {
            "Top": {
                "A": "AA",
                "B": "BB",
                "C": "CC",
                "Nested": {
                    "P": "PP",
                    "Q": "QQ",
                    "R": "RR"
                }
            },
            "OldTop": {
                "W": "WW",
                "X": "XX",
                "Y": "YY"
            }
        }

        # Execute

        target = patch.OperationListBuilder()
        target.diff('/', old, new)
        result = target.get()

        # Verify

        expected = [{
            'op': patch.OperationListBuilder.OP_REPLACE,
            'path': '/Top/B',
            'value': 'BBBB'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/Top/C'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/Top/D',
            'value': 'DD'
        }, {
            'op': patch.OperationListBuilder.OP_REPLACE,
            'path': '/Top/Nested/Q',
            'value': 'QQQQ'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/Top/Nested/R'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/Top/Nested/S',
            'value': 'SS'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/NewTop/W',
            'value': 'WW'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/NewTop/X',
            'value': 'XXXX'
        }, {
            'op': patch.OperationListBuilder.OP_ADD,
            'path': '/NewTop/Z',
            'value': 'ZZ'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/OldTop/W'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/OldTop/X'
        }, {
            'op': patch.OperationListBuilder.OP_REMOVE,
            'path': '/OldTop/Y'
        }]

        result_dict = {e['path']: e for e in result}
        expected_dict = {e['path']: e for e in expected}

        print 'EXPECTED', expected_dict
        print 'ACTUAL  ', result_dict

        self.assertEquals(expected_dict, result_dict)
예제 #5
0
def get_rest_api_stage_update_patch_operations(current_stage, props):
    builder = patch.OperationListBuilder()

    if current_stage.get('cacheClusterEnabled',
                         False) != props.CacheClusterEnabled:
        builder.replace('/cacheClusterEnabled', props.CacheClusterEnabled)

    if current_stage.get('cacheClusterSize', '') != props.CacheClusterSize:
        builder.replace('/cacheClusterSize', props.CacheClusterSize)

    builder.diff('/variables/', current_stage.get('variables', {}),
                 props.StageVariables)

    # MethodSettings modifications - Set in your resource-template.json's ServiceApi Definition as:
    # "Properties": {
    #       "MethodSettings": {
    #           "/client/content": {
    #               "POST": {
    #                   "throttlingBurstLimit": 177
    #               }
    #           }
    #       }
    #   }
    # }
    settings_obj = current_stage.get('methodSettings', {})
    existing_paths = [
        curPath for curPath, curSettings in iteritems(settings_obj)
    ]

    props_settings = props.MethodSettings

    for path_str in dir(props_settings):
        path_info = getattr(props_settings, path_str)
        if not isinstance(path_info, properties._Properties):
            continue

        for requestVerb in dir(path_info):
            settings_path = path_str.replace('/', '~1') + '/' + requestVerb

            if settings_path in existing_paths:
                existing_paths.remove(settings_path)

            update_path = '/' + settings_path
            path_settings = getattr(path_info, requestVerb)
            if not isinstance(path_settings, properties._Properties):
                continue
            for method_base, method_update in [
                ('throttlingBurstLimit', '/throttling/burstLimit'),
                ('throttlingRateLimit', '/throttling/rateLimit'),
                ('cacheDataEncrypted', '/caching/dataEncrypted'),
                ('cacheTtlInSeconds', '/caching/ttlInSeconds'),
                ('cachingEnabled', '/caching/enabled'),
                ('dataTraceEnabled', '/logging/dataTrace'),
                ('loggingLevel', '/logging/loglevel'),
                ('metricsEnabled', '/metrics/enabled')
            ]:
                cur_settings = settings_obj.get(settings_path, {})
                cur_value = cur_settings.get(method_base, '')
                prop_value = getattr(path_settings, method_base)
                if cur_value != prop_value:
                    builder.replace(update_path + method_update,
                                    str(prop_value))

    for thisPath in existing_paths:
        builder.remove('/' + thisPath)

    return builder.get()