Repository: ansible/ansible

Issue:
Feature Idea: rabbitmq_user update password only
From @benjamin-bergia on 2016-01-21T10:13:10Z

##### ISSUE TYPE
 - Feature Idea

##### COMPONENT NAME
rabbitmq_user

##### Ansible Version:

```
ansible 2.1.0 (devel 627dec716b) last updated 2016/01/21 18:00:33 (GMT +800)
  lib/ansible/modules/core: (detached HEAD 002028748f) last updated 2016/01/05 15:44:18 (GMT +800)
  lib/ansible/modules/extras: (detached HEAD f6a7b6dd1f) last updated 2016/01/05 15:44:18 (GMT +800)
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### Ansible Configuration:

```
[defaults]                                                                                                                                      
host_key_checking = False                                                                                                                       
gathering = smart                                                                                                                               
fact_caching = jsonfile                                                                                                                         
fact_caching_connection = /tmp/ansible                                                                                                          
fact_caching_timeout = 86400
```
##### Environment:

Running on Ubuntu Wily. Managed nodes are Joyent SmartMachines
##### Summary:

I am using the rabbitmq_user module to manage the users from our rabbitmq server. If I decide to change the password of one of my existing users, I need to specify force=true. By doing so, user will be deleted and recreated even without changes. Would it be possible update an user password without having to use force ?
##### Steps To Reproduce:

```
- rabbitmq_user: user=existingUser
                 password=newPassword
                 vhost=/
                 configure_priv=.*
                 read_priv=.*
                 write_priv=.*
                 state=present
```
##### Expected Results:

User password should be updated
##### Actual Results:

No changes

Copied from original issue: ansible/ansible-modules-extras#1533

Feature Idea: rabbitmq_user update password only
From @benjamin-bergia on 2016-01-21T10:13:10Z

##### ISSUE TYPE
 - Feature Idea

##### COMPONENT NAME
rabbitmq_user

##### Ansible Version:

```
ansible 2.1.0 (devel 627dec716b) last updated 2016/01/21 18:00:33 (GMT +800)
  lib/ansible/modules/core: (detached HEAD 002028748f) last updated 2016/01/05 15:44:18 (GMT +800)
  lib/ansible/modules/extras: (detached HEAD f6a7b6dd1f) last updated 2016/01/05 15:44:18 (GMT +800)
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```
##### Ansible Configuration:

```
[defaults]                                                                                                                                      
host_key_checking = False                                                                                                                       
gathering = smart                                                                                                                               
fact_caching = jsonfile                                                                                                                         
fact_caching_connection = /tmp/ansible                                                                                                          
fact_caching_timeout = 86400
```
##### Environment:

Running on Ubuntu Wily. Managed nodes are Joyent SmartMachines
##### Summary:

I am using the rabbitmq_user module to manage the users from our rabbitmq server. If I decide to change the password of one of my existing users, I need to specify force=true. By doing so, user will be deleted and recreated even without changes. Would it be possible update an user password without having to use force ?
##### Steps To Reproduce:

```
- rabbitmq_user: user=existingUser
                 password=newPassword
                 vhost=/
                 configure_priv=.*
                 read_priv=.*
                 write_priv=.*
                 state=present
