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

ask_become_pass in ansible provisioner only works with true not false #10834

Open Gnitset opened 5 years ago

Gnitset commented 5 years ago

Vagrantfile

ENV["LC_ALL"] = "en_US.UTF-8"

number_of_nodes = 1

Vagrant.configure(2) do |config|
  config.vm.box = "centos/7"

  (1..number_of_nodes).each do |i|
    config.vm.define "centos#{i}", primary: true do |centos|
      centos.vm.hostname = "centos#{i}"
      centos.vm.provision :ansible do |ansible|
        ansible.playbook = "playbooks/vagrant.yml"
        ansible.extra_vars = { vagrant: true }
        ansible.compatibility_mode = "2.0"
        ansible.ask_become_pass = false
        ansible.verbose = true
      end
      centos.vm.network "private_network", ip: "192.168.20.#{i+20}"
      centos.vm.provider "virtualbox" do |v|
        v.memory = 4096
        v.cpus = 2
      end
    end
  end
end

ansible.cfg

[defaults]
inventory = inventories/all.inv
roles_path = roles
retry_files_enabled = False

[privilege_escalation]
become = True
become_ask_pass = True

Expected behavior

When setting ansible.ask_become_pass to false I expect it to tell ansible in a convincing way not not ask for password even if the default is to ask based on its config.

Actual behavior

It asks for SUDO password.

Steps to reproduce

  1. Configure ansible with become_ask_pass = True in ansible.cfg
  2. Set the option ansible.ask_become_pass to false in the Vagrantfile
  3. Do a provision

Suggested change

If the setting is being sent to ansible with environment ANSIBLE_BECOME_ASK_PASS= instead of the existence of the command line parameter -K it would work both ways.

texhnolyze commented 2 years ago

I came across this issue today myself with a pretty basic vagrant ansible setup and had a quick look.

I think this could easily be changed by moving the candling of ask_become_pass from a command argument into an environment variable as @Gnitset suggested. From this into something like this:

...
          @command_arguments << "--ask-vault-pass" if config.ask_vault_pass

          prepare_common_command_arguments
        end

        def prepare_environment_variables
          prepare_common_environment_variables

          # Some Ansible options must be passed as environment variables,
          # as there is no equivalent command line arguments
          @environment_variables["ANSIBLE_HOST_KEY_CHECKING"] = "#{config.host_key_checking}"

          @environment_variables["ANSIBLE_BECOME_ASK_PASS"] = "#{config.ask_become_pass}"

          # ANSIBLE_SSH_ARGS is required for Multiple SSH keys, SSH forwarding and custom SSH settings
          @environment_variables["ANSIBLE_SSH_ARGS"] = ansible_ssh_args unless ansible_ssh_args.empty?
        end
...

I'd be happy to create a pull request for this, however I'm unsure if it makes sense.

Some context

Both in ansible as well as in vagrant the default value for this setting is false. However in the specific issue mentioned here, where a custom ansible.cfg is supplied, the setting from that config would be implicitly overwritten by vagrant when changing to the ANSIBLE_BECOME_ASK_PASS method, which could lead to confusion in users.

What are others opinions on this? Is it instead possible to pass custom environment variables to the command a provisioner executes in some other way (for ansible playbooks that would be here?