Example #1
0
def _get_template(provider, template_type_name):
    template = provider.data.get(template_type_name)
    # if the template is None, try to get it from templates section on provider data
    # because additional templates are present in this section which are not present
    # under provider directly
    if not template:
        template = provider.data.templates.get(template_type_name)
    if isinstance(template, Mapping):
        template_name = template.get("name")
    else:
        template_name = template
    if template_name:
        if not TEMPLATES:
            # Same as couple of lines above
            return template
        templates = TEMPLATES.get(provider.key)
        # If template is type string then return template else template_name
        # since template could be AttrDict and returning it would fail provisioning
        # _get_template should always return template name of type string
        if templates and template_name in templates and isinstance(template, six.string_types):
            return template
        return template_name
    else:
        pytest.skip('No {} for provider {}'.format(template_type_name, provider.key))
    logger.info("Wanted template %s on %s but it is not there!", template, provider.key)
    pytest.skip('Template not available')
Example #2
0
def template(template_location, provider):
    if template_location is not None:
        o = provider.data
        try:
            for field in template_location:
                o = o[field]
        except (IndexError, KeyError):
            logger.info(
                "Cannot apply %r to %r in the template specification, ignoring.",
                field, o)
        else:
            if not isinstance(o, six.string_types):
                raise ValueError(
                    "{!r} is not a string! (for template)".format(o))
            if not TEMPLATES:
                # There is nothing in TEMPLATES, that means no trackerbot URL and no data pulled.
                # This should normally not constitute an issue so continue.
                return o
            templates = TEMPLATES.get(provider.key)
            if templates is not None:
                if o in templates:
                    return o
    logger.info("Wanted template %s on %s but it is not there!", o,
                provider.key)
    pytest.skip('Template not available')
Example #3
0
def _get_template(provider, template_type_name):
    template = provider.data.get(template_type_name)
    # if the template is None, try to get it from templates section on provider data
    # because additional templates are present in this section which are not present
    # under provider directly
    if not template:
        template = provider.data.templates.get(template_type_name)
    if isinstance(template, Mapping):
        template_name = template.get("name")
    else:
        template_name = template
    if template_name:
        if not TEMPLATES:
            # Same as couple of lines above
            return template
        templates = TEMPLATES.get(provider.key)
        # If template is type string then return template else template_name
        # since template could be AttrDict and returning it would fail provisioning
        # _get_template should always return template name of type string
        if templates and template_name in templates and isinstance(
                template, six.string_types):
            return template
        return template_name
    else:
        pytest.skip('No {} for provider {}'.format(template_type_name,
                                                   provider.key))
    logger.info("Wanted template %s on %s but it is not there!", template,
                provider.key)
    pytest.skip('Template not available')
Example #4
0
def full_template(provider):
    template = provider.data.get('full_template', {})
    if template:
        templates = TEMPLATES.get(provider.key, None)
        if templates is not None:
            if template['name'] in templates:
                return template
    logger.info(
        "Wanted template {} on {} but it is not there!\n".format(template, provider.key))
    pytest.skip('Template not available')
Example #5
0
def full_template(provider):
    template = provider.data.get('full_template', {})
    if template:
        templates = TEMPLATES.get(provider.key, None)
        if templates is not None:
            if template['name'] in templates:
                return template
    logger.info("Wanted template {} on {} but it is not there!\n".format(
        template, provider.key))
    pytest.skip('Template not available')
Example #6
0
def full_template(provider):
    template = provider.data.get('full_template', {})
    if template:
        if not TEMPLATES:
            # Same as couple of lines above
            return template
        templates = TEMPLATES.get(provider.key, None)
        if templates is not None:
            if template['name'] in templates:
                return template
    else:
        pytest.skip('No full_template for provider {}'.format(provider.key))
    logger.info("Wanted template %s on %s but it is not there!", template, provider.key)
    pytest.skip('Template not available')
Example #7
0
def _get_template(provider, template_type_name):
    template = provider.data.get(template_type_name, None)
    if isinstance(template, Mapping):
        template_name = template.get("name", None)
    else:
        template_name = template
    if template_name:
        if not TEMPLATES:
            # Same as couple of lines above
            return template
        templates = TEMPLATES.get(provider.key, None)
        if templates and template_name in templates:
            return template
    else:
        pytest.skip('No {} for provider {}'.format(template_type_name, provider.key))
    logger.info("Wanted template %s on %s but it is not there!", template, provider.key)
    pytest.skip('Template not available')
