-
Notifications
You must be signed in to change notification settings - Fork 898
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
Add simple wrapping code for running ansible-playbook #17564
Conversation
Add simple wrapping code for running ansible-playbook
@agrare @Fryguy @martinpovolny @gtanzillo so with this simple example, I was able to replace AWS power actions ManageIQ/manageiq-providers-amazon#453 Now we need to make sure the packages are installed and we get the And I need to add configurable ansible bin path, since at least for dev, the rpms don't work for me. |
app/models/ansible/runner.rb
Outdated
@@ -0,0 +1,27 @@ | |||
module Ansible | |||
class Runner |
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.
Hm my only problem with this naming is that this is the pattern we use for workers and could be confusing, @Fryguy thoughts?
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.
also, I think I should move this under lib/
👍 a setting for the exact path would be good for the appliance but for dev I would have expected to just be able to pull this from |
@agrare I've added the brakeman issue to ignore, only possible user facing values are the extra_vars, and those are being JSON.dumped, so it should be safe, right? I did add shellescape to all other values, just for sure. (Is there better way to get rid of the brakeman false positive?) |
class Runner | ||
class << self | ||
def run(env_vars, extra_vars, playbook_path) | ||
run_via_cli(env_vars, extra_vars, playbook_path) |
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.
@agrare I wonder if allowing any playbook_path is too much? Maybe we should pass ems and limit it to ems/ansible/ dir?
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.
@Ladas you mean from a security standpoint or usability? I think we'll want to keep this generic, in the provider we might want to have a helper based on the engine root path which we won't know here.
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 what you have here is exactly what I was thinking
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.
ok, sounds good
lib/ansible/runner.rb
Outdated
end | ||
|
||
def format_extra_vars(extra_vars) | ||
"--extra-vars '#{JSON.dump(extra_vars)}'" |
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 think you need to shell_escape the JSON, right? what if it has a single quote in it?
lib/ansible/runner.rb
Outdated
private | ||
|
||
def run_via_cli(env_vars, extra_vars, playbook_path) | ||
result = %x(#{format_env_vars(env_vars)} #{ansible_command.shellescape} #{format_extra_vars(extra_vars)} #{playbook_path.to_s.shellescape}) |
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 think it would be better to use AwesomeSpawn here for building the CLI and executing. This way, you don't have to do any of the shell escaping or env handling yourself as AwesomeSpawn already handles it, and this can focus on just using normal hashes. AwesomeSpawn can also handle non-zero exit codes.
def run_via_cli(env_vars, extra_vars, playbook_path)
result = AwesomeSpawn.run!(ansible_command, :env => env_vars, :params => [{:extra_vars => JSON.dump(extra_vars)}, playbook_path])
JSON.parse(result.output)
end
# no need for all of the format methods here
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 AwesomeSpawn is awesome :-)
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 is looking really nice @Ladas . For build stuff, @simaishi is your best bet. For ansible-runner needed features open issues on https://github.com/ansible/ansible-runner and ping @matburt |
6dc389c
to
b743114
Compare
b743114
to
82a70c5
Compare
Checked commits Ladas/manageiq@b12dbe8~...82a70c5 with ruby 2.3.3, rubocop 0.52.1, haml-lint 0.20.0, and yamllint 1.10.0 lib/ansible/runner.rb
|
@martinpovolny ok, so I've created few API actions, so you can test the UI.
Notes
|
This is a missing feature in the core that I am asking for for some time. |
@martinpovolny ok, so right now, the pluggable product features are in the UI BZ https://bugzilla.redhat.com/show_bug.cgi?id=1589261, let's talk to @gtanzillo, if you want that separated to core task |
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.
LGTM this is a good building block to allow parallel teams to get started
|
||
def ansible_command | ||
# TODO add possibility to use custom path, e.g. from virtualenv | ||
"ansible-playbook" |
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.
@agrare where do you think we should expose this configuration?
E.g. I can't use this in my env, I have weird conflicts with all the data science stuff in python probably. So I have to use "ansible-playbook" from my virtualenv. The conflict is that the ansible modules complain I don't have boto and boto3 pkgs, while I have them. There are few upstream issues for 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.
Hm I think this should be an appliance level setting not something that we would override per provider or per invocation. Something like Settings.ansible.runner_command
?
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.
Appliance level Settings.ansible.runner_command
sounds reasonable
Per provider would make sense if we would have virtualenv per provider type, but I think we are not going that way
This ENV var is not necessary and causes problems with output with newer ansible-runner versions such as 2.2.1. This env var was added in ManageIQ#21382, in order to remove the need for the ansible.cfg. However, walking further back to when the ansible.cfg was added leads us to ManageIQ#17564, which was added in order to support running ansible-playbook (_not ansible-runner_). This variable allows ansible core to return JSON, which was honored by ansible-playbook. ansible-runner takes care of wrapping the output properly for us, so we don't need it, and setting it causes us to lose the "normal" STDOUT we'd otherwise get from ansible-runner.
This ENV var is not necessary and causes problems with output with newer ansible-runner versions such as 2.2.1. This env var was added in ManageIQ#21382, in order to remove the need for the ansible.cfg. However, walking further back to when the ansible.cfg was added leads us to ManageIQ#17564, which was added in order to support running ansible-playbook (_not ansible-runner_). This variable allows ansible core to return JSON, which was honored by ansible-playbook. ansible-runner takes care of wrapping the output properly for us, so we don't need it, and setting it causes us to lose the "normal" STDOUT we'd otherwise get from ansible-runner. ansible-runner 1.4.7 seemingly ignores this value (or perhaps overrides it for its own purposes), so we don't need to set it. For the future versions of ansible-runner, it causes the problems above, so this commit removes it altogether.
This ENV var is not necessary and causes problems with output with newer ansible-runner versions such as 2.2.1. This env var was added in ManageIQ#21382, in order to remove the need for the ansible.cfg. However, walking further back to when the ansible.cfg was added leads us to ManageIQ#17564, which was added in order to support running ansible-playbook (_not ansible-runner_). This variable allows ansible core to return JSON, which was honored by ansible-playbook. ansible-runner takes care of wrapping the output properly for us, so we don't need it, and setting it causes us to lose the "normal" STDOUT we'd otherwise get from ansible-runner. ansible-runner 1.4.7 seemingly ignores this value (or perhaps overrides it for its own purposes), so we don't need to set it. For the future versions of ansible-runner, it causes the problems above, so this commit removes it altogether.
Add simple wrapping code for running ansible-playbook
TODOs:
stdout_callback = json
in .ansible.cfg, to get json output out of the runsImplements:
https://bugzilla.redhat.com/show_bug.cgi?id=1588189