This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/lib/ansible/module_utils/openstack.py b/lib/ansible/module_utils/openstack.py | |
index 8f4f7dff06..cdc07210e7 100644 | |
--- a/lib/ansible/module_utils/openstack.py | |
+++ b/lib/ansible/module_utils/openstack.py | |
@@ -26,41 +26,10 @@ | |
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE | |
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
-import os | |
- | |
+from ansible.module_utils.basic import AnsibleModule | |
from ansible.module_utils.six import iteritems | |
-def openstack_argument_spec(): | |
- # DEPRECATED: This argument spec is only used for the deprecated old | |
- # OpenStack modules. It turns out that modern OpenStack auth is WAY | |
- # more complex than this. | |
- # Consume standard OpenStack environment variables. | |
- # This is mainly only useful for ad-hoc command line operation as | |
- # in playbooks one would assume variables would be used appropriately | |
- OS_AUTH_URL = os.environ.get('OS_AUTH_URL', 'http://127.0.0.1:35357/v2.0/') | |
- OS_PASSWORD = os.environ.get('OS_PASSWORD', None) | |
- OS_REGION_NAME = os.environ.get('OS_REGION_NAME', None) | |
- OS_USERNAME = os.environ.get('OS_USERNAME', 'admin') | |
- OS_TENANT_NAME = os.environ.get('OS_TENANT_NAME', OS_USERNAME) | |
- | |
- spec = dict( | |
- login_username=dict(default=OS_USERNAME), | |
- auth_url=dict(default=OS_AUTH_URL), | |
- region_name=dict(default=OS_REGION_NAME), | |
- availability_zone=dict(), | |
- ) | |
- if OS_PASSWORD: | |
- spec['login_password'] = dict(default=OS_PASSWORD) | |
- else: | |
- spec['login_password'] = dict(required=True) | |
- if OS_TENANT_NAME: | |
- spec['login_tenant_name'] = dict(default=OS_TENANT_NAME) | |
- else: | |
- spec['login_tenant_name'] = dict(required=True) | |
- return spec | |
- | |
- | |
def openstack_find_nova_addresses(addresses, ext_tag, key_name=None): | |
ret = [] | |
@@ -108,49 +77,94 @@ def openstack_module_kwargs(**kwargs): | |
return ret | |
-def openstack_cloud_from_module(module, min_version=None, operator=False): | |
- from distutils.version import StrictVersion | |
- try: | |
- import shade | |
- except ImportError: | |
- module.fail_json(msg='shade is required for this module') | |
- | |
- if min_version: | |
- if StrictVersion(shade.__version__) < StrictVersion(min_version): | |
- module.fail_json( | |
- msg="To utilize this module, the installed version of" | |
+class OpenStackModule(AnsibleModule): | |
+ | |
+ def __init__( | |
+ self, argument_spec=None, | |
+ min_version=None, operator=False, **kwargs): | |
+ """Helper class wrapping AnsibleModule for OpenStack modules | |
+ | |
+ There are several things all OpenStack modules need to do to get | |
+ themselves set up properly, including manipulating the argument_spec | |
+ passed to AnsibleModule and ensuring shade is at the right version. | |
+ | |
+ :param dict argument_spec: | |
+ argument_spec dict as expected by AnsibleModule. OpenStackModule | |
+ will inject common arguments into it. | |
+ :param str min_version: | |
+ The minimum version of shade required by the module. | |
+ :param bool operator: | |
+ Whether this module needs an OperatorCloud instance. | |
+ :param **kwargs: | |
+ kwargs to pass to AnsibleModule, with OpenStack specific values | |
+ added. | |
+ """ | |
+ | |
+ if not argument_spec: | |
+ argument_spec = {} | |
+ full_argument_spec = openstack_full_argument_spec(**argument_spec) | |
+ module_kwargs = openstack_module_kwargs(**kwargs) | |
+ | |
+ super(OpenStackModule, self).__init__(argument_spec, **module_kwargs) | |
+ | |
+ from distutils.version import StrictVersion | |
+ self._StrictVersion = StrictVersion | |
+ self._sdk_version = None | |
+ | |
+ try: | |
+ import shade | |
+ except ImportError: | |
+ module.fail_json(msg='shade is required for this module') | |
+ | |
+ # Both of these are slightly weird, but we need to be able to catch | |
+ # shade exceptions and handle them ... and it would be nice to make it | |
+ # easier to update to openstacksdk in a few months without changing | |
+ # ALL of the modules | |
+ self._shade = shade | |
+ self.OpenStackCloudException = shade.OpenStackCloudException | |
+ | |
+ if min_version: | |
+ self.assert_sdk_version(min_version) | |
+ | |
+ if operator: | |
+ cloud_ctr = shade.operator_cloud | |
+ else: | |
+ cloud_ctr = shade.openstack_cloud | |
+ | |
+ cloud_config = self.params.pop('cloud', None) | |
+ if isinstance(cloud_config, dict): | |
+ fail_message = ( | |
+ "A cloud config dict was provided to the cloud parameter" | |
+ " but also a value was provided for {param}. If a cloud" | |
+ " config dict is provided, {param} should be" | |
+ " excluded.") | |
+ for param in ( | |
+ 'auth', 'region_name', 'verify', | |
+ 'cacert', 'key', 'api_timeout', 'interface'): | |
+ if self.params[param] is not None: | |
+ self.fail_json(fail_message.format(param=param)) | |
+ if self.params['auth_type'] != 'password': | |
+ self.fail_json(fail_message.format(param='auth_type')) | |
+ self.cloud = cloud_ctr(**cloud_config) | |
+ else: | |
+ self.cloud = cloud_ctr( | |
+ cloud=cloud_config, | |
+ auth_type=self.params['auth_type'], | |
+ auth=self.params['auth'], | |
+ region_name=self.params['region_name'], | |
+ verify=self.params['verify'], | |
+ cacert=self.params['cacert'], | |
+ key=self.params['key'], | |
+ api_timeout=self.params['api_timeout'], | |
+ interface=self.params['interface'], | |
+ ) | |
+ | |
+ def assert_sdk_version(self, min_version, reason='use this module'): | |
+ if self._sdk_version is None: | |
+ self._sdk_version = self._StrictVersion(shade.__version__) | |
+ if self._sdk_version < self._StrictVersion(min_version): | |
+ self.fail_json( | |
+ msg="To {reason}, the installed version of" | |
"the shade library MUST be >={min_version}".format( | |
+ reason. | |
min_version=min_version)) | |
- | |
- if operator: | |
- cloud_ctr = shade.operator_cloud | |
- else: | |
- cloud_ctr = shade.openstack_cloud | |
- | |
- cloud_config = module.params.pop('cloud', None) | |
- if isinstance(cloud_config, dict): | |
- fail_message = ( | |
- "A cloud config dict was provided to the cloud parameter" | |
- " but also a value was provided for {param}. If a cloud" | |
- " config dict is provided, {param} should be" | |
- " excluded.") | |
- for param in ( | |
- 'auth', 'region_name', 'verify', | |
- 'cacert', 'key', 'api_timeout', 'interface'): | |
- if module.params[param] is not None: | |
- module.fail_json(fail_message.format(param=param)) | |
- if module.params['auth_type'] != 'password': | |
- module.fail_json(fail_message.format(param='auth_type')) | |
- return shade, cloud_ctr(**cloud_config) | |
- else: | |
- return shade, cloud_ctr( | |
- cloud=cloud_config, | |
- auth_type=module.params['auth_type'], | |
- auth=module.params['auth'], | |
- region_name=module.params['region_name'], | |
- verify=module.params['verify'], | |
- cacert=module.params['cacert'], | |
- key=module.params['key'], | |
- api_timeout=module.params['api_timeout'], | |
- interface=module.params['interface'], | |
- ) | |
diff --git a/lib/ansible/modules/cloud/openstack/os_keystone_role.py b/lib/ansible/modules/cloud/openstack/os_keystone_role.py | |
index 175d80158d..b4cc562eb1 100644 | |
--- a/lib/ansible/modules/cloud/openstack/os_keystone_role.py | |
+++ b/lib/ansible/modules/cloud/openstack/os_keystone_role.py | |
@@ -69,8 +69,7 @@ role: | |
sample: "demo" | |
''' | |
-from ansible.module_utils.basic import AnsibleModule | |
-from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs, openstack_cloud_from_module | |
+from ansible.module_utils.openstack import OpenStackModule | |
def _system_state_change(state, role): | |
@@ -82,20 +81,17 @@ def _system_state_change(state, role): | |
def main(): | |
- argument_spec = openstack_full_argument_spec( | |
+ argument_spec = dict( | |
name=dict(required=True), | |
state=dict(default='present', choices=['absent', 'present']), | |
) | |
- | |
- module_kwargs = openstack_module_kwargs() | |
- module = AnsibleModule(argument_spec, | |
- supports_check_mode=True, | |
- **module_kwargs) | |
+ module = OpenStackModule( | |
+ argument_spec, supports_check_mode=True, operator=True) | |
+ cloud = module.cloud | |
name = module.params.get('name') | |
state = module.params.get('state') | |
- shade, cloud = openstack_cloud_from_module(module, operator=True) | |
try: | |
role = cloud.get_role(name) | |
@@ -118,7 +114,7 @@ def main(): | |
changed = True | |
module.exit_json(changed=changed) | |
- except shade.OpenStackCloudException as e: | |
+ except module.OpenStackCloudException as e: | |
module.fail_json(msg=str(e)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment