hashicorp / vagrant

Vagrant is a tool for building and distributing development environments.
https://www.vagrantup.com
Other
26.27k stars 4.43k forks source link

Allow to override the "host" and "port" values in the generated inventory #7552

Open DerekTBrown opened 8 years ago

DerekTBrown commented 8 years ago

So, two concerns:

1) As of the latest version of Ansible, the ansible_ssh_host variable is now deprecated in favor of ansible_host, this needs to be updated.

2) ansible_host has broader reaching applications than just ssh (people are using ansible_host as a standin for the servers' DNS or IP Address). Therefore, it is not always best that Vagrant sets this to be 127.0.0.1, for instance, the case where the user has a private network configured.

Therefore, I think Vagrant needs an ansible_host variable, which defaults to 127.0.0.1, but can be easily overridden.

gildegoma commented 8 years ago

Thank you Derek for reporting these two points.

The first point is already tracked as part of #6570. I hope to find some free time to work on these changes as of August-September, but help via pull request would be great (even for the resolution of some parts of all the points listed in #6570 :)

For your second point, the IP Address and SSH port set by the ansible provisioner depends on the address returned by the machine provider. The IP address is typically 127.0.0.1 for the VirtualBox provider which uses port-forwarding to provide SSH access, but it is not the case with many other providers (obviously for Cloud providers, but also for local machines or containers provided by libvirt, VMware, Parallels, Docker, ...).

The alternative when using a private network and VirtualBox can be to rely on an Ansible static inventory file. This requires to maintain two copies of the IP addresses (one in Vagrantfile and one in the Ansible inventory), which is not ideal but acceptable in many situations.

I'd like to close this issue, but if you think we should further investigate about how to improve the point 2, please provide more details about your specific use case. Thanks again!

DerekTBrown commented 8 years ago

@gildegoma in regard to the static inventory, that was my thought initially as well, but this has an issue in that you cannot use Vagrant's dynamically created private key (which is stored in a different directory based on execution). That's why just a simple if statement which would allow the user to overwrite the ansible_ssh_host or ansible_host if set in the hostvars would be ideal.

gildegoma commented 8 years ago

you cannot use Vagrant's dynamically created private key

The pattern for the private key path is: .vagrant/machines/<machine-name>/<machine-provider>/private_key. I don't see why you cannot specify these paths in your static inventory. Note that depending of your context, you also can keep the default insecure key: config.ssh.insert_key = false.

a simple if statement which would allow the user to overwrite the ansible_ssh_host or ansible_host if set in the hostvars would be ideal

In order to better grasp your proposal, can you please give me an example of how a Vagrantfile would look like with this addition? Thank you 😃


PS: I edited the issue name to better reflect that we're here addressing the point 2.

DerekTBrown commented 8 years ago

@gildegoma I do have a way of doing this, but it is simply not elegant. I have a really simple usecase (I want Ansible to be using the private network for SSH, not the 127.0.0.1 address). However, it has a lot of considerations:

1) Have to use a static inventory 2) Have to hardcode SSH key addresses (either insecure or otherwise) 3) Have to disable force_remote_user (as it needs to be manually set in each step) 4) Have to disable host_key_checking

I think there are other, similar usecases, where the user would like Vagrant to use, say, a different user for configuration than Ansible. My proposal would not actually change the syntax or API that is being used at all, it would just change the behavior. Consider the following simple example:

vagrant.vm.define "ubuntu" do |ubuntu|
   ubuntu.vm.box = "ubuntu/trusty64"

   ubuntu.vm.network "private_network", ip: "10.100.0.10"

   ubuntu.vm.provision :ansible do |ansible|
     ansible.playbook = "./setup.yml"
     ansible.limit = 'all'
     ansible.host_vars = {
       "ubuntu" => {
          "ansible_host" => "10.100.1.10"
        }
     }
    end
end

Right now, if I were to execute this Vagrantfile, you would see that the ansible_host variable is injected twice- once automatically by vagrant, and once via the host_vars. My request would simply be that if ansible_host or ansible_ssh_host is set in hostvars, that this property overwrite the one automatically generated by Vagrant. I think a similar approach would make sense for other variables like ansible_user as well.

