Repository: ansible/ansible

Issue:
Openstack/os_user missing description parameter
_From @peerster on October 7, 2016 7:17_

<!--- Verify first that your issue/request is not already reported in GitHub -->
##### ISSUE TYPE
- Feature Idea
##### COMPONENT NAME

<!--- Name of the plugin/module/task -->

os_user.py
##### ANSIBLE VERSION

<!--- Paste verbatim output from “ansible --version” between quotes below -->

```
$ ansible --version
ansible 2.1.2.0
```
##### CONFIGURATION

<!---
Mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).
-->
##### OS / ENVIRONMENT

<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say “N/A” for anything that is not platform-specific.
-->

N/A
##### SUMMARY

<!--- Explain the problem briefly -->

When creating users in Openstack it's possible to enter a description for the user.
The module `os_user` is missing this option.
##### STEPS TO REPRODUCE

<!---
For bugs, show exactly how to reproduce the problem.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->

```

```

<!--- You can also paste gist.github.com links for larger files -->
##### EXPECTED RESULTS

<!--- What did you expect to happen when running the steps above? -->
##### ACTUAL RESULTS

<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->

```

```


_Copied from original issue: ansible/ansible-modules-core#5182_


Discussion:
_From @ansibot on October 7, 2016 13:11_

<!-- @peerster: Thanks for filing this feature idea! -->

@emonty, @shrews, @juliakreger, @j2sol, @rcarrillocruz, ping. This issue is waiting on your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

<!--- boilerplate: issue_bug_new --->

_From @rcarrillocruz on October 10, 2016 8:38_

happy to take this one

_From @rcarrillocruz on October 10, 2016 10:32_

This requires a change on the shade library:

https://review.openstack.org/#/c/384404/

Once this merges, I'll prepare a patch for Ansible os_user.

👍

_From @ansibot on December 7, 2016 19:13_

This repository has been locked. All new issues and pull requests should be filed in https://github.com/ansible/ansible

Please read through the <a href="http://docs.ansible.com/ansible/dev_guide/repomerge.html#move-issues-and-prs-to-new-repo">repomerge</a> page in the dev guide. The guide contains links to tools which automatically move your issue or pull request to the ansible/ansible repo.

<!-- boilerplate: repomerge -->
cc @shrews, @thingee
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
@rcarrillocruz In case you missed it, your patch for shade is merged https://review.openstack.org/#/c/384404/ :+1: 

Resolving patch:
diff --git a/lib/ansible/modules/cloud/openstack/os_user.py b/lib/ansible/modules/cloud/openstack/os_user.py
--- a/lib/ansible/modules/cloud/openstack/os_user.py
+++ b/lib/ansible/modules/cloud/openstack/os_user.py
@@ -55,6 +55,10 @@
         - Email address for the user
      required: false
      default: None
+   description:
+     description:
+        - Description about the user
+     version_added: "2.4"
    default_project:
      description:
         - Project name or ID that the user should be associated with by default
@@ -147,11 +151,14 @@
     HAS_SHADE = True
 except ImportError:
     HAS_SHADE = False
+from distutils.version import StrictVersion
+from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.openstack import openstack_full_argument_spec, openstack_module_kwargs
 
 
 def _needs_update(params_dict, user):
-    for k, v in params_dict.items():
-        if k not in ('password', 'update_password') and user[k] != v:
+    for k in params_dict:
+        if k not in ('password', 'update_password') and user[k] != params_dict[k]:
             return True
 
     # We don't get password back in the user object, so assume any supplied
@@ -162,6 +169,7 @@ def _needs_update(params_dict, user):
 
     return False
 
+
 def _get_domain_id(cloud, domain):
     try:
         # We assume admin is passing domain id
@@ -177,6 +185,7 @@ def _get_domain_id(cloud, domain):
 
     return domain_id
 
+
 def _get_default_project_id(cloud, default_project, module):
     project = cloud.get_project(default_project)
     if not project:
@@ -184,18 +193,18 @@ def _get_default_project_id(cloud, default_project, module):
 
     return project['id']
 
-def main():
 
+def main():
     argument_spec = openstack_full_argument_spec(
         name=dict(required=True),
         password=dict(required=False, default=None, no_log=True),
         email=dict(required=False, default=None),
         default_project=dict(required=False, default=None),
+        description=dict(type='str'),
         domain=dict(required=False, default=None),
         enabled=dict(default=True, type='bool'),
         state=dict(default='present', choices=['absent', 'present']),
-        update_password=dict(default='always', choices=['always',
-                                                        'on_create']),
+        update_password=dict(default='always', choices=['always', 'on_create']),
     )
 
     module_kwargs = openstack_module_kwargs()
