diff --git a/contrib/inventory/azure_rm.py b/contrib/inventory/azure_rm.py index bc3701c27f2..73b8b959d37 100755 --- a/contrib/inventory/azure_rm.py +++ b/contrib/inventory/azure_rm.py @@ -23,7 +23,7 @@ Azure External Inventory Script =============================== Generates dynamic inventory by making API requests to the Azure Resource -Manager using the AAzure Python SDK. For instruction on installing the +Manager using the Azure Python SDK. For instruction on installing the Azure Python SDK see http://azure-sdk-for-python.readthedocs.org/ Authentication @@ -32,7 +32,7 @@ The order of precedence is command line arguments, environment variables, and finally the [default] profile found in ~/.azure/credentials. If using a credentials file, it should be an ini formatted file with one or -more sections, which we refer to as profiles. The script looks for a +more sections, which we refer to as profiles. The script looks for a [default] section, if a profile is not specified either on the command line or with an environment variable. The keys in a profile will match the list of command line arguments below. @@ -42,7 +42,7 @@ in your ~/.azure/credentials file, or a service principal or Active Directory user. Command line arguments: - - profile + - profile - client_id - secret - subscription_id @@ -61,7 +61,7 @@ Environment variables: Run for Specific Host ----------------------- -When run for a specific host using the --host option, a resource group is +When run for a specific host using the --host option, a resource group is required. For a specific host, this script returns the following variables: { @@ -76,7 +76,7 @@ required. For a specific host, this script returns the following variables: "version": "latest" }, "location": "westus", - "mac_address": "00-0D-3A-31-2C-EC", + "mac_address": "00-00-5E-00-53-FE", "name": "object-name", "network_interface": "interface-name", "network_interface_id": "/subscriptions/subscription-id/resourceGroups/galaxy-production/providers/Microsoft.Network/networkInterfaces/object-name1", @@ -142,11 +142,13 @@ If you don't need the powerstate, you can improve performance by turning off pow AZURE_INCLUDE_POWERSTATE=no azure_rm.ini ----------------------- -As mentioned above you can control execution using environment variables or an .ini file. A sample +------------ +As mentioned above, you can control execution using environment variables or a .ini file. A sample azure_rm.ini is included. The name of the .ini file is the basename of the inventory script (in this case -'azure_rm') with a .ini extension. This provides you with the flexibility of copying and customizing this -script and having matching .ini files. Go forth and customize your Azure inventory! +'azure_rm') with a .ini extension. It also assumes the .ini file is alongside the script. To specify +a different path for the .ini file, define the AZURE_INI_PATH environment variable: + + export AZURE_INI_PATH=/path/to/custom.ini Powerstate: ----------- @@ -189,7 +191,7 @@ import os import re import sys -from distutils.version import LooseVersion +from packaging.version import Version from os.path import expanduser @@ -307,7 +309,7 @@ class AzureRM(object): def _get_env_credentials(self): env_credentials = dict() - for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.iteritems(): + for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items(): env_credentials[attribute] = os.environ.get(env_variable, None) if env_credentials['profile'] is not None: @@ -326,7 +328,7 @@ class AzureRM(object): self.log('Getting credentials') arg_credentials = dict() - for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.iteritems(): + for attribute, env_variable in AZURE_CREDENTIAL_ENV_MAPPING.items(): arg_credentials[attribute] = getattr(params, attribute) # try module params @@ -360,7 +362,11 @@ class AzureRM(object): resource_client = self.rm_client resource_client.providers.register(key) except Exception as exc: - self.fail("One-time registration of {0} failed - {1}".format(key, str(exc))) + self.log("One-time registration of {0} failed - {1}".format(key, str(exc))) + self.log("You might need to register {0} using an admin account".format(key)) + self.log(("To register a provider using the Python CLI: " + "https://docs.microsoft.com/azure/azure-resource-manager/" + "resource-manager-common-deployment-errors#noregisteredproviderfound")) @property def network_client(self): @@ -440,7 +446,7 @@ class AzureInventory(object): def _parse_cli_args(self): # Parse command line arguments parser = argparse.ArgumentParser( - description='Produce an Ansible Inventory file for an Azure subscription') + description='Produce an Ansible Inventory file for an Azure subscription') parser.add_argument('--list', action='store_true', default=True, help='List instances (default: True)') parser.add_argument('--debug', action='store_true', default=False, @@ -662,7 +668,7 @@ class AzureInventory(object): self._inventory['azure'].append(host_name) if self.group_by_tag and vars.get('tags'): - for key, value in vars['tags'].iteritems(): + for key, value in vars['tags'].items(): safe_key = self._to_safe(key) safe_value = safe_key + '_' + self._to_safe(value) if not self._inventory.get(safe_key): @@ -722,13 +728,14 @@ class AzureInventory(object): def _get_env_settings(self): env_settings = dict() - for attribute, env_variable in AZURE_CONFIG_SETTINGS.iteritems(): + for attribute, env_variable in AZURE_CONFIG_SETTINGS.items(): env_settings[attribute] = os.environ.get(env_variable, None) return env_settings def _load_settings(self): basename = os.path.splitext(os.path.basename(__file__))[0] - path = basename + '.ini' + default_path = os.path.join(os.path.dirname(__file__), (basename + '.ini')) + path = os.path.expanduser(os.path.expandvars(os.environ.get('AZURE_INI_PATH', default_path))) config = None settings = None try: @@ -783,11 +790,11 @@ class AzureInventory(object): def main(): if not HAS_AZURE: - sys.exit("The Azure python sdk is not installed (try 'pip install azure==2.0.0rc5') - {0}".format(HAS_AZURE_EXC)) + sys.exit("The Azure python sdk is not installed (try `pip install 'azure>=2.0.0rc5' --upgrade`) - {0}".format(HAS_AZURE_EXC)) - if LooseVersion(azure_compute_version) != LooseVersion(AZURE_MIN_VERSION): + if Version(azure_compute_version) < Version(AZURE_MIN_VERSION): sys.exit("Expecting azure.mgmt.compute.__version__ to be {0}. Found version {1} " - "Do you have Azure == 2.0.0rc5 installed?".format(AZURE_MIN_VERSION, azure_compute_version)) + "Do you have Azure >= 2.0.0rc5 installed? (try `pip install 'azure>=2.0.0rc5' --upgrade`)".format(AZURE_MIN_VERSION, azure_compute_version)) AzureInventory()