def generate_providers_table()

in contrib/generate_provider_feature_matrix_table.py [0:0]


def generate_providers_table(api):
    result = {}

    if api in [
        "compute_main",
        "compute_image_management",
        "compute_block_storage",
        "compute_key_pair_management",
    ]:
        driver = NodeDriver
        drivers = COMPUTE_DRIVERS
        provider = ComputeProvider
        get_driver_method = get_compute_driver
    elif api == "loadbalancer":
        driver = LBDriver
        drivers = LB_DRIVERS
        provider = LBProvider
        get_driver_method = get_lb_driver
    elif api in ["storage_main", "storage_cdn"]:
        driver = StorageDriver
        drivers = STORAGE_DRIVERS
        provider = StorageProvider
        get_driver_method = get_storage_driver
    elif api == "dns":
        driver = DNSDriver
        drivers = DNS_DRIVERS
        provider = DNSProvider
        get_driver_method = get_dns_driver
    elif api == "container":
        driver = ContainerDriver
        drivers = CONTAINER_DRIVERS
        provider = ContainerProvider
        get_driver_method = get_container_driver
    elif api == "backup":
        driver = BackupDriver
        drivers = BACKUP_DRIVERS
        provider = BackupProvider
        get_driver_method = get_backup_driver
    else:
        raise Exception("Invalid api: %s" % (api))

    names = get_provider_api_names(provider)

    result = OrderedDict()
    for name in names:
        enum = getattr(provider, name)

        try:
            cls = get_driver_method(enum)
        except Exception as e:
            # Deprecated providers throw an exception
            print('Ignoring deprecated constant "{}": {}'.format(enum, str(e)))
            continue

        # Hack for providers which expose multiple classes and support multiple
        # API versions
        # TODO: Make entry per version
        if name.lower() == "cloudsigma":
            from libcloud.compute.drivers.cloudsigma import CloudSigma_2_0_NodeDriver

            cls = CloudSigma_2_0_NodeDriver
        elif name.lower() == "opennebula":
            from libcloud.compute.drivers.opennebula import OpenNebula_3_8_NodeDriver

            cls = OpenNebula_3_8_NodeDriver
        elif name.lower() == "digital_ocean" and api.startswith("compute"):
            from libcloud.compute.drivers.digitalocean import DigitalOcean_v2_NodeDriver

            cls = DigitalOcean_v2_NodeDriver
        elif name.lower() == "linode" and api.startswith("compute"):
            from libcloud.compute.drivers.linode import LinodeNodeDriverV4

            cls = LinodeNodeDriverV4
        elif name.lower() == "linode" and api.startswith("dns"):
            from libcloud.dns.drivers.linode import LinodeDNSDriverV4

            cls = LinodeDNSDriverV4
        elif name.lower() == "vultr" and api.startswith("compute"):
            from libcloud.compute.drivers.vultr import VultrNodeDriverV2

            cls = VultrNodeDriverV2
        elif name.lower() == "vultr" and api.startswith("dns"):
            from libcloud.dns.drivers.vultr import VultrDNSDriverV2

            cls = VultrDNSDriverV2

        if name.lower() in IGNORED_PROVIDERS:
            continue

        def is_function_or_method(*args, **kwargs):
            return inspect.isfunction(*args, **kwargs) or inspect.ismethod(*args, **kwargs)

        driver_methods = dict(inspect.getmembers(cls, predicate=is_function_or_method))
        base_methods = dict(inspect.getmembers(driver, predicate=is_function_or_method))
        base_api_methods = BASE_API_METHODS[api]

        result[name] = {
            "name": cls.name,
            "website": cls.website,
            "constant": name,
            "module": drivers[enum][0],
            "class": drivers[enum][1],
            "cls": cls,
            "methods": {},
        }

        print("Generating tables for provider: %s" % (name))

        for method_name in base_api_methods:
            base_method = base_methods[method_name]

            if method_name == "deploy_node":
                features = getattr(cls, "features", {}).get("create_node", [])
                is_implemented = len(features) >= 1
            else:
                if method_name not in driver_methods:
                    is_implemented = False
                else:
                    driver_method = driver_methods[method_name]
                    # NOTE: id() is not safe
                    # is_implemented = (id(driver_method) != id(base_method))
                    is_implemented = driver_method != base_method

            result[name]["methods"][method_name] = is_implemented

    return result