@@ -214,6 +223,10 @@ def main():
     enabled = module.params['enabled']
     state = module.params['state']
     update_password = module.params['update_password']
+    description = module.params['description']
+
+    if description and StrictVersion(shade.__version__) < StrictVersion('1.13.0'):
+        module.fail_json(msg="To utilize description, the installed version of the shade library MUST be >=1.13.0")
 
     try:
         cloud = shade.openstack_cloud(**module.params)
@@ -227,23 +240,30 @@ def main():
         if state == 'present':
             if update_password in ('always', 'on_create'):
                 if not password:
-                    msg = ("update_password is %s but a password value is "
-                          "missing") % update_password
+                    msg = "update_password is %s but a password value is missing" % update_password
                     module.fail_json(msg=msg)
             default_project_id = None
             if default_project:
                 default_project_id = _get_default_project_id(cloud, default_project, module)
 
             if user is None:
-                user = cloud.create_user(
-                    name=name, password=password, email=email,
-                    default_project=default_project_id, domain_id=domain_id,
-                    enabled=enabled)
+                if description is not None:
+                    user = cloud.create_user(
+                        name=name, password=password, email=email,
+                        default_project=default_project_id, domain_id=domain_id,
+                        enabled=enabled, description=description)
+                else:
+                    user = cloud.create_user(
+                        name=name, password=password, email=email,
+                        default_project=default_project_id, domain_id=domain_id,
+                        enabled=enabled)
                 changed = True
             else:
                 params_dict = {'email': email, 'enabled': enabled,
                                'password': password,
                                'update_password': update_password}
+                if description is not None:
+                    params_dict['description'] = description
                 if domain_id is not None:
                     params_dict['domain_id'] = domain_id
                 if default_project_id is not None:
@@ -251,15 +271,27 @@ def main():
 
                 if _needs_update(params_dict, user):
                     if update_password == 'always':
-                        user = cloud.update_user(
-                            user['id'], password=password, email=email,
-                            default_project=default_project_id,
-                            domain_id=domain_id, enabled=enabled)
+                        if description is not None:
+                            user = cloud.update_user(
+                                user['id'], password=password, email=email,
+                                default_project=default_project_id,
+                                domain_id=domain_id, enabled=enabled, description=description)
+                        else:
+                            user = cloud.update_user(
+                                user['id'], password=password, email=email,
+                                default_project=default_project_id,
+                                domain_id=domain_id, enabled=enabled)
                     else:
-                        user = cloud.update_user(
-                            user['id'], email=email,
-                            default_project=default_project_id,
-                            domain_id=domain_id, enabled=enabled)
+                        if description is not None:
+                            user = cloud.update_user(
+                                user['id'], email=email,
+                                default_project=default_project_id,
+                                domain_id=domain_id, enabled=enabled, description=description)
+                        else:
+                            user = cloud.update_user(
+                                user['id'], email=email,
+                                default_project=default_project_id,
+                                domain_id=domain_id, enabled=enabled)
                     changed = True
                 else:
                     changed = False
@@ -267,18 +299,15 @@ def main():
 
         elif state == 'absent':
             if user is None:
-                changed=False
+                changed = False
             else:
                 cloud.delete_user(user['id'])
-                changed=True
+                changed = True
             module.exit_json(changed=changed)
 
     except shade.OpenStackCloudException as e:
         module.fail_json(msg=str(e), extra_data=e.extra_data)
 
-from ansible.module_utils.basic import *
-from ansible.module_utils.openstack import *
-
 
 if __name__ == '__main__':
     main()


Test patch:
diff --git a/test/sanity/pep8/legacy-files.txt b/test/sanity/pep8/legacy-files.txt
--- a/test/sanity/pep8/legacy-files.txt
+++ b/test/sanity/pep8/legacy-files.txt
@@ -215,7 +215,6 @@ lib/ansible/modules/cloud/openstack/os_server_volume.py
 lib/ansible/modules/cloud/openstack/os_stack.py
 lib/ansible/modules/cloud/openstack/os_subnet.py
 lib/ansible/modules/cloud/openstack/os_subnets_facts.py
-lib/ansible/modules/cloud/openstack/os_user.py
 lib/ansible/modules/cloud/openstack/os_user_facts.py
 lib/ansible/modules/cloud/openstack/os_user_group.py
 lib/ansible/modules/cloud/openstack/os_user_role.py