Skip to content
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

Enable check_mode in command module #40428

Merged
merged 2 commits into from Jul 23, 2018
Merged

Enable check_mode in command module #40428

merged 2 commits into from Jul 23, 2018

Conversation

jradtilbrook
Copy link
Contributor

SUMMARY

As per #15828. This adds support for check_mode where possible and leaves behaviour as is where not. This only works if supplying creates or removes since it needs something to base the heuristic off. If none are supplied it will just skip as usual.

Fixes #15828.

ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

lib/ansible/modules/commands/command.py

ANSIBLE VERSION
ansible 2.5.2
  config file = None
  configured module search path = [u'/Users/jradtilbrook/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/Cellar/ansible/2.5.2/libexec/lib/python2.7/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.15 (default, May  1 2018, 16:44:08) [GCC 4.2.1 Compatible Apple LLVM 9.1.0 (clang-902.0.39.1)]
ADDITIONAL INFORMATION

I wasn't too sure about the messages to use. Let me know if you want them changed to something better.

@ansibot ansibot added affects_2.6 This issue/PR affects Ansible v2.6 core_review In order to be merged, this PR must follow the core review workflow. feature This issue/PR relates to a feature request. module This issue/PR relates to a module. needs_triage Needs a first human triage before being processed. new_contributor This PR is the first contribution by a new community member. support:core This issue/PR relates to code supported by the Ansible Engineering Team. labels May 19, 2018
@maxamillion
Copy link
Contributor

If this change is going to land, I think it should have an explicit explanation as to what check_mode means within the context of the module in the module's documentation.

@ansibot ansibot removed the needs_triage Needs a first human triage before being processed. label May 22, 2018
@jradtilbrook
Copy link
Contributor Author

Absolutely. I didn't want to spend too much time if it wasn't going to get accepted, but if you think it will I'm happy to add better docs. It looks like its built from the comments on the module so that's all I would need to do.

Are you okay with the current implementation? I'd prefer to lock that down before doing the documentation.

@nitzmahone
Copy link
Member

I've actually done something in the past with custom versions of command/shell that had a check_mode_command arg that would run a different command under check mode (so as a playbook author you could do something different and guaranteed "not to change" things without a second task). I keep thinking we should explore that as an option as well, but this change wouldn't preclude that from happening in the future... +1 from me...

@abadger
Copy link
Contributor

abadger commented May 24, 2018

There's no conceptual problem with this. However, there are some implementation details to change.

  • Right now, command returns changed=True by default. We need that to be the case in check mode as well.
  • We don't use skipped for this type of thing. Returning changed=True rather than skipped=True is the right thing to do.
  • It's probably simpler coding style to just put rc, out, err = module.run_command(args, executable=executable, use_unsafe_shell=shell, encoding=None, data=stdin) inside of a condition on module.check_mode, setting rc=0 and set out and err to some marker values (b'Command not run in check mode' perhaps?) when we're in check_mode.

@abadger
Copy link
Contributor

abadger commented May 24, 2018

Hold on, I was wrong about changed versus skipped. Talking it over with the other committers.

@jimi-c jimi-c self-requested a review May 24, 2018 17:31
Copy link
Member

@jimi-c jimi-c left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will need changes to the documentation (as well as for shell.py, which has its own document stub) noting that the behavior under check mode has been slightly modified. This should also be noted in the porting guide for 2.6.

@ansibot ansibot added needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed core_review In order to be merged, this PR must follow the core review workflow. labels May 24, 2018
@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Jun 1, 2018
@jradtilbrook
Copy link
Contributor Author

This is getting a bit stale now. I was waiting for @abadger to confirm after their comments before making any other changes. Should I continue to wait or progress with the changes requested by @jimi-c?

@samdoran
Copy link
Contributor

samdoran commented Jul 7, 2018

I think the current changed or skipped reporting in this PR is accurate:

  • If creates/deletes and in check mode, report changed True/False
  • Otherwise skip in check mode

It would be nice to have an option to run another command in check mode, but that overcomplicates this change. That could be addressed in a future PR.

@abadger
Copy link
Contributor

abadger commented Jul 7, 2018

I agree with @samdoran You can ignore my skipped vs changed request. Do take a look at my third bullet point (about reducing the number of conditionals by simplifying the code), though

@jradtilbrook
Copy link
Contributor Author

I've looked into your third point but can't come up with anything that is much better than what there is now. Either way, the conditionals for creates/removes and the glob checking needs to be done so it stays about as messy as it is now.
Perhaps you could elaborate further?

# skip if in check mode so no changes are made
if module.check_mode:
module.exit_json(msg="skipped, running in check mode", skipped=True)

startd = datetime.datetime.now()

rc, out, err = module.run_command(args, executable=executable, use_unsafe_shell=shell, encoding=None, data=stdin)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of the checks inside of the removes and creates conditions above, conditionalize running this command on check_mode like this:

startd = datetime.datetime.now()

if not module.check_mode:
    rc, out, err = module.run_command(args, executable=executable, use_unsafe_shell=shell, encoding=None, data=stdin)
elif removes or creates:
    rc = 0
    stdout = stderr = b'Command would have run if not in check mode'
else:
    module.exit_json(msg="skipped, running in check mode", skipped=True)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, that is clearer but I don't think this would be what we want.

This would not let the user know if it would change or not, ie. it doesn't really add anything to what it currently does.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll carry on the conversation here, closer to the code it references ...

I'm assuming that your suggestion means that lines 218-258 (in my current code) would be removed, otherwise the middle elif removes or creates: will never be true because its handled above. In that case, my current code differs in that it will actually check whether the file exists and will report a changed value accordingly, whereas your suggestion will return a blanket maybe without actually checking.

I feel we might be getting wires crossed here so I'll reiterate my intentions just in case - I would like for this module to be able to handle check mode and use the provided creates/removes to return something other than the skipped it currently does.

Let me know if you were actually meaning for lines 218-258 to remain. If so, this still wouldn't have reduced the number of conditionals. Also let me know if I'm not clear enough about what I'd like the module to do. Sorry for any confusion 😄

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm I realised you were asking for an example (plus, I messed up the explanation anyway):

I use the module setting creates to some file it is supposed to create, I run the playbook in check mode.
In your suggestion it reports as changed but it actually might not have been.
In my current implementation it will report as changed if it doesn't exist and not if it does exist.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct that I imagine the changes in 218-258 going away. However, the existing code should still run. So if you pass in creates and the file exists, line 222 should be true and the module will exit using the normal code path saying that it would not make a change.

If the file does not exist, we will progress to the conditional I propose and set stdout to say that the command would have run if not in check mode. Then the module will exit normally with changed=true. Am I wrong?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yes I see now and it all makes sense!! I'll update the code now but the docs update for the shell module I'll have to do another time (hopefully tomorrow). Sorry to keep bugging you

@abadger
Copy link
Contributor

abadger commented Jul 12, 2018

Added a comment on the code that shows what I meant.

@abadger
Copy link
Contributor

abadger commented Jul 13, 2018 via email

@abadger
Copy link
Contributor

abadger commented Jul 16, 2018

Sorry, autocorrect on my phone really mangled that... Can you trace the code path for me where it outputs something differently than your version?

@jradtilbrook
Copy link
Contributor Author

@jimi-c @maxamillion Is there any specific wording or place I should mention the changed behaviour of this module under check mode?
I'm thinking it fits under either the description or the notes section, and something like: The behavior under check mode has changed. If creates or removes is specified the module will perform checks to determine if a change will be made. If those are not provided it will be skipped

@ansibot ansibot removed the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Jul 17, 2018
@maxamillion
Copy link
Contributor

Nothing specific that comes to mind, but I'd want to make sure that anywhere in the docs we introduce the concept of check_mode there is a note about this. Also the module docs for the shell and command modules should reflect the change. @abadger @jimi-c thoughts?

@abadger
Copy link
Contributor

abadger commented Jul 17, 2018 via email

jradtilbrook added 2 commits July 18, 2018 18:25
This only works if supplying creates or removes since it needs
something to base the heuristic off. If none are supplied it will just
skip as usual.
Fixes ansible#15828
@ansibot ansibot added the docs This issue/PR relates to or includes documentation. label Jul 18, 2018
@abadger abadger merged commit 460f858 into ansible:devel Jul 23, 2018
@abadger
Copy link
Contributor

abadger commented Jul 23, 2018

@jradtilbrook Thanks for your hard work and patience getting this finalized! Merged to devel for the 2.7.0 release.

@jradtilbrook
Copy link
Contributor Author

No worries, thanks for your help and sorry about all the back-and-forth from me trying to clarify! 😀

@ansible ansible locked and limited conversation to collaborators Jul 22, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.6 This issue/PR affects Ansible v2.6 docs This issue/PR relates to or includes documentation. feature This issue/PR relates to a feature request. module This issue/PR relates to a module. needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. new_contributor This PR is the first contribution by a new community member. support:core This issue/PR relates to code supported by the Ansible Engineering Team.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Modules with creates= / removes= could support check mode
7 participants