Skip to content

Commit 18dc215

Browse files
Merge pull request #13740 from taru-garg-hashicorp/fix-test-ansible
Support selection of inventory argument for the ansible-playbook command, based on ansible-core version, as `--inventory` is not the strategic supported argument instead of `--inventory-file` as such this PR updates the behaviour of Vagrant to start using the new argument for when the `ansible-core` version is `>=2.19` i.e. when the deprecation was introduced
2 parents f2960d5 + 91e63ec commit 18dc215

File tree

5 files changed

+111
-7
lines changed

5 files changed

+111
-7
lines changed

plugins/provisioners/ansible/provisioner/base.rb

Lines changed: 46 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,16 +53,24 @@ def initialize(machine, config)
5353
@gathered_version_stdout = nil
5454
@gathered_version_major = nil
5555
@gathered_version = nil
56+
57+
@ansible_package_version_map = {}
5658
end
5759

5860
def set_and_check_compatibility_mode
5961
begin
60-
set_gathered_ansible_version(gather_ansible_version)
62+
set_gathered_ansible_version(gather_ansible_version("ansible"))
6163
rescue StandardError => e
6264
# Nothing to do here, as the fallback on safe compatibility_mode is done below
6365
@logger.error("Error while gathering the ansible version: #{e.to_s}")
6466
end
6567

68+
begin
69+
set_gathered_ansible_package_version("ansible-core", gather_ansible_version("ansible-core"))
70+
rescue StandardError => e
71+
@logger.error("Error while gathering the ansible-core version: #{e}")
72+
end
73+
6674
if @gathered_version_major
6775
if config.compatibility_mode == Ansible::COMPATIBILITY_MODE_AUTO
6876
detect_compatibility_mode
@@ -164,7 +172,7 @@ def prepare_common_command_arguments
164172
@command_arguments << "--limit=#{@machine.name}"
165173
end
166174

167-
@command_arguments << "--inventory-file=#{inventory_path}"
175+
@command_arguments << get_inventory_argument(inventory_path)
168176
@command_arguments << "--extra-vars=#{extra_vars_argument}" if config.extra_vars
169177
@command_arguments << "--#{@lexicon[:become]}" if config.become
170178
@command_arguments << "--#{@lexicon[:become_user]}=#{config.become_user}" if config.become_user
@@ -175,6 +183,22 @@ def prepare_common_command_arguments
175183
@command_arguments << "--start-at-task=#{config.start_at_task}" if config.start_at_task
176184
end
177185

186+
def get_inventory_argument(inventory_path)
187+
ansible_core_version = @ansible_package_version_map["ansible-core"]
188+
# Default to --inventory-file if version info is not available
189+
return "--inventory-file=#{inventory_path}" if ansible_core_version.nil? || ansible_core_version.empty?
190+
191+
major = ansible_core_version[:major].to_i
192+
minor = ansible_core_version[:minor].to_i
193+
194+
# Use --inventory for ansible-core >= 2.19
195+
if major > 2 || (major == 2 && minor >= 19)
196+
"--inventory=#{inventory_path}"
197+
else
198+
"--inventory-file=#{inventory_path}"
199+
end
200+
end
201+
178202
def prepare_common_environment_variables
179203
# Ensure Ansible output isn't buffered so that we receive output
180204
# on a task-by-task basis.
@@ -399,6 +423,26 @@ def set_gathered_ansible_version(stdout_output)
399423
end
400424
end
401425

426+
def set_gathered_ansible_package_version(ansible_package, stdout_output)
427+
if !stdout_output.empty?
428+
first_line = stdout_output.lines[0]
429+
ansible_version_pattern = first_line.match(/^#{ansible_package}\s+(.+)$/)
430+
if ansible_version_pattern
431+
gathered_version = ansible_version_pattern.captures.first
432+
gathered_version.strip!
433+
if !gathered_version.empty?
434+
gathered_version_major = gathered_version.match(/(\d+)\..+$/).captures[0].to_i
435+
gathered_version_minor = gathered_version.match(/\d+\.(\d+)\..+$/).captures[0].to_i
436+
@ansible_package_version_map[ansible_package] = {
437+
version: gathered_version,
438+
major: gathered_version_major,
439+
minor: gathered_version_minor
440+
}
441+
end
442+
end
443+
end
444+
end
445+
402446
end
403447
end
404448
end

plugins/provisioners/ansible/provisioner/guest.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ def check_and_install_ansible
7474
end
7575
end
7676

77-
def gather_ansible_version
77+
def gather_ansible_version(package = 'ansible')
7878
raw_output = ""
7979

8080
result = @machine.communicate.execute(
81-
"python3 -c \"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))\"",
81+
"python3 -c \"import importlib.metadata; print('#{package} ' + importlib.metadata.version('#{package}'))\"",
8282
error_class: Ansible::Errors::AnsibleNotFoundOnGuest,
8383
error_key: :ansible_not_found_on_guest) do |type, output|
8484
if type == :stdout && output.lines[0]

plugins/provisioners/ansible/provisioner/host.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,10 +110,10 @@ def execute_command_from_host(command)
110110
end
111111
end
112112

113-
def gather_ansible_version
113+
def gather_ansible_version(package = 'ansible')
114114
raw_output = ''
115115
command = ['python3', '-c',
116-
"import importlib.metadata; print('ansible ' + importlib.metadata.version('ansible'))"]
116+
"import importlib.metadata; print('#{package} ' + importlib.metadata.version('#{package}'))"]
117117