Example #8
0
def _get_template(provider, template_type_name):
    template = provider.data.get(template_type_name, None)
    if isinstance(template, Mapping):
        template_name = template.get("name", None)
    else:
        template_name = template
    if template_name:
        if not TEMPLATES:
            # Same as couple of lines above
            return template
        templates = TEMPLATES.get(provider.key, None)
        if templates and template_name in templates:
            return template
    else:
        pytest.skip('No {} for provider {}'.format(template_type_name, provider.key))
    logger.info("Wanted template %s on %s but it is not there!", template, provider.key)
    pytest.skip('Template not available')
Example #9
0
def template(template_location, provider):
    if template_location is not None:
        o = provider.data
        try:
            for field in template_location:
                o = o[field]
        except (IndexError, KeyError):
            logger.info("Cannot apply %s to %s in the template specification, ignoring.",
                repr(field), repr(o))
        else:
            if not isinstance(o, basestring):
                raise ValueError("{} is not a string! (for template)".format(repr(o)))
            templates = TEMPLATES.get(provider.key, None)
            if templates is not None:
                if o in templates:
                    return o
    logger.info(
        "Wanted template {} on {} but it is not there!\n".format(o, provider.key))
    pytest.skip('Template not available')
Example #10
0
def template(template_location, provider):
    if template_location is not None:
        o = provider.data
        try:
            for field in template_location:
                o = o[field]
        except (IndexError, KeyError):
            logger.info("Cannot apply %r to %r in the template specification, ignoring.", field, o)
        else:
            if not isinstance(o, six.string_types):
                raise ValueError("{!r} is not a string! (for template)".format(o))
            if not TEMPLATES:
                # There is nothing in TEMPLATES, that means no trackerbot URL and no data pulled.
                # This should normally not constitute an issue so continue.
                return o
            templates = TEMPLATES.get(provider.key, None)
            if templates is not None:
                if o in templates:
                    return o
    logger.info("Wanted template %s on %s but it is not there!", o, provider.key)
    pytest.skip('Template not available')
Example #11
0
def template(template_location, provider):
    if template_location is not None:
        o = provider.data
        try:
            for field in template_location:
                o = o[field]
        except (IndexError, KeyError):
            logger.info(
                "Cannot apply %s to %s in the template specification, ignoring.",
                repr(field), repr(o))
        else:
            if not isinstance(o, basestring):
                raise ValueError("{} is not a string! (for template)".format(
                    repr(o)))
            templates = TEMPLATES.get(provider.key, None)
            if templates is not None:
                if o in templates:
                    return o
    logger.info("Wanted template {} on {} but it is not there!\n".format(
        o, provider.key))
    pytest.skip('Template not available')
