1.9.5
OS X 10.12.4
Debian 8
Vagrant should quote Ansible host variables when generating an inventory file.
It doesn't, and then pukes.
When generating the Ansible host file, I'm using "host_vars" like so...
cfg.vm.provision :ansible do |a|
a.host_vars = ansible_host_vars
end
Problem is, it's not quoting strings that should be quoted...generating something like this:
cb-beta-app-1 ansible_ssh_host=173.255.247.7 ansible_ssh_port=22 hostname=cb-beta-app-1 vpn_hostname=vpn_app_1 vpn_ip=10.0.0.20 datacenter=fremont linode_plan=Linode 2048
The last variable there "linode_plan" should be quoted. The space inside throws off vagrant provision and causes the following errors with Ansible:
ERROR! Attempted to read "/Users/seth/Work/cashboard/app/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory" as YAML: 'AnsibleUnicode' object has no attribute 'keys'
Attempted to read "/Users/seth/Work/cashboard/app/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory" as ini file: /Users/seth/Work/cashboard/app/.vagrant/provisioners/ansible/inventory/vagrant_ansible_inventory:2: Expected key=value host variable assignment, got: 2048
Ansible failed to complete successfully. Any error output should be
visible above. Please fix these errors and try again.
FWIW, it looks like provisioners/ansible/provisioner/base.rb line 151. If you change...
s = vars.each.collect{ |k, v| "#{k}=#{v}" }.join(" ")
...to...
s = vars.each.collect{ |k, v| "#{k}=\"#{v}\"" }.join(" ")
I think it should be good.
@subimage This is actually a known issue (see #8158).
In this case, you need to explicitly apply quotes where necessary, for instance:
ansible.host_vars = {
"cb-beta-app-1" => {
"hostname" => "cb-beta-app-1",
...
"linode_plan" => "'Linode 2048'",
}
}
(See also https://www.vagrantup.com/docs/provisioning/ansible_common.html#host_vars)
I know it's confusing and not very "friendly", but I'm afraid if always putting these quotes could potentially break things in existing Vagrant configurations. I'm also unsure about try to add a "smarter" behaviour (automatically quote _only when necessary_, i.e. if this is an unquoted text that contains blank characters).
For all these reasons, I considered this issue as "low priority" and preferred to stick to this "basic" behaviour (KISS). But I'm open to accept the addition of the "smarter" behaviour described above, but not to always set the double quotes as proposed in #8158.
I'm closing, but feedbacks (or pull request) are welcome. Thanks!
A farily safe smarter behavior would be pretty trivial to code...example:
s = vars.each.collect do |k, v|
if v.include?(' ') && !v.match(/^('|").*('|")$/)
v = %Q|"#{v}"|
end
"#{k}=#{v}"
end
s.join(" ")
I understand your concern, but I believe it to be a bit overblown. Right now this is breaking configurations and causing confusion.
If you have to resort to a documentation explanation to "fix" this, I don't believe it's a solid approach. "Gotchas" are never beneficial in product design.
@subimage I agree, and your patch looks good.
Adding test coverage, and it will be all set to be merged. I reopen the issue to keep it on the radar. Pull request welcome, if someone is interested to accelerate the things...
I'm going to lock this issue because it has been closed for _30 days_ โณ. This helps our maintainers find and focus on the active issues.
If you have found a problem that seems similar to this, please open a new issue and complete the issue template so we can capture all the details necessary to investigate further.