Exemple #1
0
    def test_seek_regex_in_dict_value_nested_dict(self):
        haystack = dict(search_key=dict(something='value'))
        key_name = 'something'
        needle = 'val.*'
        expected = ['value']

        self.assertEqual(seek_regex_key_in_dict_values(haystack, key_name, needle), expected)
def its_key_condition_be_value(_step_obj,
                               key,
                               condition,
                               value,
                               stash=Null,
                               depth=0):
    if condition not in ('must', 'must not'):
        raise TerraformComplianceNotImplemented(
            'This step only accepts "must" and "must not" as a condition.')

    if stash is Null:
        stash = _step_obj.context.stash

    if not stash or stash is Null:
        Error(
            _step_obj,
            'No entities found for this step to process. Check your filtering steps in this scenario.'
        )
        return False

    found_values = []
    for entity in stash:
        if isinstance(entity, dict):
            found_values.extend(
                seek_regex_key_in_dict_values(entity, key, value))
        elif isinstance(entity, list):
            for element in entity:
                found_values.extend(
                    its_key_condition_be_value(_step_obj, key, condition,
                                               element, entity, depth + 1))
        elif isinstance(entity,
                        (str, int, bool)) and (str(entity).lower == key.lower
                                               or str(entity) == value.lower):
            found_values.append(entity)

    # Return the values to the parent call.
    if depth > 0:
        return found_values

    condition = condition == 'must'
    found_values = [values for values in found_values if values is not None]

    obj_address = _step_obj.context.name
    if hasattr(_step_obj.context, 'address'):
        obj_address = _step_obj.context.address
    elif hasattr(_step_obj.context, 'addresses'):
        obj_address = ', '.join(_step_obj.context.addresses)

    if found_values and not condition:
        Error(
            _step_obj, 'Found {}({}) in {} property of {}.'.format(
                value, ', '.join(found_values), key, obj_address))
    elif not found_values and condition:
        Error(
            _step_obj, 'Can not find {} in {} property of {}.'.format(
                value, key, obj_address))

    return True
def its_value_condition_match_the_search_regex_regex(_step_obj,
                                                     condition,
                                                     search_regex,
                                                     _stash=None):
    def fail(condition):
        text = 'matches' if condition == 'must not' else 'does not match'
        raise Failure('{} property in {} {} {} with {} regex. '
                      'It is set to {}.'.format(
                          _step_obj.context.property_name,
                          _step_obj.context.name, _step_obj.context.type, text,
                          regex, values))

    regex = r'{}'.format(search_regex)
    values = _step_obj.context.stash if _stash is None else _stash

    if type(values) is str or type(values) is int or type(values) is bool:
        matches = re.match(regex, str(values), flags=re.IGNORECASE)

        if (condition == 'must'
                and matches is None) or (condition == "must not"
                                         and matches is not None):
            fail(condition)

    elif type(values) is list:
        for value in values:
            its_value_condition_match_the_search_regex_regex(
                _step_obj, condition, search_regex, value)

    elif type(values) is dict:
        if values.get('values') is not None:
            values = its_value_condition_match_the_search_regex_regex(
                _step_obj, condition, search_regex, values['values'])
        else:
            values = seek_regex_key_in_dict_values(
                values, _step_obj.context.property_name, search_regex)

        if (condition == 'must' and values == []) or (condition == "must not"
                                                      and values != []):
            fail(condition)