Example #12
0
def provider_by_type(metafunc, provider_types, *fields, **options):
    """Get the values of the named field keys from ``cfme_data.get('management_systems', {})``

    Args:
        provider_types: A list of provider types to include. If None, all providers are considered
        *fields: Names of keys in an individual provider dict whose values will be returned when
            used as test function arguments
        **options: Explained below

    The ``**options`` available are defined below:

    * ``required_fields``: when fields passed are not present, skip them
    * ``choose_random``: choose a single provider from the list
    * ``template_location``: Specification where a required tempalte lies in the yaml, If not
      found in the provider, warning is printed and the test not collected. The spec
      is a tuple or list where each item is a key to the next field (str or int).

    The following test function arguments are special:

        ``provider``
            the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider`
            or a :py:class:`cfme.infrastructure.provider.Provider`

    Returns:
        An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or
        with the :py:func:`parametrize` helper.

    Usage:

        # In the function itself
        def pytest_generate_tests(metafunc):
            argnames, argvalues, idlist = testgen.provider_by_type(
                ['openstack', 'ec2'],
                'type', 'name', 'credentials', 'provider', 'hosts'
            )
        metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module')

        # Using the parametrize wrapper
        pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'],
            'type', 'name', 'credentials', 'provider', 'hosts', scope='module')

    Note:

        Using the default 'function' scope, each test will be run individually for each provider
        before moving on to the next test. To group all tests related to single provider together,
        parametrize tests in the 'module' scope.

    Note:

        testgen for providers now requires the usage of test_flags for collection to work.
        Please visit http://cfme-tests.readthedocs.org/guides/documenting.html#documenting-tests
        for more details.

    """

    metafunc.function = pytest.mark.uses_testgen()(metafunc.function)

    argnames = list(fields)
    argvalues = []
    idlist = []
    template_location = options.pop("template_location", None)

    if 'provider' in metafunc.fixturenames and 'provider' not in argnames:
        argnames.append('provider')

    for provider, data in cfme_data.get('management_systems', {}).iteritems():

        # Check provider hasn't been filtered out with --use-provider
        if provider not in filtered:
            continue

        try:
            prov_obj = get_crud(provider)
        except UnknownProviderType:
            continue

        if not prov_obj:
            logger.debug(
                "Whilst trying to create an object for {} we failed".format(
                    provider))
            continue

        skip = False
        if provider_types is not None and prov_obj.type not in provider_types:
            # Skip unwanted types
            continue

        restricted_version = data.get('restricted_version', None)
        if restricted_version:
            logger.info('we found a restricted version')
            for op, comparator in _version_operator_map.items():
                # split string by op; if the split works, version won't be empty
                head, op, ver = restricted_version.partition(op)
                if not ver:  # This means that the operator was not found
                    continue
                if not comparator(version.current_version(), ver):
                    skip = True
                break
            else:
                raise Exception(
                    'Operator not found in {}'.format(restricted_version))

        # Test to see the test has meta data, if it does and that metadata contains
        # a test_flag kwarg, then check to make sure the provider contains that test_flag
        # if not, do not collect the provider for this particular test.

        # Obtain the tests flags
        meta = getattr(metafunc.function, 'meta', None)

        test_flags = getattr(meta, 'kwargs', {}) \
            .get('from_docs', {}).get('test_flag', '').split(',')
        if test_flags != ['']:
            test_flags = [flag.strip() for flag in test_flags]

            defined_flags = cfme_data.get('test_flags', '').split(',')
            defined_flags = [flag.strip() for flag in defined_flags]

            excluded_flags = data.get('excluded_test_flags', '').split(',')
            excluded_flags = [flag.strip() for flag in excluded_flags]

            allowed_flags = set(defined_flags) - set(excluded_flags)

            if set(test_flags) - allowed_flags:
                logger.info(
                    "Skipping Provider {} for test {} in module {} because "
                    "it does not have the right flags, "
                    "{} does not contain {}".format(
                        provider, metafunc.function.func_name,
                        metafunc.function.__module__, list(allowed_flags),
                        list(set(test_flags) - allowed_flags)))
                continue

        try:
            if prov_obj.type == "scvmm" and version.current_version() < "5.3":
                # Ignore SCVMM on 5.2
                continue
            if "since_version" in data:
                # Ignore providers that are not supported in this version yet
                if version.current_version() < data["since_version"]:
                    continue
        except Exception:  # No SSH connection
            continue

        # Get values for the requested fields, filling in with None for undefined fields
        data_values = {field: data.get(field, None) for field in fields}

        # Go through the values and handle the special 'data' name
        # report the undefined fields to the log
        for key in data_values.keys():
            if data_values[key] is None:
                if 'require_fields' not in options:
                    options['require_fields'] = True
                if options['require_fields']:
                    skip = True
                    logger.warning(
                        'Field "%s" not defined for provider "%s", skipping' %
                        (key, provider))
                else:
                    logger.debug(
                        'Field "%s" not defined for provider "%s", defaulting to None'
                        % (key, provider))
        if skip:
            continue

        # Check the template presence if requested
        if template_location is not None:
            o = data
            try:
                for field in template_location:
                    o = o[field]
            except (IndexError, KeyError):
                logger.info(
                    "Cannot apply {} to {} in the template specification, ignoring."
                    .format(repr(field), repr(o)))
            else:
                if not isinstance(o, basestring):
                    raise ValueError(
                        "{} is not a string! (for template)".format(repr(o)))
                templates = TEMPLATES.get(provider, None)
                if templates is not None:
                    if o not in templates:
                        logger.info(
                            "Wanted template {} on {} but it is not there!\n".
                            format(o, provider))
                        # Skip collection of this one
                        continue

        values = []
        for arg in argnames:
            if arg == 'provider':
                metafunc.function = pytest.mark.provider_related()(
                    metafunc.function)
                values.append(prov_obj)
            elif arg in data_values:
                values.append(data_values[arg])

        # skip when required field is not present and option['require_field'] == True
        argvalues.append(values)

        # Use the provider name for idlist, helps with readable parametrized test output
        idlist.append(provider)

    # pick a single provider if option['choose_random'] == True
    if 'choose_random' not in options:
        options['choose_random'] = False
    if idlist and options['choose_random']:
        single_index = idlist.index(random.choice(idlist))
        new_idlist = ['random_provider']
        new_argvalues = [argvalues[single_index]]
        logger.debug('Choosing random provider, "%s" selected, ' % (provider))
        return argnames, new_argvalues, new_idlist

    return argnames, argvalues, idlist