118118
command << {
119119
notify: [:stdout, :stderr]

test/unit/plugins/provisioners/ansible/provisioner_test.rb

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,17 @@ def self.it_should_check_ansible_version
8585
end
8686
end
8787

88+
def self.it_should_check_ansible_core_version
89+
it "executes 'Python ansible-core version check before executing 'ansible-playbook'" do
90+
expect(Vagrant::Util::Subprocess).to receive(:execute)
91+
.once.with('python3', '-c', "import importlib.metadata; print('ansible-core ' + importlib.metadata.version('ansible-core'))", { notify: %i[
92+
stdout stderr
93+
] })
94+
expect(Vagrant::Util::Subprocess).to receive(:execute)
95+
.once.with('ansible-playbook', any_args)
96+
end
97+
end
98+
8899
def self.it_should_set_arguments_and_environment_variables(
89100
expected_args_count = 5,
90101
expected_vars_count = 4,
@@ -286,6 +297,7 @@ def ensure_that_config_is_valid
286297

287298
describe "with default options" do
288299
it_should_check_ansible_version
300+
it_should_check_ansible_core_version
289301
it_should_set_arguments_and_environment_variables
290302
it_should_create_and_use_generated_inventory
291303

@@ -383,6 +395,7 @@ def ensure_that_config_is_valid
383395
end
384396

385397
it_should_check_ansible_version
398+
it_should_check_ansible_core_version
386399
it_should_create_and_use_generated_inventory
387400

388401
it "doesn't warn about compatibility mode auto-detection" do
@@ -1262,5 +1275,52 @@ def ensure_that_config_is_valid
12621275
}.and_return(default_execute_result)
12631276
end
12641277
end
1278+
1279+
describe '#get_inventory_argument' do
1280+
context 'when ansible version is not detected' do
1281+
before do
1282+
config.version = nil
1283+
allow(subject).to receive(:gather_ansible_version).and_return("ansible #{config.version}\n...\n")
1284+
allow(subject).to receive(:gather_ansible_version).with("ansible-core").and_return("ansible #{config.version}\n...\n")
1285+
end
1286+
1287+
it 'returns the default inventory command' do
1288+
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
1289+
expect(args).to include("--inventory-file=#{generated_inventory_dir}")
1290+
}.and_return(default_execute_result)
1291+
end
1292+
end
1293+
1294+
context 'when ansible version is detected' do
1295+
describe 'version >= 2.19' do
1296+
before do
1297+
config.version = "2.19.0"
1298+
allow(subject).to receive(:gather_ansible_version).with("ansible").and_return("ansible #{config.version}\n...\n")
1299+
allow(subject).to receive(:gather_ansible_version).with("ansible-core").and_return("ansible-core #{config.version}\n...\n")
1300+
end
1301+
1302+
it 'returns --inventory as the inventory command' do
1303+
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
1304+
expect(args).to include("--inventory=#{generated_inventory_dir}")
1305+
}.and_return(default_execute_result)
1306+
end
1307+
end
1308+
1309+
describe 'version < 2.19' do
1310+
before do
1311+
config.version = "2.18.5"
1312+
allow(subject).to receive(:gather_ansible_version).with("ansible").and_return("ansible #{config.version}\n...\n")
1313+
allow(subject).to receive(:gather_ansible_version).with("ansible-core").and_return("ansible-core #{config.version}\n...\n")
1314+
end
1315+
1316+
it 'returns --inventory-file as the inventory command' do
1317+
expect(Vagrant::Util::Subprocess).to receive(:execute).with('ansible-playbook', any_args) { |*args|
1318+
expect(args).to include("--inventory-file=#{generated_inventory_dir}")
1319+
}.and_return(default_execute_result)
1320+
end
1321+
end
1322+
end
1323+
end
1324+
12651325
end
12661326
end

test/unit/vagrant/action/builtin/box_add_test.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ def with_web_server(path, **opts)
410410
}.and_return(box)
411411

412412
allow(env[:ui]).to receive(:detail).and_call_original
413-
expect(env[:ui]).to receive(:detail).with(%r{.*http://(?!#{username}).+?:(?!#{password}).+?@127\.0\.0\.1:#{port}/#{box_path.basename}.*}).
413+
expect(env[:ui]).to receive(:detail).with(/.*http:\/\/\*+(?::\*+)?@127\.0\.0\.1:#{port}\/#{box_path.basename}.*/).
414414
and_call_original
415415
expect(app).to receive(:call).with(env)
416416

0 commit comments

Comments
 (0)