From a5ff2415869c6c6c7cbfff9529921dc3b8e41b60 Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 15:16:51 +0100 Subject: [PATCH 01/14] Updated documentation to reflect the possibility of adding group vars. --- .../v2/provisioning/ansible_common.html.md | 9 +++++++++ .../v2/provisioning/ansible_intro.html.md | 17 +++++++++++------ 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/website/docs/source/v2/provisioning/ansible_common.html.md b/website/docs/source/v2/provisioning/ansible_common.html.md index cb8daf55e..053938d5c 100644 --- a/website/docs/source/v2/provisioning/ansible_common.html.md +++ b/website/docs/source/v2/provisioning/ansible_common.html.md @@ -41,6 +41,15 @@ Some of these options are for advanced usage only and should not be used unless "db" => ["vm3"] } ``` + Example with [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables): + + ```ruby + ansible.groups = { + "atlanta" => ["host1", "host2"], + "atlanta:vars" => {"ntp_server" => "ntp.atlanta.example.com", + "proxy" => "proxy.atlanta.example.com"} + } + ``` Notes: diff --git a/website/docs/source/v2/provisioning/ansible_intro.html.md b/website/docs/source/v2/provisioning/ansible_intro.html.md index b49568f07..6bbb377b9 100644 --- a/website/docs/source/v2/provisioning/ansible_intro.html.md +++ b/website/docs/source/v2/provisioning/ansible_intro.html.md @@ -109,7 +109,7 @@ Note that the generated inventory file is uploaded to the guest VM in a subdirec **How to generate Inventory Groups:** -The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. +The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. It is also possible to specify [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables). With this configuration example: @@ -126,7 +126,9 @@ Vagrant.configure(2) do |config| ansible.groups = { "group1" => ["machine1"], "group2" => ["machine2"], - "all_groups:children" => ["group1", "group2"] + "all_groups:children" => ["group1", "group2"], + "group1:vars" => {"variable1" => 9, + "variable2" => "example"} } end end @@ -149,22 +151,25 @@ machine2 [all_groups:children] group1 group2 + +[group1:vars] +variable1=9 +variable2=example ``` **Notes:** - Prior to Vagrant 1.7.3, the `ansible_ssh_private_key_file` variable was not set in generated inventory, but passed as command line argument to `ansible-playbook` command. - - The generation of group variables blocks (e.g. `[group1:vars]`) are intentionally not supported, as it is [not recommended to store group variables in the main inventory file](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). A good practice is to store these group (or host) variables in `YAML` files stored in `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory. + - The generation of group variables blocks (e.g. `[group1:vars]`) is only possible since Vagrant ???. Note however that setting variables directly in the inventory is not the [preferred practice in Ansible](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). If possible, group (or host) variables should be set in `YAML` files stored in the `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory instead. - Unmanaged machines and undefined groups are not added to the inventory, to avoid useless Ansible errors (e.g. *unreachable host* or *undefined child group*) -For example, `machine3`, `group3` and `group1:vars` in the example below would not be added to the generated inventory file: +For example, `machine3` and `group3` in the example below would not be added to the generated inventory file: ``` ansible.groups = { "group1" => ["machine1"], "group2" => ["machine2", "machine3"], - "all_groups:children" => ["group1", "group2", "group3"], - "group1:vars" => { "variable1" => 9, "variable2" => "example" } + "all_groups:children" => ["group1", "group2", "group3"] } ``` From 3fbbfeb8628ee16fa660ec4a9db44867eeef62bb Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 14:25:41 +0100 Subject: [PATCH 02/14] Expect group variables to be inserted in the test. --- .../provisioners/ansible/provisioner_test.rb | 28 ++++++++++++++++--- 1 file changed, 24 insertions(+), 4 deletions(-) diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 55b40cd18..a382dfc71 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -245,15 +245,11 @@ VF "group3" => ["unknown", "#{machine.name}"], "bar" => ["#{machine.name}", "group3"], "bar:children" => ["group1", "group2", "group3", "group4"], - "bar:vars" => ["myvar=foo"], } expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| inventory_content = File.read(generated_inventory_file) - # Group variables are intentionally not supported in generated inventory - expect(inventory_content).not_to match(/^\[.*:vars\]$/) - # Accept String instead of Array for group that contains a single item expect(inventory_content).to include("[group1]\n#{machine.name}\n") expect(inventory_content).to include("[group1:children]\nbar\n") @@ -272,6 +268,30 @@ VF expect(inventory_content).to include("[bar:children]\ngroup1\ngroup2\ngroup3\n") } end + + it "adds group vars to the generated inventory" do + config.groups = { + "group1" => [machine.name], + "group2" => [machine.name], + "group3" => [machine.name], + "group1:vars" => {"hashvar1" => "hashvalue1", "hashvar2" => "hashvalue2"}, + "group2:vars" => ["arrayvar1=arrayvalue1", "arrayvar2=arrayvalue2"], + "group3:vars" => "stringvar1=stringvalue1 stringvar2=stringvalue2", + } + + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + inventory_content = File.read(generated_inventory_file) + + # Hash syntax + expect(inventory_content).to include("[group1:vars]\nhashvar1=hashvalue1\nhashvar2=hashvalue2\n") + + # Array syntax + expect(inventory_content).to include("[group2:vars]\narrayvar1=arrayvalue1\narrayvar2=arrayvalue2\n") + + # Single string syntax + expect(inventory_content).to include("[group3:vars]\nstringvar1=stringvalue1\nstringvar2=stringvalue2\n") + } + end end describe "with host_key_checking option enabled" do From dd4ae1a51cfb246d561bced89d3b34ee90a0a38f Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 14:28:24 +0100 Subject: [PATCH 03/14] Parse and insert group variables into the generated inventory. --- .../provisioners/ansible/provisioner/base.rb | 22 ++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index 7a455b2bf..bf577ab6e 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -88,21 +88,27 @@ module VagrantPlugins # Write out groups information. # All defined groups will be included, but only supported # machines and defined child groups will be included. - # Group variables are intentionally skipped. def generate_inventory_groups groups_of_groups = {} defined_groups = [] + group_vars = {} inventory_groups = "" config.groups.each_pair do |gname, gmembers| - # Require that gmembers be an array - # (easier to be tolerant and avoid error management of few value) - gmembers = [gmembers] if !gmembers.is_a?(Array) + if gmembers.is_a?(String) + gmembers = gmembers.split(/\s+/) + elsif gmembers.is_a?(Hash) + gmembers = gmembers.each.collect{ |k, v| "#{k}=#{v}" } + elsif !gmembers.is_a?(Array) + gmembers = [] + end if gname.end_with?(":children") groups_of_groups[gname] = gmembers defined_groups << gname.sub(/:children$/, '') - elsif !gname.include?(':vars') + elsif gname.end_with?(":vars") + group_vars[gname] = gmembers + else defined_groups << gname inventory_groups += "\n[#{gname}]\n" gmembers.each do |gm| @@ -119,6 +125,12 @@ module VagrantPlugins end end + group_vars.each_pair do |gname, gmembers| + if defined_groups.include?(gname.sub(/:vars$/, "")) + inventory_groups += "\n[#{gname}]\n" + gmembers.join("\n") + "\n" + end + end + return inventory_groups end From 78766ded4e60ccada7d2e6f65923d7e00f3b9063 Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 16:43:03 +0100 Subject: [PATCH 04/14] Document host_vars option. --- .../v2/provisioning/ansible_common.html.md | 17 +++++++++++ .../v2/provisioning/ansible_intro.html.md | 29 +++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/website/docs/source/v2/provisioning/ansible_common.html.md b/website/docs/source/v2/provisioning/ansible_common.html.md index 053938d5c..44b787e7e 100644 --- a/website/docs/source/v2/provisioning/ansible_common.html.md +++ b/website/docs/source/v2/provisioning/ansible_common.html.md @@ -31,6 +31,23 @@ Some of these options are for advanced usage only and should not be used unless ``` These variables take the highest precedence over any other variables. +- `host_vars` (hash) - Set of inventory host variables to be included in the [auto-generated inventory file](http://docs.ansible.com/ansible/intro_inventory.html#host-variables). + + Example: + + ```ruby + ansible.host_vars = { + "host1" => {"http_port" => 80, + "maxRequestsPerChild" => 808}, + "host2" => {"http_port" => 303, + "maxRequestsPerChild" => 909} + } + ``` + + Notes: + + - This option has no effect when the `inventory_path` option is defined. + - `groups` (hash) - Set of inventory groups to be included in the [auto-generated inventory file](/v2/provisioning/ansible_intro.html). Example: diff --git a/website/docs/source/v2/provisioning/ansible_intro.html.md b/website/docs/source/v2/provisioning/ansible_intro.html.md index 6bbb377b9..441e8cbc8 100644 --- a/website/docs/source/v2/provisioning/ansible_intro.html.md +++ b/website/docs/source/v2/provisioning/ansible_intro.html.md @@ -107,6 +107,35 @@ default ansible_connection=local Note that the generated inventory file is uploaded to the guest VM in a subdirectory of [`tmp_path`](/v2/provisioning/ansible_local.html), e.g. `/tmp/vagrant-ansible/inventory/vagrant_ansible_local_inventory`. +**Host variables:** + +Since Vagrant ???, the [`host_vars`](/v2/provisioning/ansible_common.html) option can be used to set [variables for individual hosts](http://docs.ansible.com/ansible/intro_inventory.html#host-variables) in the generated inventory file (see also the notes on group variables below). + +``` +Vagrant.configure(2) do |config| + config.vm.define "host1" + config.vm.define "host2" + config.vm.provision "ansible" do |ansible| + ansible.playbook = "playbook.yml" + ansible.host_vars = { + "host1" => {"http_port" => 80, + "maxRequestsPerChild" => 808}, + "host2" => {"http_port" => 303, + "maxRequestsPerChild" => 909} + } + end +end +``` + +Generated inventory: + +``` +# Generated by Vagrant + +host1 ansible_ssh_host=... http_port=80 maxRequestsPerChild=808 +host2 ansible_ssh_host=... http_port=303 maxRequestsPerChild=909 +``` + **How to generate Inventory Groups:** The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. It is also possible to specify [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables). From a5dd61c45081ca8097a807083a679c0266026816 Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 17:04:56 +0100 Subject: [PATCH 05/14] Added test to expect host vars being inserted into inventory. --- .../plugins/provisioners/ansible/config_test.rb | 2 ++ .../provisioners/ansible/provisioner_test.rb | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/test/unit/plugins/provisioners/ansible/config_test.rb b/test/unit/plugins/provisioners/ansible/config_test.rb index 78e352914..f836382a3 100644 --- a/test/unit/plugins/provisioners/ansible/config_test.rb +++ b/test/unit/plugins/provisioners/ansible/config_test.rb @@ -30,6 +30,7 @@ describe VagrantPlugins::Ansible::Config::Host do galaxy_roles_path groups host_key_checking + host_vars inventory_path limit playbook @@ -62,6 +63,7 @@ describe VagrantPlugins::Ansible::Config::Host do expect(subject.tags).to be_nil expect(subject.skip_tags).to be_nil expect(subject.start_at_task).to be_nil + expect(subject.host_vars).to eq({}) expect(subject.groups).to eq({}) expect(subject.host_key_checking).to be_false expect(subject.raw_arguments).to be_nil diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index a382dfc71..cd76d68f8 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -234,6 +234,20 @@ VF end end + describe "with host_vars option" do + it_should_create_and_use_generated_inventory + + it "adds host variables to the generated inventory" do + config.host_vars = { + machine.name => {"http_port" => 80, "maxRequestsPerChild" => 808} + } + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + inventory_content = File.read(generated_inventory_file) + expect(inventory_content).to match("^" + Regexp.quote(machine.name) + ".+http_port=80 maxRequestsPerChild=808") + } + end + end + describe "with groups option" do it_should_create_and_use_generated_inventory From 77b11a989ca1aaa02e60068c1754c052bc4e8031 Mon Sep 17 00:00:00 2001 From: Christian Henz Date: Tue, 1 Dec 2015 18:15:40 +0100 Subject: [PATCH 06/14] Implemented host_vars option. --- plugins/provisioners/ansible/config/base.rb | 3 +++ plugins/provisioners/ansible/provisioner/base.rb | 13 +++++++++++++ plugins/provisioners/ansible/provisioner/guest.rb | 2 ++ plugins/provisioners/ansible/provisioner/host.rb | 3 +++ 4 files changed, 21 insertions(+) diff --git a/plugins/provisioners/ansible/config/base.rb b/plugins/provisioners/ansible/config/base.rb index 2cefe4a89..14ae1a3e6 100644 --- a/plugins/provisioners/ansible/config/base.rb +++ b/plugins/provisioners/ansible/config/base.rb @@ -9,6 +9,7 @@ module VagrantPlugins attr_accessor :galaxy_role_file attr_accessor :galaxy_roles_path attr_accessor :galaxy_command + attr_accessor :host_vars attr_accessor :groups attr_accessor :inventory_path attr_accessor :limit @@ -27,6 +28,7 @@ module VagrantPlugins @galaxy_role_file = UNSET_VALUE @galaxy_roles_path = UNSET_VALUE @galaxy_command = UNSET_VALUE + @host_vars = UNSET_VALUE @groups = UNSET_VALUE @inventory_path = UNSET_VALUE @limit = UNSET_VALUE @@ -46,6 +48,7 @@ module VagrantPlugins @galaxy_role_file = nil if @galaxy_role_file == UNSET_VALUE @galaxy_roles_path = nil if @galaxy_roles_path == UNSET_VALUE @galaxy_command = GALAXY_COMMAND_DEFAULT if @galaxy_command == UNSET_VALUE + @host_vars = {} if @host_vars == UNSET_VALUE @groups = {} if @groups == UNSET_VALUE @inventory_path = nil if @inventory_path == UNSET_VALUE @limit = nil if @limit == UNSET_VALUE diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index bf577ab6e..51377a61f 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -70,6 +70,19 @@ module VagrantPlugins end end + def get_inventory_host_vars_string(machine_name) + vars = config.host_vars[machine_name] + s = nil + if vars.is_a?(Hash) + s = vars.each.collect{ |k, v| "#{k}=#{v}" }.join(" ") + elsif vars.is_a?(Array) + s = vars.join(" ") + elsif vars.is_a?(String) + s = vars + end + if s and !s.empty? then s else nil end + end + def generate_inventory inventory = "# Generated by Vagrant\n\n" diff --git a/plugins/provisioners/ansible/provisioner/guest.rb b/plugins/provisioners/ansible/provisioner/guest.rb index a82bf7562..6f0b43f95 100644 --- a/plugins/provisioners/ansible/provisioner/guest.rb +++ b/plugins/provisioners/ansible/provisioner/guest.rb @@ -128,6 +128,8 @@ module VagrantPlugins else machines += "#{machine_name}\n" end + host_vars = get_inventory_host_vars_string(machine_name) + machines.sub!(/\n$/, " #{host_vars}\n") if host_vars end end diff --git a/plugins/provisioners/ansible/provisioner/host.rb b/plugins/provisioners/ansible/provisioner/host.rb index 54928bdfc..dcce98fb8 100644 --- a/plugins/provisioners/ansible/provisioner/host.rb +++ b/plugins/provisioners/ansible/provisioner/host.rb @@ -151,12 +151,15 @@ module VagrantPlugins # Call only once the SSH and WinRM info computation # Note that machines configured with WinRM communicator, also have a "partial" ssh_info. m_ssh_info = m.ssh_info + host_vars = get_inventory_host_vars_string(m.name) if m.config.vm.communicator == :winrm m_winrm_net_info = CommunicatorWinRM::Helper.winrm_info(m) # can raise a WinRMNotReady exception... machines += get_inventory_winrm_machine(m, m_winrm_net_info) + machines.sub!(/\n$/, " #{host_vars}\n") if host_vars @inventory_machines[m.name] = m elsif !m_ssh_info.nil? machines += get_inventory_ssh_machine(m, m_ssh_info) + machines.sub!(/\n$/, " #{host_vars}\n") if host_vars @inventory_machines[m.name] = m else @logger.error("Auto-generated inventory: Impossible to get SSH information for machine '#{m.name} (#{m.provider_name})'. This machine should be recreated.") From c49a146467f7d7a0e441564a2418a1b8a42bb8a6 Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Wed, 2 Dec 2015 08:37:41 +0100 Subject: [PATCH 07/14] provisioners/ansible(both): alias String-to-Symbol String and Symbol types are different when used as a Hash key. By default the Vagrant machine names are set in Symbol format, but users may write their `host_vars` entries with String keys. This is a very simple way to ensure smooth experience, without having to coerce the data types during the config validation (e.g. with a library like Hashie, which is currently not in the Vagrant dependencies) See also: - https://bugs.ruby-lang.org/issues/5964#note-17 - https://github.com/intridea/hashie#keyconversion --- plugins/provisioners/ansible/provisioner/base.rb | 7 ++++++- .../plugins/provisioners/ansible/provisioner_test.rb | 10 ++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index 51377a61f..981cbf5d1 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -71,7 +71,12 @@ module VagrantPlugins end def get_inventory_host_vars_string(machine_name) - vars = config.host_vars[machine_name] + # In Ruby, Symbol and String values are different, but + # Vagrant has to unify them for better user experience. + vars = config.host_vars[machine_name.to_sym] + if !vars + vars = config.host_vars[machine_name.to_s] + end s = nil if vars.is_a?(Hash) s = vars.each.collect{ |k, v| "#{k}=#{v}" }.join(" ") diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index cd76d68f8..4a352a29e 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -246,6 +246,16 @@ VF expect(inventory_content).to match("^" + Regexp.quote(machine.name) + ".+http_port=80 maxRequestsPerChild=808") } end + + it "retrieves the host variables by machine name, also in String format" do + config.host_vars = { + "machine1" => "http_port=80 maxRequestsPerChild=808" + } + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + inventory_content = File.read(generated_inventory_file) + expect(inventory_content).to match("^" + Regexp.quote(machine.name) + ".+http_port=80 maxRequestsPerChild=808") + } + end end describe "with groups option" do From 3dbcf5083c6bd0ef2731361bf193f102ee549e46 Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Wed, 2 Dec 2015 08:42:44 +0100 Subject: [PATCH 08/14] provisioners/ansible(both) add more unit tests Improve the test coverage of 'get_inventory_host_vars_string' method. --- .../provisioners/ansible/provisioner_test.rb | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 4a352a29e..a98f456fb 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -237,9 +237,29 @@ VF describe "with host_vars option" do it_should_create_and_use_generated_inventory - it "adds host variables to the generated inventory" do + it "adds host variables (given in Hash format) to the generated inventory" do config.host_vars = { - machine.name => {"http_port" => 80, "maxRequestsPerChild" => 808} + machine1: {"http_port" => 80, "maxRequestsPerChild" => 808} + } + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + inventory_content = File.read(generated_inventory_file) + expect(inventory_content).to match("^" + Regexp.quote(machine.name) + ".+http_port=80 maxRequestsPerChild=808") + } + end + + it "adds host variables (given in Array format) to the generated inventory" do + config.host_vars = { + machine1: ["http_port=80", "maxRequestsPerChild=808"] + } + expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| + inventory_content = File.read(generated_inventory_file) + expect(inventory_content).to match("^" + Regexp.quote(machine.name) + ".+http_port=80 maxRequestsPerChild=808") + } + end + + it "adds host variables (given in String format) to the generated inventory " do + config.host_vars = { + :machine1 => "http_port=80 maxRequestsPerChild=808" } expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| inventory_content = File.read(generated_inventory_file) From c99de13893f036feb37c84a63ea57483f67b3db0 Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Wed, 2 Dec 2015 08:47:58 +0100 Subject: [PATCH 09/14] ansible docs: inventory variables support in 1.8+ Ref #6619 --- website/docs/source/v2/provisioning/ansible_intro.html.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/website/docs/source/v2/provisioning/ansible_intro.html.md b/website/docs/source/v2/provisioning/ansible_intro.html.md index 441e8cbc8..ee031a893 100644 --- a/website/docs/source/v2/provisioning/ansible_intro.html.md +++ b/website/docs/source/v2/provisioning/ansible_intro.html.md @@ -109,7 +109,7 @@ Note that the generated inventory file is uploaded to the guest VM in a subdirec **Host variables:** -Since Vagrant ???, the [`host_vars`](/v2/provisioning/ansible_common.html) option can be used to set [variables for individual hosts](http://docs.ansible.com/ansible/intro_inventory.html#host-variables) in the generated inventory file (see also the notes on group variables below). +As of Vagrant 1.8.0, the [`host_vars`](/v2/provisioning/ansible_common.html) option can be used to set [variables for individual hosts](http://docs.ansible.com/ansible/intro_inventory.html#host-variables) in the generated inventory file (see also the notes on group variables below). ``` Vagrant.configure(2) do |config| @@ -138,7 +138,8 @@ host2 ansible_ssh_host=... http_port=303 maxRequestsPerChild=909 **How to generate Inventory Groups:** -The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. It is also possible to specify [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables). +The [`groups`](/v2/provisioning/ansible_common.html) option can be used to pass a hash of group names and group members to be included in the generated inventory file. +As of Vagrant 1.8.0, it is also possible to specify [group variables](http://docs.ansible.com/ansible/intro_inventory.html#group-variables). With this configuration example: @@ -189,7 +190,7 @@ variable2=example **Notes:** - Prior to Vagrant 1.7.3, the `ansible_ssh_private_key_file` variable was not set in generated inventory, but passed as command line argument to `ansible-playbook` command. - - The generation of group variables blocks (e.g. `[group1:vars]`) is only possible since Vagrant ???. Note however that setting variables directly in the inventory is not the [preferred practice in Ansible](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). If possible, group (or host) variables should be set in `YAML` files stored in the `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory instead. + - The generation of group variables blocks (e.g. `[group1:vars]`) is only possible since Vagrant 1.8.0. Note however that setting variables directly in the inventory is not the [preferred practice in Ansible](http://docs.ansible.com/intro_inventory.html#splitting-out-host-and-group-specific-data). If possible, group (or host) variables should be set in `YAML` files stored in the `group_vars/` or `host_vars/` directories in the playbook (or inventory) directory instead. - Unmanaged machines and undefined groups are not added to the inventory, to avoid useless Ansible errors (e.g. *unreachable host* or *undefined child group*) For example, `machine3` and `group3` in the example below would not be added to the generated inventory file: From 06e772a2419222cdcec4b519dcf99cface81e89d Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Thu, 3 Dec 2015 08:14:47 +0100 Subject: [PATCH 10/14] docs (ansible): update inventory host vars example Better reflect the true generated inventory output. [ci skip] --- website/docs/source/v2/provisioning/ansible_intro.html.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/website/docs/source/v2/provisioning/ansible_intro.html.md b/website/docs/source/v2/provisioning/ansible_intro.html.md index ee031a893..daa21aeb4 100644 --- a/website/docs/source/v2/provisioning/ansible_intro.html.md +++ b/website/docs/source/v2/provisioning/ansible_intro.html.md @@ -132,8 +132,8 @@ Generated inventory: ``` # Generated by Vagrant -host1 ansible_ssh_host=... http_port=80 maxRequestsPerChild=808 -host2 ansible_ssh_host=... http_port=303 maxRequestsPerChild=909 +host1 ansible_ssh_host=... http_port=80 maxRequestsPerChild=808 +host2 ansible_ssh_host=... http_port=303 maxRequestsPerChild=909 ``` **How to generate Inventory Groups:** From 98672819714f25ac4ed59fe6572284d3de8cfd5d Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Thu, 3 Dec 2015 09:34:53 +0100 Subject: [PATCH 11/14] provisioners/ansible: allow symbol in `groups` key After c49a146467f7d7a0e441564a2418a1b8a42bb8a6, it makes even more sense to support Symbol datatypes in `groups` option handling. --- plugins/provisioners/ansible/provisioner/base.rb | 4 ++++ test/unit/plugins/provisioners/ansible/provisioner_test.rb | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index 981cbf5d1..ec8075f99 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -113,6 +113,10 @@ module VagrantPlugins inventory_groups = "" config.groups.each_pair do |gname, gmembers| + if gname.is_a?(Symbol) + gname = gname.to_s + end + if gmembers.is_a?(String) gmembers = gmembers.split(/\s+/) elsif gmembers.is_a?(Hash) diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index a98f456fb..01b0edbf2 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -287,6 +287,7 @@ VF "group1:children" => 'bar', "group2" => [iso_env.machine_names[1]], "group3" => ["unknown", "#{machine.name}"], + group4: [machine.name], "bar" => ["#{machine.name}", "group3"], "bar:children" => ["group1", "group2", "group3", "group4"], } @@ -304,11 +305,13 @@ VF # Skip "unknown" machines expect(inventory_content).to include("[group3]\n#{machine.name}\n") + # Accept Symbol datatype for group names + expect(inventory_content).to include("[group4]\n#{machine.name}\n\n") + # Don't mix group names and host names expect(inventory_content).to include("[bar]\n#{machine.name}\n") # A group of groups only includes declared groups - expect(inventory_content).not_to match(/^group4$/) expect(inventory_content).to include("[bar:children]\ngroup1\ngroup2\ngroup3\n") } end From 4c137a9b6bd38433f9fc3b770b32833a701817ae Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Thu, 3 Dec 2015 09:36:57 +0100 Subject: [PATCH 12/14] provisioners/ansible: fix comment indentation [ci skip] --- plugins/provisioners/ansible/provisioner/base.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/provisioners/ansible/provisioner/base.rb b/plugins/provisioners/ansible/provisioner/base.rb index ec8075f99..6671f0218 100644 --- a/plugins/provisioners/ansible/provisioner/base.rb +++ b/plugins/provisioners/ansible/provisioner/base.rb @@ -91,8 +91,8 @@ module VagrantPlugins def generate_inventory inventory = "# Generated by Vagrant\n\n" - # This "abstract" step must fill the @inventory_machines list - # and return the list of supported host(s) + # This "abstract" step must fill the @inventory_machines list + # and return the list of supported host(s) inventory += generate_inventory_machines inventory += generate_inventory_groups From 8517014a9982e9155c9eb1c08ddbe4715d6b957f Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Thu, 3 Dec 2015 09:39:12 +0100 Subject: [PATCH 13/14] provisioners/ansible: update inventory groups tests With the introduction of inventory variables, group members provided as String are not splitted (by ' ') into an array (instead of auto-conversion to a single-item array). --- .../provisioners/ansible/provisioner_test.rb | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/unit/plugins/provisioners/ansible/provisioner_test.rb b/test/unit/plugins/provisioners/ansible/provisioner_test.rb index 01b0edbf2..9a8188f0f 100644 --- a/test/unit/plugins/provisioners/ansible/provisioner_test.rb +++ b/test/unit/plugins/provisioners/ansible/provisioner_test.rb @@ -283,36 +283,37 @@ VF it "adds group sections to the generated inventory" do config.groups = { - "group1" => "#{machine.name}", - "group1:children" => 'bar', + "group1" => "machine1", + "group1:children" => 'bar group3', "group2" => [iso_env.machine_names[1]], "group3" => ["unknown", "#{machine.name}"], group4: [machine.name], "bar" => ["#{machine.name}", "group3"], - "bar:children" => ["group1", "group2", "group3", "group4"], + "bar:children" => ["group1", "group2", "group3", "group5"], } expect(Vagrant::Util::Subprocess).to receive(:execute).with { |*args| inventory_content = File.read(generated_inventory_file) - # Accept String instead of Array for group that contains a single item - expect(inventory_content).to include("[group1]\n#{machine.name}\n") - expect(inventory_content).to include("[group1:children]\nbar\n") + # Accept String instead of Array for group member list + expect(inventory_content).to include("[group1]\nmachine1\n\n") + expect(inventory_content).to include("[group1:children]\nbar\ngroup3\n\n") # Skip "lost" machines expect(inventory_content).to include("[group2]\n\n") # Skip "unknown" machines - expect(inventory_content).to include("[group3]\n#{machine.name}\n") + expect(inventory_content).to include("[group3]\n#{machine.name}\n\n") # Accept Symbol datatype for group names expect(inventory_content).to include("[group4]\n#{machine.name}\n\n") # Don't mix group names and host names - expect(inventory_content).to include("[bar]\n#{machine.name}\n") + expect(inventory_content).to include("[bar]\n#{machine.name}\n\n") # A group of groups only includes declared groups - expect(inventory_content).to include("[bar:children]\ngroup1\ngroup2\ngroup3\n") + expect(inventory_content).not_to include("group5") + expect(inventory_content).to match(Regexp.quote("[bar:children]\ngroup1\ngroup2\ngroup3\n") + "$") } end From cc2d11b49710f11e35fa64efa2add554de60a35c Mon Sep 17 00:00:00 2001 From: Gilles Cornu Date: Thu, 3 Dec 2015 21:50:53 +0100 Subject: [PATCH 14/14] provisioners/ansible+ansible_local: inventory vars Add support for group and host variables in the generated inventory. Close #6619 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0e4f48173..249891a71 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,8 @@ IMPROVEMENTS: scripts [GH-6185] - provisioners/shell: add `env` option [GH-6588, GH-6516] - provisioners/ansible+ansible_local: add support for ansible-galaxy [GH-2718] + - provisioners/ansible+ansible_local: add support for group and host variables + in the generated inventory [GH-6619] - provisioners/ansible: add support for WinRM settings [GH-5086] - provisioners/ansible: add new `force_remote_user` option to control whether `ansible_ssh_user` parameter should be applied or not [GH-6348]