-
Notifications
You must be signed in to change notification settings - Fork 23.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Now influxdb_user module can change user password #35471
Conversation
The test
The test
The test
The test
The test
The test
The test
|
0b0381c
to
574283d
Compare
influxdb = InfluxDb(module) | ||
client = influxdb.connect_to_influxdb() | ||
try: | ||
client.switch_user(user_name, user_password) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switch_user function just sets two properties, it doesn't call server:
self._username = username
self._password = password
We should execute some command on server, that's why we call get_list_users
.
that: | ||
- change_password.changed == true | ||
|
||
- name: Test remove user in check mode |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've found that there are no tests to check user removal. So I've added them. And I can move them into separate PR if needed. :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Integration tests are always welcomed. I think we can keep it here unless there is a specific reason not to.
574283d
to
19b7231
Compare
The test
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try to keep code clean and don't duplicate it.
@@ -83,6 +83,12 @@ | |||
from ansible.module_utils.basic import AnsibleModule | |||
from ansible.module_utils.influxdb import InfluxDb | |||
|
|||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this block is already in module_utils i don't think it is necessary to duplicate code.
86..91 take a look on module_utils/influxdb.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhhuta, Thank you for the review!
As you see, I need to catch InfluxDBClientError in the check_user_password function.
This error defined in the influxdb-python module. That's why I need to add import line:
from influxdb.exceptions import InfluxDBClientError
If I add only the import
line, then test ansible-test sanity --test import --python XX
will fail with the error:
lib/ansible/modules/database/influxdb/influxdb_user.py:85:0: ImportError: No module named influxdb..exceptions
I've already tried. :-)
It is because of this check:
All Python imports in
lib/ansible/modules/
andlib/ansible/module_utils/
which are not from the Python standard library must be imported in a try/except ImportError block.
That's why I'd copied try...except
from module_utils/influxdb.py:
try:
from influxdb.exceptions import InfluxDBClientError
HAS_INFLUXDB = True
except ImportError:
HAS_INFLUXDB = False
I think I can replace this block with
try:
from influxdb.exceptions import InfluxDBClientError
except ImportError:
pass
And then I can drop:
if not HAS_INFLUXDB:
module.fail_json(msg='This module requires influxdb python package.')
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets keep logic striate: you want set password if user already exist:
if user:
if check_user_password(module, user_name, user_password):
module.exit_json(changed=False)
else:
set_user_password(module, client, user_name, user_password)
else:
create_user(module, client, user_name, user_password, admin)
it's ok but lets look on logic above, you already have
client = influxdb.connect_to_influxdb()
and when you call check_user_password
you create another connection to db inside of this function.
influxdb = InfluxDb(module)
client = influxdb.connect_to_influxdb()
Obviously you can pass to this function client object that was init in main()
Next
client.switch_user(user_name, user_password)
client.get_list_users()
except InfluxDBClientError as e:
if e.code == 401:
return False
why do you useclient.get_list_users()
? it returns a list of users : actually a list-object. I guess you can keep only client.switch_user(user_name, user_password)
Another is about InfluxDBClientError
its already part of InfluxDBClient that we import from influxdb in module_utils/influxdb.py
and if you go deeper in influxdb-python/influxdb/client.py
Any way let me try to work with your code and figure out how we can make this code more clean
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
take a look on drop_user()
try:
client.drop_user(user_name)
except client.InfluxDBClientError as e:
module.fail_json(msg=e.content)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
Import
take a look on drop_user()
try: client.drop_user(user_name) except client.InfluxDBClientError as e: module.fail_json(msg=e.content)
@zhhuta Are you sure that this code works? I'm not a python expert, sorry if I say something stupid.
I've tried to causeInfluxDBClientError
indrop_user
. I've replaced it by:def drop_user(module, client, user_name): if not module.check_mode: try: client.switch_user('test', 'test') client.drop_user(user_name) except client.InfluxDBClientError as e: module.fail_json(msg=e.content) module.exit_json(changed=True)
As you can see, I've added
client.switch_user('test', 'test')
. This line always causesInfluxDBClientError
with code 401 (Unauthorized) (there is no 'test' user in my InfluxDB).
Then I've run the following test:- name: Add user influxdb_user: user_name=user user_password=password login_username=admin login_password=admin - name: Remove user influxdb_user: user_name=user state=absent login_username=admin login_password=admin
It failed with the error
AttributeError: 'InfluxDBClient' object has no attribute 'InfluxDBClientError'
:An exception occurred during task execution. To see the full traceback, use -vvv. The error was: AttributeError: 'InfluxDBClient' object has no attribute 'InfluxDBClientError' fatal: [testhost]: FAILED! => {"changed": false, "failed": true, "module_stderr": "Traceback (most recent call last):\n File \"/tmp/ansible_sSZKDE/ansible_module_influxdb_user.py\", line 195, in <module>\n main()\n File \"/tmp/ansible_sSZKDE/ansible_module_influxdb_user.py\", line 189, in main\n drop_user(module, client, user_name)\n File \"/tmp/ansible_sSZKDE/ansible_module_influxdb_user.py\", line 147, in drop_user\n except client.InfluxDBClientError as e:\nAttributeError: 'InfluxDBClient' object has no attribute 'InfluxDBClientError'\n", "module_stdout": "", "msg": "MODULE FAILURE", "rc": 1}
When I've added import:
from influxdb.exceptions import InfluxDBClientError
and replaced
client.InfluxDBClientError
toInfluxDBClientError
in drop_user function:def drop_user(module, client, user_name): if not module.check_mode: try: client.switch_user('test', 'test') client.drop_user(user_name) except InfluxDBClientError as e: module.fail_json(msg=e.content) module.exit_json(changed=True)
the test have failed as expected:
fatal: [testhost]: FAILED! => {"changed": false, "failed": true, "msg": "{\"error\":\"authorization failed\"}\n"}
That's why I think that we need to explicitly add import.
-
Pass client from
main
and when you call check_user_password you create another connection to db inside of this function.
influxdb = InfluxDb(module) client = influxdb.connect_to_influxdb()
Obviously you can pass to this function client object that was init in main()
As you know, there are two users in the module:
username
+password
(with aliaseslogin_username
+login_password
). This user is used to authenticate against InfluxDB server.user_name
+user_password
. This is user to modify.
When
main
calls your version ofcheck_user_password
:def check_user_password(module, client, user_name, user_password): try: client.switch_user(user_name, user_password) client.get_list_users() except client.InfluxDBClientError as e: if e.code == 401: return False except ansible.module_utils.urls.ConnectionError as e: module.fail_json(msg=str(e)) return True
it replaces
username
andpassword
(user for authentication) inclient
byuser_name
anduser_password
(user to modify) and never rollbacks. Thus ifcheck_user_password
returnsFalse
,set_user_password(module, client, user_name, user_password)
call will never succeed.But I understand your concern. What do you think if I change
check_user_password
by this:def check_user_password(module, client, user_name, user_password): try: client.switch_user(user_name, user_password) client.get_list_users() except InfluxDBClientError as e: if e.code == 401: return False except ansible.module_utils.urls.ConnectionError as e: module.fail_json(msg=str(e)) finally: # restore previous user client.switch_user(module.params['username'], module.params['password']) return True
-
Use only
switch_user
callwhy do you use
client.get_list_users()
? it returns a list of users : actually a list-object. I guess you can keep onlyclient.switch_user(user_name, user_password)
As I've already written, switch_user function just sets two properties, it doesn't call server:
def switch_user(self, username, password): """Change the client's username. :param username: the username to switch to :type username: str :param password: the password for the username :type password: str """ self._username = username self._password = password
get_list_users
is just a random function which calls server.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi Artem.
I miss switch user logic in influxdb/client.py - you are right and i got the logic - i agree on suggested change in 2 and it make sense to keep switch_user.
about InfluxDBClientError i guess i need to dive more deep and get understanding thy dependency doesn't work as it import in influxdb/client.py
from .exceptions import InfluxDBClientError
from .exceptions import InfluxDBServerError```
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually i've figured out and code need to be refactored in next way
from ansible.module_utils.influxdb import *
so you can use exceptions.InfluxDBClientError
but it's not really nice way of import
it's another way
import ansible.module_utils.influxdb as influxdb
so it will bring next changes:
argument_spec = influxdb.InfluxDb.influxdb_argument_spec()
influxdb = inflxudb.InfluxDb(module)
except inflxudb.exceptions.InfluxDBClientError
such refactoring reduce reimport but bring some hard to understand call.
@@ -131,6 +161,9 @@ def main(): | |||
supports_check_mode=True | |||
) | |||
|
|||
if not HAS_INFLUXDB: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same thing about code duplication.
164..166 check module_utils/influxdb.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please take a look on refactored file
https://gist.github.com/zhhuta/7cb08f58678375f2bb7f311cade36d92
I've refactored code and tested it |
@zhhuta Great work, thank you! I've added your changes in 59c0ac9. |
@ar7z1 This PR contains |
49a306d
to
59c0ac9
Compare
@resmo Can you look at this PR? |
shipit |
SUMMARY
Previous implementation didn't allow to change user password.
Test to reproduce the problem:
In this PR I've added some code to check if we should change user password. The only way to check is try to authenticate. And if authentication failed with error
401
(Unauthorized), we should change user password.ISSUE TYPE
COMPONENT NAME
influxdb_user
ANSIBLE VERSION
ADDITIONAL INFORMATION