From cae0bfdf9d097bb207070461a48447312aba8d36 Mon Sep 17 00:00:00 2001 From: Darragh Bailey Date: Thu, 31 Mar 2016 14:44:17 +0100 Subject: [PATCH] provisioners/ansible: Replace inventory file instead of modify When updating the inventory, write to a temp file and replace the original once writing is complete, to allow for an atomic replacement of the contents. Ensures that ansible reading an inventory file will get either the old or new contents, but never the truncated version of the file that appears should you open it with 'w' mode set to replace the contents. Solves the 'provided hosts list is empty' error, which is emitted by ansible should it manage to be reading the inventory file just as it was truncated, but before the new contents were flushed to disk. Partially-Fixes: #6526 --- plugins/provisioners/ansible/provisioner/host.rb | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index 245a00499..ac6bd1e16 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -132,8 +132,15 @@ module VagrantPlugins inventory_file = Pathname.new(File.join(inventory_path, 'vagrant_ansible_inventory')) @@lock.synchronize do if !File.exists?(inventory_file) or inventory_content != File.read(inventory_file) - inventory_file.open('w') do |file| - file.write(inventory_content) + begin + # ansible dir inventory will ignore files starting with '.' + inventory_tmpfile = Tempfile.new('.vagrant_ansible_inventory', inventory_path) + inventory_tmpfile.write(inventory_content) + inventory_tmpfile.close + File.rename(inventory_tmpfile.path, inventory_file) + ensure + inventory_tmpfile.close + inventory_tmpfile.unlink end end end