Example #13
0
def provider_by_type(metafunc, provider_types, *fields, **options):
    """Get the values of the named field keys from ``cfme_data.get('management_systems', {})``

    Args:
        provider_types: A list of provider types to include. If None, all providers are considered
        *fields: Names of keys in an individual provider dict whose values will be returned when
            used as test function arguments
        **options: Explained below

    The ``**options`` available are defined below:

    * ``require_fields``: when fields passed are not present, skip them, boolean
    * ``template_location``: Specification where a required tempalte lies in the yaml, If not
      found in the provider, warning is printed and the test not collected. The spec
      is a tuple or list where each item is a key to the next field (str or int).

    The following test function arguments are special:

        ``provider``
            the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider`
            or a :py:class:`cfme.infrastructure.provider.Provider`

    Returns:
        An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or
        with the :py:func:`parametrize` helper.

    Usage:

        # In the function itself
        def pytest_generate_tests(metafunc):
            argnames, argvalues, idlist = testgen.provider_by_type(
                ['openstack', 'ec2'],
                'type', 'name', 'credentials', 'provider', 'hosts'
            )
        metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module')

        # Using the parametrize wrapper
        pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'],
            'type', 'name', 'credentials', 'provider', 'hosts', scope='module')

    Note:

        Using the default 'function' scope, each test will be run individually for each provider
        before moving on to the next test. To group all tests related to single provider together,
        parametrize tests in the 'module' scope.

    Note:

        testgen for providers now requires the usage of test_flags for collection to work.
        Please visit http://cfme-tests.readthedocs.org/guides/documenting.html#documenting-tests
        for more details.

    """

    metafunc.function = pytest.mark.uses_testgen()(metafunc.function)

    argnames = list(fields)
    argvalues = []
    idlist = []
    template_location = options.pop("template_location", None)

    if 'provider' in metafunc.fixturenames and 'provider' not in argnames:
        argnames.append('provider')

    for provider, data in cfme_data.get('management_systems', {}).iteritems():

        # Check provider hasn't been filtered out with --use-provider
        if provider not in filtered:
            continue

        try:
            prov_obj = get_crud(provider)
        except UnknownProviderType:
            continue

        if not prov_obj:
            logger.debug("Whilst trying to create an object for %s we failed", provider)
            continue

        skip = False
        if provider_types is not None and prov_obj.type not in provider_types:
            # Skip unwanted types
            continue

        restricted_version = data.get('restricted_version', None)
        if restricted_version:
            logger.info('we found a restricted version')
            for op, comparator in _version_operator_map.items():
                # split string by op; if the split works, version won't be empty
                head, op, ver = restricted_version.partition(op)
                if not ver:  # This means that the operator was not found
                    continue
                if not comparator(version.current_version(), ver):
                    skip = True
                break
            else:
                raise Exception('Operator not found in {}'.format(restricted_version))

        # Test to see the test has meta data, if it does and that metadata contains
        # a test_flag kwarg, then check to make sure the provider contains that test_flag
        # if not, do not collect the provider for this particular test.

        # Obtain the tests flags
        meta = getattr(metafunc.function, 'meta', None)

        test_flags = getattr(meta, 'kwargs', {}) \
            .get('from_docs', {}).get('test_flag', '').split(',')
        if test_flags != ['']:
            test_flags = [flag.strip() for flag in test_flags]

            defined_flags = cfme_data.get('test_flags', '').split(',')
            defined_flags = [flag.strip() for flag in defined_flags]

            excluded_flags = data.get('excluded_test_flags', '').split(',')
            excluded_flags = [flag.strip() for flag in excluded_flags]

            allowed_flags = set(defined_flags) - set(excluded_flags)

            if set(test_flags) - allowed_flags:
                logger.info("Skipping Provider %s for test %s in module %s because "
                    "it does not have the right flags, "
                    "%s does not contain %s",
                    provider, metafunc.function.func_name, metafunc.function.__module__,
                    list(allowed_flags), list(set(test_flags) - allowed_flags))
                continue

        try:
            if "since_version" in data:
                # Ignore providers that are not supported in this version yet
                if version.current_version() < data["since_version"]:
                    continue
        except Exception:  # No SSH connection
            continue

        # Get values for the requested fields, filling in with None for undefined fields
        data_values = {field: data.get(field, None) for field in fields}

        # Go through the values and handle the special 'data' name
        # report the undefined fields to the log
        for key in data_values.keys():
            if data_values[key] is None:
                if 'require_fields' not in options:
                    options['require_fields'] = True
                if options['require_fields']:
                    skip = True
                    logger.warning('Field "%s" not defined for provider "%s", skipping' %
                        (key, provider)
                    )
                else:
                    logger.debug('Field "%s" not defined for provider "%s", defaulting to None' %
                        (key, provider)
                    )
        if skip:
            continue

        # Check the template presence if requested
        if template_location is not None:
            o = data
            try:
                for field in template_location:
                    o = o[field]
            except (IndexError, KeyError):
                logger.info("Cannot apply %s to %s in the template specification, ignoring.",
                    repr(field), repr(o))
            else:
                if not isinstance(o, basestring):
                    raise ValueError("{} is not a string! (for template)".format(repr(o)))
                templates = TEMPLATES.get(provider, None)
                if templates is not None:
                    if o not in templates:
                        logger.info(
                            "Wanted template %s on %s but it is not there!\n", o, provider)
                        # Skip collection of this one
                        continue

        values = []
        for arg in argnames:
            if arg == 'provider':
                metafunc.function = pytest.mark.provider_related()(metafunc.function)
                values.append(prov_obj)
            elif arg in data_values:
                values.append(data_values[arg])

        # skip when required field is not present and option['require_field'] == True
        argvalues.append(values)

        # Use the provider name for idlist, helps with readable parametrized test output
        idlist.append(provider)

    return argnames, argvalues, idlist