tonycapone commented 8 years ago

@DerekTBrown actually, your example worked for me, with a slight addition:

ansible.host_vars = {
       "ubuntu" => {
          "ansible_host" => "10.100.1.10",
          "ansible_port" => 22
        }
     } 

This works despite the fact that the inventory also contains the Ansible 1.x style variables ansible_ssh_host and ansible_ssh_port I suspect this is because the new Ansible 2 form of host variables takes precedence over the Ansible 1.x style. It's slightly hacky but it will work until the feature is added to the Ansible provisioner.

v1k0d3n commented 8 years ago

@DerekTBrown i think your solution could work, but how would i do this for mult-machine deployments, similar to: https://gist.github.com/v1k0d3n/d2500d9bccdaec275fa3f505fa13359c

i think i'm running into this issue as well (if I'm reading it correct). i would like to ansible to use a declared private_network ip for the inventory, rather than a 10.x.x.x nat/port. again, hopefully i'm reading this correctly (if not, I can open another issue).

DerekTBrown commented 8 years ago

@v1k0d3n this thread is more of a feature request at this point. The method of currently accomplishing this is to create an Ansible static inventory file, and then in your Vagrantfile, only provision the last VM using Ansible, but set hosts to all (See https://www.vagrantup.com/docs/provisioning/ansible.html#ansible-parallel-execution).

I am also running into a new issue, which is that the VirtualBox provider assigns a temporary IP address for Vagrant be default, (its a 192.168 address) and only later activates the IP address I assigned the VM. However, this address doesn't show up as the machine ipv4 in ansible variables, instead it is the "secondary IP". This would also be resolved by the addition I proposed above, as the ansible_host seems to be set properly.

gildegoma commented 7 years ago

Hello Guys! A few updates that might interest you:

gildegoma commented 7 years ago

ERRATUM: Sorry for my previous comment, #8131 addresses an issue with a static inventory, while the topic here is about a possible enhancement of the dynamic inventory capabilities.

DerekTBrown commented 7 years ago

Not sure how #6570 will fix this. The issue I have is with the value, and not the key. SSH on my VMs are not bound to 127.0.0.1, which is what Vagrant supplies to Ansible.

gildegoma commented 7 years ago

@DerekTBrown my comment about #6570 was only about your first concern in the original issue description

the ansible_ssh_host variable is now deprecated in favor of ansible_host, this needs to be updated

which is addressed by #6570.

Indeed, this current issue #7553 now only focuses on your second concern (and issue title):

Allow to override/shadow the ansible_ssh_host (ansible_host) in generated inventory

Making the provisioner able to detect ansible(_ssh)_host and ansible(_ssh)_port overrides everywhere sounds more than tricky. On the long run, I feel that it hardly could succeed to cover all the possible cases.

So, to instruct Vagrant Ansible provisioner when host and port settings should not be added to the inventory, I am more keen on adding a dedicated option (less error prone).

For instance (wild thoughts, to be quietly reviewed...):

ansible.skip_inventory_host_and_port_settings = true
ansible.host_vars = {
       "ubuntu" => {
          "ansible_host" => "10.100.1.10",
          "ansible_port" => 22
        }
     } 

With this new skip_inventory_host_and_port_settings option (better naming welcome, etc.), Vagrant could actually offers two new interesting behaviours:

  1. 7552 (with a generated inventory): The host and port settings are not written to the generated inventory, assuming these settings are managed elsewhere (via host_vars, extra-vars, dns, ...).

  2. 8131 (with a static inventory): The Vagrant's provider host and port settings are passed as extra variables in order to override the values present in the static inventory.

I am not certain right now about the way to name things and coordinate these two requests (#7552 and #8131). But so far, I am convinced it will makes sense to resolve them togheter, in a unified way. Your thoughts are welcome, as always!


ATTENTION: #6570 is a prerequisite to start working on this issue (so we support Ansible 1.x and 2.x formats from Day 1.)