def it_condition_contain_something(_step_obj, something):
    prop_list = []

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if type(resource) is not dict:
                resource = {
                    'values': resource,
                    'address': resource,
                    'type': _step_obj.context.name
                }

            values = resource.get('values', resource.get('expressions', {}))

            found_value = Null
            found_key = Null
            if type(values) is dict:
                found_key = values.get(something,
                                       seek_key_in_dict(values, something))
                if type(found_key) is not list:
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(
                        found_key) == 1 else found_key

                    if type(found_key) is dict:
                        found_value = jsonify(
                            found_key.get(something, found_key))
                    else:
                        found_value = found_key
            elif type(values) is list:
                found_value = []

                for value in values:

                    if type(value) is dict:
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(
                                value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(
                            found_key) == 1 else found_key

                        if type(found_key) is dict:
                            found_value.append(
                                jsonify(found_key.get(something, found_key)))

            if type(found_value) is dict and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value is not Null and found_value != [] and found_value != '' and found_value != {}:
                prop_list.append({
                    'address': resource['address'],
                    'values': found_value,
                    'type': _step_obj.context.name
                })

            elif 'must' in _step_obj.context_sensitive_sentence:
                raise Failure('{} ({}) does not have {} property.'.format(
                    resource['address'], resource.get('type', ''), something))

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something
            return True

        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Can not find any {} property for {} resource in '
                  'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        values = seek_key_in_dict(_step_obj.context.stash, something)

        if values:
            _step_obj.context.stash = values
            _step_obj.context.property_name = something
            return True

    skip_step(
        _step_obj,
        resource=_step_obj.context.name,
        message='Skipping the step since {} type does not have {} property.'.
        format(_step_obj.context.type, something))
Exemple #5
0
def it_must_contain_something(_step_obj, something, inherited_values=Null):
    prop_list = []

    _step_obj.context.stash = inherited_values if inherited_values is not Null else _step_obj.context.stash

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if not isinstance(resource, dict) \
                    or 'values' not in resource \
                    or 'address' not in resource \
                    or 'type' not in resource:
                resource = {
                    'values': resource,
                    'address': resource,
                    'type': _step_obj.context.name
                }

            values = resource.get('values', resource.get('expressions', {}))
            if not values:
                values = seek_key_in_dict(resource, something)

            found_value = Null
            found_key = Null
            if isinstance(values, dict):
                found_key = values.get(something,
                                       seek_key_in_dict(values, something))
                if not isinstance(found_key, list):
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(
                        found_key
                    ) == 1 and something in found_key[0] else found_key

                    if isinstance(found_key, dict):
                        found_value = jsonify(
                            found_key.get(something, found_key))
                        found_value = found_value if found_value not in (
                            [], '') else found_key
                    else:
                        found_value = found_key
            elif isinstance(values, list):
                found_value = []

                for value in values:

                    if isinstance(value, dict):
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(
                                value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    elif isinstance(value, list):
                        found_key, found_value = it_must_contain_something(
                            _step_obj, something, value)

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(
                            found_key) == 1 else found_key

                        if isinstance(found_key, dict):
                            found_value.append(
                                jsonify(found_key.get(something, found_key)))

            if isinstance(found_value,
                          dict) and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value is not Null and found_value != [] and found_value != '' and found_value != {}:
                prop_list.append({
                    'address': resource['address'],
                    'values': found_value,
                    'type': _step_obj.context.name
                })

            else:
                Error(
                    _step_obj, '{} ({}) does not have {} property.'.format(
                        resource['address'], resource.get('type', ''),
                        something))

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something
            return something, prop_list

    elif _step_obj.context.type == 'provider':
        for provider_data in _step_obj.context.stash:
            values = seek_key_in_dict(provider_data, something)

            if values:
                _step_obj.context.stash = values
                _step_obj.context.property_name = something
                _step_obj.context.address = '{}.{}'.format(
                    provider_data.get('name', _step_obj.context.addresses),
                    provider_data.get('alias', "\b"))
                return True
            else:
                Error(
                    _step_obj, '{} {} does not have {} property.'.format(
                        _step_obj.context.addresses, _step_obj.context.type,
                        something))

        Error(
            _step_obj, '{} {} does not have {} property.'.format(
                _step_obj.context.addresses, _step_obj.context.type,
                something))
def it_does_not_have_something(_step_obj, something, inherited_values=Null):
    prop_list = []

    _step_obj.context.stash = inherited_values if inherited_values is not Null else _step_obj.context.stash

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if not isinstance(resource, dict) \
                    or 'values' not in resource \
                    or 'address' not in resource \
                    or 'type' not in resource:
                resource = {'values': resource,
                            'address': resource,
                            'type': _step_obj.context.name}

            values = resource.get('values', resource.get('expressions', {}))
            if not values:
                values = seek_key_in_dict(resource, something)

            found_value = Null
            found_key = Null
            if isinstance(values, dict):
                found_key = values.get(something, seek_key_in_dict(values, something))
                if not isinstance(found_key, list):
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(found_key) == 1 and something in found_key[0] else found_key

                    if isinstance(found_key, dict):
                        found_value = jsonify(found_key.get(something, found_key))
                    else:
                        found_value = found_key
            elif isinstance(values, list):
                found_value = []

                for value in values:

                    if isinstance(value, dict):
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    elif isinstance(value, list):
                        found_key, found_value = it_has_something(_step_obj, something, value)

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(found_key) == 1 else found_key

                        if isinstance(found_key, dict):
                            found_value.append(jsonify(found_key.get(something, found_key)))

            if isinstance(found_value, dict) and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value is not Null and found_value != [] and found_value != '' and found_value != {}:
                prop_list.append(resource['address'])


        prop_list = [resource for resource in _step_obj.context.stash if resource['address'] not in prop_list]
        _step_obj.context.property_name = something

        if prop_list:
            _step_obj.context.stash = prop_list
            return something, prop_list

        if _step_obj.state != Step.State.FAILED:
            skip_step(_step_obj,
                      resource=_step_obj.context.name,
                      message='All objects ({}) coming from previous step has {} '
                              'property.'.format(_step_obj.context.name, something))

    elif _step_obj.context.type == 'provider':
        stash = []
        for provider_data in _step_obj.context.stash:
            values = seek_key_in_dict(provider_data, something)

            if values:
                return False
            else:
                stash.append(provider_data)

        if stash:
            _step_obj.context.stash = stash
            _step_obj.context.property_name = something
            return True


    return True
def it_contains_something_old(_step_obj, something, inherited_values=Null):
    console_write("\t{} {}: {}".format(Defaults().warning_icon,
                                       Defaults().warning_colour('WARNING'),
                                       Defaults().info_colour('"When it contains {}" step functionality will be changed'
                                                              ' on future versions and the functionality will be same '
                                                              'as "When it has {}" step. Please use the '
                                                              'latter.'.format(something, something))))
    prop_list = []

    _step_obj.context.stash = inherited_values if inherited_values is not Null else _step_obj.context.stash

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if not isinstance(resource, dict) \
                    or 'values' not in resource \
                    or 'address' not in resource \
                    or 'type' not in resource:
                resource = {'values': resource,
                            'address': resource,
                            'type': _step_obj.context.name}

            values = resource.get('values', resource.get('expressions', {}))
            if not values:
                values = seek_key_in_dict(resource, something)

            found_value = Null
            found_key = Null
            if isinstance(values, dict):
                found_key = values.get(something, seek_key_in_dict(values, something))
                if not isinstance(found_key, list):
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(found_key) == 1 and something in found_key[0] else found_key

                    if isinstance(found_key, dict):
                        found_value = jsonify(found_key.get(something, found_key))
                    else:
                        found_value = found_key
            elif isinstance(values, list):
                found_value = []

                for value in values:

                    if isinstance(value, dict):
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    elif isinstance(value, list):
                        found_key, found_value = it_contains_something_old(_step_obj, something, value)

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(found_key) == 1 else found_key

                        if isinstance(found_key, dict):
                            found_value.append(jsonify(found_key.get(something, found_key)))

            if isinstance(found_value, dict) and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value is not Null and found_value != [] and found_value != '' and found_value != {}:
                prop_list.append({'address': resource['address'],
                                  'values': found_value,
                                  'type': _step_obj.context.name})

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something

            return something, prop_list

        if _step_obj.state != Step.State.FAILED:
            skip_step(_step_obj,
                      resource=_step_obj.context.name,
                      message='Can not find any {} property for {} resource in '
                              'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        for provider_data in _step_obj.context.stash:
            values = seek_key_in_dict(provider_data, something)

            if values:
                _step_obj.context.stash = values
                _step_obj.context.property_name = something
                _step_obj.context.address = '{}.{}'.format(provider_data.get('name', _step_obj.context.addresses),
                                                           provider_data.get('alias', "\b"))
                return True

    if _step_obj.state != Step.State.FAILED:
        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Skipping the step since {} type does not have {} property.'.format(_step_obj.context.type,
                                                                                              something))
def it_has_something(_step_obj, something, inherited_values=Null):
    prop_list = []

    _step_obj.context.stash = inherited_values if inherited_values is not Null else _step_obj.context.stash

    if _step_obj.context.type in ('resource', 'data'):
        for resource in _step_obj.context.stash:
            if not isinstance(resource, dict) \
                    or 'values' not in resource \
                    or 'address' not in resource \
                    or 'type' not in resource:
                resource = {'values': resource,
                            'address': resource,
                            'type': _step_obj.context.name}

            values = resource.get('values', resource.get('expressions', {}))
            if not values:
                values = seek_key_in_dict(resource, something)

            found_value = Null
            found_key = Null
            if isinstance(values, dict):
                found_key = values.get(something, seek_key_in_dict(values, something))
                if not isinstance(found_key, list):
                    found_key = [{something: found_key}]

                if len(found_key):
                    found_key = found_key[0] if len(found_key) == 1 and something in found_key[0] else found_key

                    if isinstance(found_key, dict):
                        found_value = jsonify(found_key.get(something, found_key))
                    else:
                        found_value = found_key
            elif isinstance(values, list):
                found_value = []

                for value in values:

                    if isinstance(value, dict):
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    elif isinstance(value, list):
                        found_key, found_value = it_has_something(_step_obj, something, value)

                    if found_key is not Null and len(found_key):
                        found_key = found_key[0] if len(found_key) == 1 else found_key

                        if isinstance(found_key, dict):
                            found_value.append(jsonify(found_key.get(something, found_key)))

            if isinstance(found_value, dict) and 'constant_value' in found_value:
                found_value = found_value['constant_value']

            if found_value not in (Null, [], '', {}):
                prop_list.append(resource)

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something

            return something, prop_list

        if _step_obj.state != Step.State.FAILED:
            skip_step(_step_obj,
                      resource=_step_obj.context.name,
                      message='Can not find any {} property for {} resource in '
                              'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        for provider_data in _step_obj.context.stash:
            values = seek_key_in_dict(provider_data, something)

            if values:
                _step_obj.context.stash = provider_data
                _step_obj.context.property_name = something
                _step_obj.context.address = '{}.{}'.format(provider_data.get('name', _step_obj.context.addresses),
                                                           provider_data.get('alias', "\b"))
                return True

    if _step_obj.state != Step.State.FAILED:
        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Skipping the step since {} type does not have {} property.'.format(_step_obj.context.type,
                                                                                              something))
