# Buggy code
def __init__(
    self,
    username,
    project_id,
    auth_url,
    region_name=None,
    password=None,
    os_auth_plugin=None,
    **kwargs,
):
    """
    Set up nova credentials
    """
    self.kwargs = kwargs.copy()

    if not novaclient.base.Manager._hooks_map:
        self.extensions = client.discover_extensions("1.1")
        for extension in self.extensions:
            extension.run_hooks("__pre_parse_args__")
        self.kwargs["extensions"] = self.extensions

    self.kwargs["username"] = username
    self.kwargs["project_id"] = project_id
    self.kwargs["auth_url"] = auth_url
    self.kwargs["region_name"] = region_name
    self.kwargs["service_type"] = "compute"

    # used in novaclient extensions to see if they are rackspace or not, to know if it needs to load
    # the hooks for that extension or not.  This is cleaned up by sanatize_novaclient
    self.kwargs["os_auth_url"] = auth_url

    if os_auth_plugin is not None:
        novaclient.auth_plugin.discover_auth_systems()
        auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_plugin)
        self.kwargs["auth_plugin"] = auth_plugin
        self.kwargs["auth_system"] = os_auth_plugin

    if not self.kwargs.get("api_key", None):
        self.kwargs["api_key"] = password

    # This has to be run before sanatize_novaclient before extra variables are cleaned out.
    if hasattr(self, "extensions"):
        # needs an object, not a dictionary
        self.kwargstruct = KwargsStruct(**self.kwargs)
        for extension in self.extensions:
            extension.run_hooks("__post_parse_args__", self.kwargstruct)
        self.kwargs = self.kwargstruct.__dict__

    self.kwargs = sanatize_novaclient(self.kwargs)

    # Requires novaclient version >= 2.6.1
    self.kwargs["version"] = str(kwargs.get("version", 2))

    conn = client.Client(**self.kwargs)
    try:
        conn.client.authenticate()
    except novaclient.exceptions.AmbiguousEndpoints:
        raise SaltCloudSystemExit(
            "Nova provider requires a 'region_name' to be specified"
        )

    self.kwargs["auth_token"] = conn.client.auth_token
    self.catalog = conn.client.service_catalog.catalog["access"]["serviceCatalog"]

    if region_name is not None:
        servers_endpoints = get_entry(self.catalog, "type", "compute")["endpoints"]
        self.kwargs["bypass_url"] = get_entry(servers_endpoints, "region", region_name)[
            "publicURL"
        ]

    self.compute_conn = client.Client(**self.kwargs)

    volume_endpoints = get_entry(self.catalog, "type", "volume", raise_error=False).get(
        "endpoints", {}
    )
    if volume_endpoints:
        if region_name is not None:
            self.kwargs["bypass_url"] = get_entry(
                volume_endpoints, "region", region_name
            )["publicURL"]

        self.volume_conn = client.Client(**self.kwargs)
        if hasattr(self, "extensions"):
            self.expand_extensions()
    else:
        self.volume_conn = None


# Traceback (SaltRenderError)
Comment: An exception occurred in this state: Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/salt/state.py", line 1594, in call
**cdata['kwargs'])
File "/usr/lib/python2.7/dist-packages/salt/loader.py", line 1491, in wrapper
return f(*args, **kwargs)
File "/usr/lib/python2.7/dist-packages/salt/states/file.py", line 2355, in recurse
manage_file(dest, src)
File "/usr/lib/python2.7/dist-packages/salt/states/file.py", line 2232, in manage_file
**pass_kwargs)
File "/usr/lib/python2.7/dist-packages/salt/states/file.py", line 1451, in managed
**kwargs
File "/usr/lib/python2.7/dist-packages/salt/modules/file.py", line 3720, in check_managed_changes
**kwargs)
File "/usr/lib/python2.7/dist-packages/salt/modules/file.py", line 3419, in get_managed
**kwargs)
File "/usr/lib/python2.7/dist-packages/salt/utils/templates.py", line 180, in render_tmpl
output = render_str(tmplstr, context, tmplpath)
File "/usr/lib/python2.7/dist-packages/salt/utils/templates.py", line 415, in render_jinja_tmpl
trace=tracestr)
SaltRenderError: Jinja error: 'module' object has no attribute 'discover_extensions'
Traceback (most recent call last):
File "/usr/lib/python2.7/dist-packages/salt/utils/templates.py", line 368, in render_jinja_tmpl
output = template.render(**decoded_context)
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 969, in render
return self.environment.handle_exception(exc_info, True)
File "/usr/lib/python2.7/dist-packages/jinja2/environment.py", line 742, in handle_exception
reraise(exc_type, exc_value, tb)
File "<template>", line 4, in top-level template code
File "/usr/lib/python2.7/dist-packages/salt/modules/nova.py", line 504, in image_list
conn = _auth(profile)
File "/usr/lib/python2.7/dist-packages/salt/modules/nova.py", line 99, in _auth
return suon.SaltNova(**kwargs)
File "/usr/lib/python2.7/dist-packages/salt/utils/openstack/nova.py", line 145, in __init__
self.extensions = client.discover_extensions('1.1')
AttributeError: 'module' object has no attribute 'discover_extensions'