```
##### Expected Results:

User password should be updated
##### Actual Results:

No changes

Copied from original issue: ansible/ansible-modules-extras#1533



Discussion:
From @ansibot on 2016-01-21T10:13:10Z

<!-- @benjamin-bergia: Thanks for filing this feature idea! -->

@chrishoffman ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

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

From @krzysztof-magosa on 2016-01-21T10:13:10Z

`user` module has parameter `update_password` parameter.
I believe `rabbitmq_user` module should follow that.
The only problem is that `rabbitmqctl` does not report whether password has been changed or not:

```
[root@centos-7 vagrant]# rabbitmqctl change_password km new_pass
Changing password for user "km" ...
...done.
[root@centos-7 vagrant]# echo $?
0
[root@centos-7 vagrant]# rabbitmqctl change_password km new_pass
Changing password for user "km" ...
...done.
[root@centos-7 vagrant]# echo $?
0
```

cc @hyperized @manuel-sousa @romanek-adam
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Regarding the issue with `rabbitmqctl change_password` reporting, could we at least implement this as described and always assume a change? We could then send a feature request upstream and add support to ansible when or if it is addressed.

Managing rabbitmq user credentials in ansible is currently impossible without `force=yes`, which is far from ideal. Having the option to merely set the password seems a worthwhile tradeoff for imperfect change status reporting.
From @ansibot on 2016-01-21T10:13:10Z

<!-- @benjamin-bergia: Thanks for filing this feature idea! -->

@chrishoffman ping, this issue is waiting for your response.
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)

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

From @krzysztof-magosa on 2016-01-21T10:13:10Z

`user` module has parameter `update_password` parameter.
I believe `rabbitmq_user` module should follow that.
The only problem is that `rabbitmqctl` does not report whether password has been changed or not:

```
[root@centos-7 vagrant]# rabbitmqctl change_password km new_pass
Changing password for user "km" ...
...done.
[root@centos-7 vagrant]# echo $?
0
[root@centos-7 vagrant]# rabbitmqctl change_password km new_pass
Changing password for user "km" ...
...done.
[root@centos-7 vagrant]# echo $?
0
```

cc @hyperized @manuel-sousa @romanek-adam
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Regarding the issue with `rabbitmqctl change_password` reporting, could we at least implement this as described and always assume a change? We could then send a feature request upstream and add support to ansible when or if it is addressed.

Managing rabbitmq user credentials in ansible is currently impossible without `force=yes`, which is far from ideal. Having the option to merely set the password seems a worthwhile tradeoff for imperfect change status reporting.

Resolving patch:
diff --git a/lib/ansible/modules/messaging/rabbitmq_user.py b/lib/ansible/modules/messaging/rabbitmq_user.py
--- a/lib/ansible/modules/messaging/rabbitmq_user.py
+++ b/lib/ansible/modules/messaging/rabbitmq_user.py
@@ -31,7 +31,7 @@
     description:
       - Password of user to add.
       - To change the password of an existing user, you must also specify
-        C(force=yes).
+        C(update_password=always).
   tags:
     description:
       - User tags specified as comma delimited
@@ -84,6 +84,13 @@
       - Specify if user is to be added or removed
     default: present
     choices: [present, absent]
+  update_password:
+    description:
+      - C(on_create) will only set the password for newly created users.  C(always) will update passwords if they differ.
+    required: false
+    default: on_create
+    choices: [ on_create, always ]
+    version_added: "2.6"
 '''
 
 EXAMPLES = '''
@@ -180,6 +187,9 @@ def _get_permissions(self):
                                        write_priv=write_priv, read_priv=read_priv))
         return perms_list
 
+    def check_password(self):
+        return self._exec(['authenticate_user', self.username, self.password], True)
+
     def add(self):
         if self.password is not None:
             self._exec(['add_user', self.username, self.password])
@@ -190,6 +200,12 @@ def add(self):
     def delete(self):
         self._exec(['delete_user', self.username])
 
+    def change_password(self):
+        if self.password is not None:
+            self._exec(['change_password', self.username, self.password])
+        else:
+            self._exec(['clear_password', self.username])
+
     def set_tags(self):
         self._exec(['set_user_tags', self.username] + self.tags)
 
@@ -229,7 +245,8 @@ def main():
         read_priv=dict(default='^$'),
         force=dict(default='no', type='bool'),
         state=dict(default='present', choices=['present', 'absent']),
-        node=dict(default=None)
+        node=dict(default=None),
+        update_password=dict(default='on_create', choices=['on_create', 'always'])
     )
     module = AnsibleModule(
         argument_spec=arg_spec,
@@ -247,6 +264,7 @@ def main():
     force = module.params['force']
     state = module.params['state']
     node = module.params['node']
+    update_password = module.params['update_password']
 
     bulk_permissions = True
     if not permissions:
@@ -274,6 +292,10 @@ def main():
                 rabbitmq_user.add()
                 rabbitmq_user.get()
                 result['changed'] = True
+            elif update_password == 'always':
+                if not rabbitmq_user.check_password():
+                    rabbitmq_user.change_password()
+                    result['changed'] = True
 
             if rabbitmq_user.has_tags_modifications():
                 rabbitmq_user.set_tags()


Test patch: