Skip to content

Instantly share code, notes, and snippets.

@emonty
Created November 30, 2017 15:24
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save emonty/ce8b1c90cf972bfc104e3eb38ae74762 to your computer and use it in GitHub Desktop.
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