# Fixed code
def __init__(
    self,
    username,
    project_id,
    auth_url,
    region_name=None,
    password=None,
    os_auth_plugin=None,
    **kwargs,
):
    """
    Set up nova credentials
    """
    self.kwargs = kwargs.copy()

    if not novaclient.base.Manager._hooks_map:
        self.extensions = getattr(
            self, "_discover_extensions", client.discover_extensions
        )("1.1")
        for extension in self.extensions:
            extension.run_hooks("__pre_parse_args__")
        self.kwargs["extensions"] = self.extensions

    self.kwargs["username"] = username
    self.kwargs["project_id"] = project_id
    self.kwargs["auth_url"] = auth_url
    self.kwargs["region_name"] = region_name
    self.kwargs["service_type"] = "compute"

    # used in novaclient extensions to see if they are rackspace or not, to know if it needs to load
    # the hooks for that extension or not.  This is cleaned up by sanatize_novaclient
    self.kwargs["os_auth_url"] = auth_url

    if os_auth_plugin is not None:
        novaclient.auth_plugin.discover_auth_systems()
        auth_plugin = novaclient.auth_plugin.load_plugin(os_auth_plugin)
        self.kwargs["auth_plugin"] = auth_plugin
        self.kwargs["auth_system"] = os_auth_plugin

    if not self.kwargs.get("api_key", None):
        self.kwargs["api_key"] = password

    # This has to be run before sanatize_novaclient before extra variables are cleaned out.
    if hasattr(self, "extensions"):
        # needs an object, not a dictionary
        self.kwargstruct = KwargsStruct(**self.kwargs)
        for extension in self.extensions:
            extension.run_hooks("__post_parse_args__", self.kwargstruct)
        self.kwargs = self.kwargstruct.__dict__

    self.kwargs = sanatize_novaclient(self.kwargs)

    # Requires novaclient version >= 2.6.1
    self.kwargs["version"] = str(kwargs.get("version", 2))

    conn = client.Client(**self.kwargs)
    try:
        conn.client.authenticate()
    except novaclient.exceptions.AmbiguousEndpoints:
        raise SaltCloudSystemExit(
            "Nova provider requires a 'region_name' to be specified"
        )

    self.kwargs["auth_token"] = conn.client.auth_token
    self.catalog = conn.client.service_catalog.catalog["access"]["serviceCatalog"]

    if region_name is not None:
        servers_endpoints = get_entry(self.catalog, "type", "compute")["endpoints"]
        self.kwargs["bypass_url"] = get_entry(servers_endpoints, "region", region_name)[
            "publicURL"
        ]

    self.compute_conn = client.Client(**self.kwargs)

    volume_endpoints = get_entry(self.catalog, "type", "volume", raise_error=False).get(
        "endpoints", {}
    )
    if volume_endpoints:
        if region_name is not None:
            self.kwargs["bypass_url"] = get_entry(
                volume_endpoints, "region", region_name
            )["publicURL"]

        self.volume_conn = client.Client(**self.kwargs)
        if hasattr(self, "extensions"):
            self.expand_extensions()
    else:
        self.volume_conn = None