def it_condition_contain_something(_step_obj, something):
    prop_list = []

    if _step_obj.context.type == 'resource':
        for resource in _step_obj.context.stash:
            if type(resource) is not dict:
                resource = {
                    'values': resource,
                    'address': resource,
                    'type': _step_obj.context.name
                }

            values = resource.get('values', {})

            found_value = None
            found_key = None
            if type(values) is dict:
                found_key = seek_key_in_dict(values, something)
                if len(found_key):
                    found_key = found_key[0]

                    if type(found_key) is dict:
                        found_value = jsonify(found_key[something])
            elif type(values) is list:
                for value in values:

                    if type(value) is dict:
                        # First search in the keys
                        found_key = seek_key_in_dict(value, something)

                        # Then search in the values with 'key'
                        if not found_key:
                            found_key = seek_regex_key_in_dict_values(
                                value, 'key', something)

                            if found_key:
                                found_key = found_key[0]
                                found_value = value.get('value')
                                break
                    else:
                        raise TerraformComplianceInternalFailure(
                            'Unexpected value type {}. {}'.format(
                                type(value), value))

            if found_key:
                prop_list.append({
                    'address': resource['address'],
                    'values': found_value,
                    'type': _step_obj.context.name
                })

            elif 'must' in _step_obj.context_sensitive_sentence:
                raise Failure('{} ({}) does not have {} property.'.format(
                    resource['address'], resource.get('type', ''), something))

        if prop_list:
            _step_obj.context.stash = prop_list
            _step_obj.context.property_name = something
            return True

        skip_step(_step_obj,
                  resource=_step_obj.context.name,
                  message='Can not find any {} property for {} resource in '
                  'terraform plan.'.format(something, _step_obj.context.name))

    elif _step_obj.context.type == 'provider':
        values = seek_key_in_dict(_step_obj.context.stash, something)

        if values:
            _step_obj.context.stash = values
            _step_obj.context.property_name = something
            return True

    skip_step(
        _step_obj,
        resource=_step_obj.context.name,
        message='Skipping the step since {} type does not have {} property.'.
        format(_step_obj.context.type, something))