Example #14
0
def provider_by_type(metafunc, provider_types, *fields, **options):
    """Get the values of the named field keys from ``cfme_data.get('management_systems', {})``

    Args:
        provider_types: A list of provider types to include. If None, all providers are considered
        *fields: Names of keys in an individual provider dict whose values will be returned when
            used as test function arguments
        **options: Explained below

    The ``**options`` available are defined below:

    * ``required_fields``: when fields passed are not present, skip them
    * ``choose_random``: choose a single provider from the list
    * ``template_location``: Specification where a required tempalte lies in the yaml, If not
      found in the provider, warning is printed and the test not collected. The spec
      is a tuple or list where each item is a key to the next field (str or int).

    The following test function arguments are special:

        ``provider_data``
            the entire provider data dict from cfme_data.

        ``provider_key``
            the provider's key in ``cfme_data.get('management_systems', {})``

        ``provider_crud``
            the provider's CRUD object, either a :py:class:`cfme.cloud.provider.Provider`
            or a :py:class:`cfme.infrastructure.provider.Provider`

        ``provider_mgmt``
            the provider's backend manager, from :py:class:`utils.mgmt_system`

    Returns:
        An tuple of ``(argnames, argvalues, idlist)`` for use in a pytest_generate_tests hook, or
        with the :py:func:`parametrize` helper.

    Usage:

        # In the function itself
        def pytest_generate_tests(metafunc):
            argnames, argvalues, idlist = testgen.provider_by_type(
                ['openstack', 'ec2'],
                'type', 'name', 'credentials', 'provider_data', 'hosts'
            )
        metafunc.parametrize(argnames, argvalues, ids=idlist, scope='module')

        # Using the parametrize wrapper
        pytest_generate_tests = testgen.parametrize(testgen.provider_by_type, ['openstack', 'ec2'],
            'type', 'name', 'credentials', 'provider_data', 'hosts', scope='module')

    Note:

        Using the default 'function' scope, each test will be run individually for each provider
        before moving on to the next test. To group all tests related to single provider together,
        parametrize tests in the 'module' scope.

    Note:

        testgen for providers now requires the usage of test_flags for collection to work.
        Please visit http://cfme-tests.readthedocs.org/guides/documenting.html#documenting-tests
        for more details.

    """

    metafunc.function = pytest.mark.uses_testgen()(metafunc.function)

    argnames = list(fields)
    argvalues = []
    idlist = []
    template_location = options.pop("template_location", None)

    special_args = ('provider_key', 'provider_data', 'provider_crud',
        'provider_mgmt', 'provider_type')
    # Hook on special attrs if requested
    for argname in special_args:
        if argname in metafunc.fixturenames and argname not in argnames:
            argnames.append(argname)

    for provider, data in cfme_data.get('management_systems', {}).iteritems():
        skip = False
        prov_type = data['type']
        if provider_types is not None and prov_type not in provider_types:
            # Skip unwanted types
            continue

        # Test to see the test has meta data, if it does and that metadata contains
        # a test_flag kwarg, then check to make sure the provider contains that test_flag
        # if not, do not collect the provider for this particular test.

        # Obtain the tests flags
        meta = getattr(metafunc.function, 'meta', None)

        test_flags = getattr(meta, 'kwargs', {}) \
            .get('from_docs', {}).get('test_flag', '').split(',')
        if test_flags != ['']:
            test_flags = [flag.strip() for flag in test_flags]

            defined_flags = cfme_data.get('test_flags', '').split(',')
            defined_flags = [flag.strip() for flag in defined_flags]

            excluded_flags = data.get('excluded_test_flags', '').split(',')
            excluded_flags = [flag.strip() for flag in excluded_flags]

            allowed_flags = set(defined_flags) - set(excluded_flags)

            if set(test_flags) - allowed_flags:
                logger.info("Skipping Provider {} for test {} in module {} because "
                    "it does not have the right flags, "
                    "{} does not contain {}".format(provider,
                                                    metafunc.function.func_name,
                                                    metafunc.function.__module__,
                                                    list(allowed_flags),
                                                    list(set(test_flags) - allowed_flags)))
                continue

        try:
            if prov_type == "scvmm" and version.current_version() < "5.3":
                # Ignore SCVMM on 5.2
                continue
        except Exception:  # No SSH connection
            continue

        # Check provider hasn't been filtered out with --use-provider
        if provider not in filtered:
            continue

        # Use the provider name for idlist, helps with readable parametrized test output
        idlist.append(provider)

        # Get values for the requested fields, filling in with None for undefined fields
        data_values = {field: data.get(field, None) for field in fields}

        # Go through the values and handle the special 'data' name
        # report the undefined fields to the log
        for key in data_values.keys():
            if data_values[key] is None:
                if 'require_fields' not in options:
                    options['require_fields'] = True
                if options['require_fields']:
                    skip = True
                    try:
                        idlist.remove(provider)
                    except ValueError:
                        pass
                    logger.warning('Field "%s" not defined for provider "%s", skipping' %
                        (key, provider)
                    )
                else:
                    logger.debug('Field "%s" not defined for provider "%s", defaulting to None' %
                        (key, provider)
                    )

        # Check the template presence if requested
        if template_location is not None:
            o = data
            try:
                for field in template_location:
                    o = o[field]
            except (IndexError, KeyError):
                logger.info("Cannot apply {} to {} in the template specification, ignoring.".format(
                    repr(field), repr(o)))
            else:
                if not isinstance(o, basestring):
                    raise ValueError("{} is not a string! (for template)".format(repr(o)))
                templates = TEMPLATES.get(provider, None)
                if templates is not None:
                    if o not in templates:
                        logger.info(
                            "Wanted template {} on {} but it is not there!\n".format(o, provider))
                        # Skip collection of this one
                        continue

        if prov_type in cloud_provider_type_map:
            crud = get_cloud_provider(provider)
        elif prov_type in infra_provider_type_map:
            crud = get_infra_provider(provider)
        # else: wat? You deserve the NameError you're about to receive

        mgmt = provider_factory(provider)

        values = []
        special_args_map = dict(zip(special_args, (provider, data, crud, mgmt, prov_type)))
        for arg in argnames:
            if arg in special_args_map:
                if arg == "provider_crud":
                    metafunc.function = pytest.mark.provider_related()(metafunc.function)
                values.append(special_args_map[arg])
            elif arg in data_values:
                values.append(data_values[arg])

        # skip when required field is not present and option['require_field'] == True
        if not skip:
            argvalues.append(values)

    # pick a single provider if option['choose_random'] == True
    if 'choose_random' not in options:
        options['choose_random'] = False
    if idlist and options['choose_random']:
        single_index = idlist.index(random.choice(idlist))
        new_idlist = ['random_provider']
        new_argvalues = [argvalues[single_index]]
        logger.debug('Choosing random provider, "%s" selected, ' % (provider))
        return argnames, new_argvalues, new_idlist

    return argnames, argvalues, idlist