Skip to content

Commit f20b49a

Browse files
bdunneFryguy
authored andcommitted
Merge pull request #23576 from Fryguy/ansible_runner_async_bug
Fix issue where ansible-runner async did not respect the venv (cherry picked from commit c257ffb)
1 parent 4d3d4b8 commit f20b49a

File tree

3 files changed

+100
-15
lines changed

3 files changed

+100
-15
lines changed

lib/ansible/runner.rb

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,21 @@ def run_role_queue(env_vars, extra_vars, role_name, user_id, queue_opts, roles_p
163163
run_in_queue("run_role", user_id, queue_opts, [env_vars, extra_vars, role_name, kwargs])
164164
end
165165

166+
# Executes ansible-runner within the venv.
167+
#
168+
# Prefer the various run_* methods unless you need to run the ansible-runner command directly.
169+
#
170+
# @param env [Hash] Hash that will be passed as environment variables to ansible-runner
171+
# @param params [Hash,Array] Command line parameters to pass to ansible-runner
172+
# @return [AwesomeSpawn::CommandResult] Result of the ansible-runner command
173+
def raw_execute(env: {}, params:)
174+
env = env.merge(runner_env)
175+
176+
# puts "#{env.map { |k, v| "#{k}=#{v}" }.join(" ")} #{AwesomeSpawn.build_command_line("ansible-runner", params)}"
177+
178+
AwesomeSpawn.run("ansible-runner", :env => env, :params => params)
179+
end
180+
166181
private
167182

168183
# Run a method on self class, via queue, executed by generic worker
@@ -219,7 +234,7 @@ def run_via_cli(hosts, credentials, env_vars, extra_vars, tags: nil, ansible_run
219234
end
220235
command_line_hash.merge!(cred_command_line)
221236

222-
env_vars_hash = env_vars.merge(cred_env_vars).merge(runner_env)
237+
env_vars_hash = env_vars.merge(cred_env_vars)
223238
extra_vars_hash = extra_vars.merge(cred_extra_vars)
224239

225240
create_hosts_file(base_dir, hosts)
@@ -228,15 +243,13 @@ def run_via_cli(hosts, credentials, env_vars, extra_vars, tags: nil, ansible_run
228243

229244
params = runner_params(base_dir, ansible_runner_method, playbook_or_role_args, verbosity)
230245

231-
# puts "#{env_vars_hash.map { |k, v| "#{k}=#{v}" }.join(" ")} #{AwesomeSpawn.build_command_line("ansible-runner", params)}"
232-
233246
begin
234247
fetch_galaxy_roles(playbook_or_role_args)
235248

236249
result = if async?(ansible_runner_method)
237-
wait_for(base_dir, "pid") { AwesomeSpawn.run("ansible-runner", :env => env_vars_hash, :params => params) }
250+
wait_for(base_dir, "pid") { raw_execute(:env => env_vars_hash, :params => params) }
238251
else
239-
AwesomeSpawn.run("ansible-runner", :env => env_vars_hash, :params => params)
252+
raw_execute(:env => env_vars_hash, :params => params)
240253
end
241254

242255
res = response(base_dir, ansible_runner_method, result, debug)

lib/ansible/runner/response_async.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ def initialize(base_dir:, command_line: nil, ident: "result", debug: false)
2323

2424
# @return [Boolean] true if the ansible job is still running, false when it's finished
2525
def running?
26-
AwesomeSpawn.run("ansible-runner", :params => ["is-alive", base_dir, :json, {:ident => "result"}]).success?
26+
Ansible::Runner.raw_execute(:params => ["is-alive", base_dir, :json, {:ident => "result"}]).success?
2727
end
2828

2929
# Stops the running Ansible job
3030
def stop
31-
AwesomeSpawn.run("ansible-runner", :params => ["stop", base_dir, :json, {:ident => "result"}])
31+
Ansible::Runner.raw_execute(:params => ["stop", base_dir, :json, {:ident => "result"}])
3232
end
3333

3434
# @return [Ansible::Runner::Response, NilClass] Response object with all details about the Ansible run, or nil

spec/lib/ansible/runner_execution_spec.bats

Lines changed: 80 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -139,49 +139,49 @@ exec_ansible_runner_role() {
139139
rails runner "resp = Ansible::Runner.run_role({}, {}, '$1', roles_path: '$ROLES_DIR'); puts resp.human_stdout; exit resp.return_code"
140140
}
141141

142-
@test "[Ansible::Runner] runs a playbook" {
142+
@test "[Ansible::Runner#run] runs a playbook" {
143143
run exec_ansible_runner hello_world.yml
144144
assert_success
145145
assert_output --partial '"msg": "Hello World!"'
146146
}
147147

148-
@test "[Ansible::Runner] runs a playbook with variables in a vars file" {
148+
@test "[Ansible::Runner#run] runs a playbook with variables in a vars file" {
149149
run exec_ansible_runner hello_world_vars_file.yml
150150
assert_success
151151
assert_output --partial '"msg": "Hello World! vars_file_1=vars_file_1_value, vars_file_2=vars_file_2_value"'
152152
}
153153

154-
@test "[Ansible::Runner] runs a playbook with vault encrypted variables" {
154+
@test "[Ansible::Runner#run] runs a playbook with vault encrypted variables" {
155155
skip "requires database access"
156156

157157
run exec_ansible_runner hello_world_vault_encrypted_vars.yml
158158
assert_success
159159
assert_output --partial '"msg": "Hello World! (NOTE: This message has been encrypted with ansible-vault)"'
160160
}
161161

162-
@test "[Ansible::Runner] runs a playbook with variables in a vault encrypted vars file" {
162+
@test "[Ansible::Runner#run] runs a playbook with variables in a vault encrypted vars file" {
163163
skip "requires database access"
164164

165165
run exec_ansible_runner hello_world_vault_encrypted_vars_file.yml
166166
assert_success
167167
assert_output --partial '"msg": "Hello World! vars_file_1=vars_file_1_value, vars_file_2=vars_file_2_value"'
168168
}
169169

170-
@test "[Ansible::Runner] runs a playbook using roles from github" {
170+
@test "[Ansible::Runner#run] runs a playbook using roles from github" {
171171
run exec_ansible_runner hello_world_with_requirements_github/hello_world_with_requirements_github.yml
172172
assert_success
173173
assert_output --partial '"msg": "Hello World! example_var='\''example var value'\''"'
174174
}
175175

176-
@test "[Ansible::Runner] runs a role" {
176+
@test "[Ansible::Runner#run_role] runs a role" {
177177
setup_roles_dir $ROLES_DIR $DATA_DIR/hello_world_with_requirements_github/roles/requirements.yml
178178

179179
run exec_ansible_runner_role manageiq.example
180180
assert_success
181181
assert_output --partial '"msg": "Hello from manageiq.example role! example_var='\''example var value'\''"'
182182
}
183183

184-
@test "[Ansible::Runner] vmware collection" {
184+
@test "[Ansible::Runner#run] vmware collection" {
185185
if [ ! -d /var/lib/manageiq/venv ]; then
186186
skip "manageiq venv collections are not present"
187187
fi
@@ -191,7 +191,7 @@ exec_ansible_runner_role() {
191191
assert_output --partial '"msg": "Unknown error while connecting to vCenter or ESXi API at vcenter_hostname:443 : [Errno -2] Name or service not known"'
192192
}
193193

194-
@test "[Ansible::Runner] aws collection" {
194+
@test "[Ansible::Runner#run] aws collection" {
195195
if [ ! -d /var/lib/manageiq/venv ]; then
196196
skip "manageiq venv collections are not present"
197197
fi
@@ -200,3 +200,75 @@ exec_ansible_runner_role() {
200200
assert_failure # We expect to this to fail due to connecting with bad creds
201201
assert_output --partial '"msg": "Failed to describe instances: An error occurred (AuthFailure) when calling the DescribeInstances operation: AWS was not able to validate the provided access credentials"'
202202
}
203+
204+
################################################################################
205+
206+
exec_ansible_runner_async() {
207+
rails runner "resp = Ansible::Runner.run_async({}, {}, '$DATA_DIR/$1').wait(5); puts resp.human_stdout; exit resp.return_code"
208+
}
209+
210+
exec_ansible_runner_role_async() {
211+
rails runner "resp = Ansible::Runner.run_role_async({}, {}, '$1', roles_path: '$ROLES_DIR').wait(5); puts resp.human_stdout; exit resp.return_code"
212+
}
213+
214+
@test "[Ansible::Runner#run_async] runs a playbook" {
215+
run exec_ansible_runner_async hello_world.yml
216+
assert_success
217+
assert_output --partial '"msg": "Hello World!"'
218+
}
219+
220+
@test "[Ansible::Runner#run_async] runs a playbook with variables in a vars file" {
221+
run exec_ansible_runner_async hello_world_vars_file.yml
222+
assert_success
223+
assert_output --partial '"msg": "Hello World! vars_file_1=vars_file_1_value, vars_file_2=vars_file_2_value"'
224+
}
225+
226+
@test "[Ansible::Runner#run_async] runs a playbook with vault encrypted variables" {
227+
skip "requires database access"
228+
229+
run exec_ansible_runner_async hello_world_vault_encrypted_vars.yml
230+
assert_success
231+
assert_output --partial '"msg": "Hello World! (NOTE: This message has been encrypted with ansible-vault)"'
232+
}
233+
234+
@test "[Ansible::Runner#run_async] runs a playbook with variables in a vault encrypted vars file" {
235+
skip "requires database access"
236+
237+
run exec_ansible_runner_async hello_world_vault_encrypted_vars_file.yml
238+
assert_success
239+
assert_output --partial '"msg": "Hello World! vars_file_1=vars_file_1_value, vars_file_2=vars_file_2_value"'
240+
}
241+
242+
@test "[Ansible::Runner#run_async] runs a playbook using roles from github" {
243+
run exec_ansible_runner_async hello_world_with_requirements_github/hello_world_with_requirements_github.yml
244+
assert_success
245+
assert_output --partial '"msg": "Hello World! example_var='\''example var value'\''"'
246+
}
247+
248+
@test "[Ansible::Runner#run_role_async] runs a role" {
249+
setup_roles_dir $ROLES_DIR $DATA_DIR/hello_world_with_requirements_github/roles/requirements.yml
250+
251+
run exec_ansible_runner_role_async manageiq.example
252+
assert_success
253+
assert_output --partial '"msg": "Hello from manageiq.example role! example_var='\''example var value'\''"'
254+
}
255+
256+
@test "[Ansible::Runner#run_async] vmware collection" {
257+
if [ ! -d /var/lib/manageiq/venv ]; then
258+
skip "manageiq venv collections are not present"
259+
fi
260+
261+
run exec_ansible_runner_async vmware.yml
262+
assert_failure # We expect to this to fail due to connecting to an unknown vcenter
263+
assert_output --partial '"msg": "Unknown error while connecting to vCenter or ESXi API at vcenter_hostname:443 : [Errno -2] Name or service not known"'
264+
}
265+
266+
@test "[Ansible::Runner#run_async] aws collection" {
267+
if [ ! -d /var/lib/manageiq/venv ]; then
268+
skip "manageiq venv collections are not present"
269+
fi
270+
271+
run exec_ansible_runner_async aws.yml
272+
assert_failure # We expect to this to fail due to connecting with bad creds
273+
assert_output --partial '"msg": "Failed to describe instances: An error occurred (AuthFailure) when calling the DescribeInstances operation: AWS was not able to validate the provided access credentials"'
274+
}

0 commit comments

Comments
 (0)