def its_key_condition_be_value(_step_obj,
                               key,
                               condition,
                               value,
                               stash=Null,
                               depth=0):
    if condition not in ('must', 'must not'):
        raise TerraformComplianceNotImplemented(
            'This step only accepts "must" and "must not" as a condition.')
    condition = condition == 'must'

    if stash is Null:
        stash = _step_obj.context.stash

    if not stash or stash is Null:
        Error(
            _step_obj,
            'No entities found for this step to process. Check your filtering steps in this scenario.'
        )
        return False

    obj_address = _step_obj.context.name
    if hasattr(_step_obj.context, 'address'):
        obj_address = _step_obj.context.address
    elif hasattr(_step_obj.context, 'addresses'):
        obj_address = ', '.join(_step_obj.context.addresses)

    found_values = []
    for entity in stash:
        if isinstance(entity, dict):
            found_value = seek_regex_key_in_dict_values(entity, key, value)
            if not found_value and condition:
                Error(
                    _step_obj, 'Can not find {} in {} property of {}.'.format(
                        value, key, entity.get('address', obj_address)))
                Error(_step_obj,
                      'Can not find {} in {} property of {}.'.format(
                          value, key, obj_address))  # legacy error message
            elif found_value and not condition:
                Error(
                    _step_obj, 'Found {}({}) in {} property of {}.'.format(
                        value, ', '.join(found_values), key, obj_address))

            found_values.extend(found_value)

        elif isinstance(entity, list):
            dict_entity = {f'not_{str(key)}': entity}
            found_value = seek_regex_key_in_dict_values(
                dict_entity, key, value)
            if not found_value and condition:
                Error(
                    _step_obj, 'Can not find {} in {} property of {}.'.format(
                        value, key, obj_address))
            elif found_value and not condition:
                Error(
                    _step_obj, 'Found {}({}) in {} property of {}.'.format(
                        value, ', '.join(found_values), key, obj_address))

            found_values.extend(found_value)

        elif isinstance(entity, (str, int, bool)):
            # raise error because you don't have a {key: value}
            if (str(entity).lower == key.lower
                    or str(entity) == value.lower) and condition:
                Error(
                    _step_obj,
                    'Value {} found in {} property of {}, but is not in {{key: value}} format.'
                    .format(value, key, obj_address))
            if condition:
                Error(
                    _step_obj, 'Can not find {} in {} property of {}.'.format(
                        value, key, obj_address))

    _step_obj.context.stash = found_values

    return True