-
Notifications
You must be signed in to change notification settings - Fork 86
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
Fix mysqldump ignoring errors #403
Fix mysqldump ignoring errors #403
Conversation
sh is missing the pipefail flag. We must use bash for this.
Codecov Report
@@ Coverage Diff @@
## main #403 +/- ##
==========================================
+ Coverage 77.71% 77.84% +0.13%
==========================================
Files 27 27
Lines 2315 2320 +5
Branches 558 560 +2
==========================================
+ Hits 1799 1806 +7
+ Misses 356 355 -1
+ Partials 160 159 -1
Continue to review full report at Codecov.
|
@laurent-indermuehle thanks for the fix! The CI tests have failed. Please see the logs. Anyway I'm afraid in this implementation it'll be a breaking change.. at least for FreeBSD users as |
@Andersson007 I didn't thought that bash could be missing on some systems. For the CI, it's my first time working with Github Actions. I see that some tests are returning a none 0 code but have no clue why. On my machine, units, integrations and sanity tests passes. |
Thanks!
It's because your local fork contains default versions of things we test against (listed in the setup_mysql role that prepares the test environment and is run before every target as a dependency). When you're debugging, the easiest (imo) algorithm is to:
Following these steps, i can see that the error is
|
It looks like only tests against Python 3.6 failed |
@Andersson007 Thanks for the workflow to read GH Actions logs! It helps :) I'm not sure what the issue is. I see so many things that looks weird to me:
TASK [test_mysql_db : remove database if it exists]
[fatal: [testhost]: FAILED! => {
"cmd": "'mysql -uroot -pmsandbox -P3307 --protocol=tcp -sse '\"'\"'drop database data'\"'\"''",
"msg": "[Errno 2] No such file or directory: b\"mysql -uroot -pmsandbox -P3307 --protocol=tcp -sse 'drop database data'\": b\"mysql -uroot -pmsandbox -P3307 --protocol=tcp -sse 'drop database data'\"",
"rc": 2}
TASK [test_mysql_db : make sure the test database is not there]
[changed: [testhost] => {
"changed": true,
"cmd": ["mysql", "-uroot", "-pmsandbox", "-P3307", "--protocol=tcp", "data"],
"msg": "non-zero return code", "rc": 1,
"stderr": "mysql: ERROR 1049 (42000): Unknown database 'data'",
} I'm running ansible-test locally for Python 3.6. I'll see if the problem is the same on my machine. |
Ok, so MySQL8 causes issue with its new authentication plugin:
I'm starting to wounder if using module_defaults was a good idea? https://github.com/laurent-indermuehle/community.mysql/blob/fix_mysqldump_ignore_errors/tests/integration/targets/test_mysql_db/tasks/issue_256_mysqldump_errors.yml#L6-L12 |
ok, I missed the blue-green 'ignoring' ;) |
I pushed a version with the new option "pipefail". Tests continues to fails using mysql 8 due to a missing package cryptography. I added a changelog fragment and a documentation for the option. I put the "version_added" at 3.3.1 but not sure what number to put. Do I have forgot anything? |
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.
@laurent-indermuehle thanks!
I think it would be nice to add an example to the EXAMPLES block.
I took only a quick look today. I'll take a deeper one tomorrow or on Friday. Thanks!
Co-authored-by: Andrew Klychkov <[email protected]>
Co-authored-by: Andrew Klychkov <[email protected]>
Co-authored-by: Andrew Klychkov <[email protected]>
@Andersson007 I'm done for today. I'm sorry for the number of commits. I'm not used to work on Ansible plugins... yet ;) Thank you if you can review the tests and fixes. |
@laurent-indermuehle no problem at all! Please do any number of commits/ask any questions needed! Thanks for working on this:) |
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.
@laurent-indermuehle one small thing from me besides adding the example as mentioned in my yesterday's comment.
Co-authored-by: Andrew Klychkov <[email protected]>
Great, I commited your changes. I think we are done with this PR, unless the CI tells otherwise. I'm not 100% satisfied because, the default is highly insecure or prevent us from using compression. If a way exists to pipe commands together with Python subcommand.Popen() while preserving the return code of each command, it would be ways better. But I failed to find it. Especially in our case, where this method is wrapped by Ansible module.run_command(). Without help from an expert I can't offer a better solution. I was happy to help, I learned alot and your guidances was very appreciated. |
Agreed. We can change the default later in a major release
I'm happy to help:) |
After having read the documentation for the subprocess module, it seems we can use 2 Popen object and check the returned code of each. While experimenting with that, I found the following code from mysql_db.py into the db_import() function: https://github.com/ansible-collections/community.mysql/blob/main/plugins/modules/mysql_db.py#L492-L512 I'm a bit worried about the "'Broken pipe' errors that occasionally occur" message, but aside from that, it seems to be the solution I was looking for? Right? |
ah, forgot that the module uses the subprocess module directly
Yep, sounds scary
Would you like to continue experimenting or we should merge the PR? I'm not sure, let's ask the other maintainers, @bmalynovytch ideas? |
I created a playbook and a container to test locally with a 100MB database to see if the changes affect performances. Then I created yet another option to mysql_db called 'popen' that uses the following code to compress the dump: import gzip
from shlex import split as shlex_split
if popen:
p1 = subprocess.Popen(shlex_split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with gzip.open(shlex_quote(target), 'wb', compresslevel=5) as f:
stdout, stderr = p1.communicate()
f.write(stdout)
p1.wait()
if p1.returncode != 0:
return p1.returncode, '', to_native(stderr)
else:
return 0, 'Dump done', '' This works, the error is captured popen the same way pipefail did. But:
The good news is, that the performances are almost equivalent :
Without the , compresslevel=5, Python defaults to 9. Which resulted in 6+ seconds per dump. I found that 5 produce the same file size as the shell version. I'm running out of time. I'll get back in 2 weeks. What is left to do:
|
Here is a version without the gzip module: from shlex import split as shlex_split
[...]
if popen:
compress_cmd = [module.get_bin_path('gzip', True), ' > ', shlex_quote(target)]
p1 = subprocess.Popen(shlex_split(cmd), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
p2 = subprocess.Popen(compress_cmd, stdin=p1.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
stdout1, stderr1 = p1.communicate()
stdout2, stderr2 = p2.communicate()
if p1.returncode != 0:
return p1.returncode, '', to_native(stderr1)
else:
return p2.returncode, stdout2, to_native(stderr2) Should I go this route? I tried to use run_command(), but because it uses the .close() method, it will be impossible to pipe two run_command() together. I tried |
@laurent-indermuehle thanks for the experimenting!
@bmalynovytch @rsicart any ideas? |
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.
The approach is the one I would have had.
Good job !
"{{ mysql_command }} -sse 'drop database {{ db_name }}'" | ||
ignore_errors: True | ||
"{{ mysql_command }} -sse 'DROP DATABASE IF EXISTS {{ db_name }}'" | ||
ignore_errors: true | ||
|
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.
Is this related to the issue ? 🤨
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.
No sorry. I did that when the tests were failing on python 3.6.
Should I revert that?
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.
No sorry. I did that when the tests were failing on python 3.6.
I'm curious why they fail if they are not related to the changes. If it's safe, we can leave it as is.
@laurent-indermuehle thanks for the contribution! |
SUMMARY
The mysql_db module does not display mysqldump errors when compression is used.
Fixes #256
ISSUE TYPE
COMPONENT NAME
mysql_db
ADDITIONAL INFORMATION
The issue #256 initially was met the first time because of a too big field and a
max_allowed_packet
to small. As this is difficult to test, the tests were written with a MySQL view pointing to a non-existent table.