Exemplo n.º 1
0
    def test_filter_regexp(self):
        hostnames = set()
        for s in Query({'hostname': Regexp('^test[02]$')}):
            hostnames.add(s['hostname'])

        self.assertIn('test0', hostnames)
        self.assertNotIn('test1', hostnames)
        self.assertIn('test2', hostnames)
Exemplo n.º 2
0
def clean_all(route_network, datacenter_type, vm_hostname=None):
    # Cancelled builds are forcefully killed by Jenkins. They did not have the
    # opportunity to clean up so we forcibly destroy everything found on any HV
    # which would interrupt our work in the current JENKINS_EXECUTOR.
    hvs = [Hypervisor(o) for o in Query({
        'servertype': 'hypervisor',
        'environment': 'testing',
        'vlan_networks': route_network,
        'state': 'online',
    }, HYPERVISOR_ATTRIBUTES)]

    # If a VM hostname is given, only that will be cleaned from HVs.
    if vm_hostname is None:
        pattern = '^([0-9]+_)?(vm-rename-)?{}$'.format(
            VM_HOSTNAME_PATTERN.format(JENKINS_EXECUTOR, '[0-9]+'),
        )
    else:
        pattern = '^([0-9]+_)?(vm-rename-)?{}$'.format(vm_hostname)

    # Clean HVs one by one.
    if datacenter_type == 'kvm.dct':
        for hv in hvs:
            clean_hv(hv, pattern)

    if datacenter_type == 'aws.dct':
        clean_aws(vm_hostname)

    # Remove all connected Serveradmin objects.
    clean_serveradmin({'hostname': Regexp(pattern)})

    # Try to remove VMs with the same IP in any case because we use custom
    # logic to assign them and we want to avoid IP address conflicts.
    # Index 1 is usually used for the test's subject VM,
    # 2 might be used for testing IP change.
    ips = [get_next_address(VM_NET, i) for i in [1, 2]]
    clean_serveradmin({'intern_ip': Any(*ips)})
Exemplo n.º 3
0
 def test_filter_regexp_servertype(self):
     s = Query({'servertype': Regexp('^test[870]')}).get()
     self.assertEqual(s['hostname'], 'test0')
Exemplo n.º 4
0
def parse_query(term, hostname=None):  # NOQA: C901
    parsed_args = parse_function_string(term, strict=True)
    if not parsed_args:
        return {}

    # If first token is not a key, we assume that a hostname is meant
    token, value = parsed_args[0]
    if token != 'key':
        if hostname:
            # We already parsed a hostname, so we don't expect another one
            raise DatatypeError("Garbled hostname: {0}".format(hostname))

        term_parts = term.split(None, 1)
        if len(term_parts) == 2:
            hostname_part, remaining_part = term_parts
            query_args = parse_query(remaining_part, hostname_part)
        else:
            hostname_part = term
            query_args = {}

        if any(x in hostname_part for x in _trigger_re_chars):
            hostname = Regexp(hostname_part)
        else:
            hostname = BaseFilter(hostname_part)

        if 'hostname' in query_args:
            query_args['hostname'] = Any(query_args['hostname'], hostname)
        else:
            query_args['hostname'] = hostname

        return query_args

    # Otherwise just parse all attributes
    query_args = {}
    stack = []
    call_depth = 0
    for arg in parsed_args:
        token, value = arg

        if token == 'key':
            if stack:
                query_args[stack[0][1]] = stack[1][1]
                stack = []
            stack.append(arg)

        elif token == 'func':
            # Do not allow functions without preceding key
            # if they are on top level (e.g. call_depth = 0)
            if not stack or (call_depth == 0 and stack[-1][0] != 'key'):
                raise DatatypeError(
                    'Invalid term: top level function requires '
                    'preceding attribute'
                )
            call_depth += 1
            stack.append(arg)

        elif token == 'endfunc':
            call_depth -= 1
            fn_args = []
            while True:
                s_token, s_value = stack.pop()
                if s_token == 'func':
                    break
                else:
                    fn_args.append(s_value)
            fn_args.reverse()

            for filter_class in filter_classes:
                if filter_class.__name__.lower() == s_value.lower():
                    try:
                        instance = filter_class(*fn_args)
                    except TypeError:
                        raise DatatypeError(
                            'Invalid function args ' + filter_class.__name__
                        )
                    break
            else:
                raise DatatypeError('Invalid function ' + s_value)
            stack.append(('instance', instance))

        elif token == 'literal':
            # Do not allow literals without key or function context
            if not stack or (call_depth == 0 and stack[-1][0] != 'key'):
                raise DatatypeError(
                    'Invalid term: Top level literals are not '
                    'allowed when attributes are used'
                )
            if call_depth == 0:
                stack.append(('literal', BaseFilter(value)))
            else:
                stack.append(('literal', value))

    if stack and stack[0][0] == 'key':
        if len(stack) != 2:
            raise DatatypeError(
                'Invalid term: Attribute requires one argument'
            )
        query_args[stack[0][1]] = stack[1][1]

    return query_args