vagrant-ansible_auto 0.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (34) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +11 -0
  3. data/LICENSE.md +23 -0
  4. data/README.md +129 -0
  5. data/Rakefile +12 -0
  6. data/TODO.md +8 -0
  7. data/Vagrantfile +23 -0
  8. data/Vagrantfile2 +4 -0
  9. data/Vagrantfile3 +8 -0
  10. data/Vagrantfile4 +31 -0
  11. data/lib/vagrant/ansible_auto/cap/guest/posix/bash_installed.rb +30 -0
  12. data/lib/vagrant/ansible_auto/cap/guest/posix/check_open_port.rb +34 -0
  13. data/lib/vagrant/ansible_auto/cap/guest/posix/executable_installed.rb +20 -0
  14. data/lib/vagrant/ansible_auto/cap/guest/posix/gateway_addresses.rb +62 -0
  15. data/lib/vagrant/ansible_auto/cap/guest/posix/private_key.rb +22 -0
  16. data/lib/vagrant/ansible_auto/cap/guest/posix/public_key.rb +28 -0
  17. data/lib/vagrant/ansible_auto/cap/guest/posix/ssh_server_address.rb +88 -0
  18. data/lib/vagrant/ansible_auto/command/inventory.rb +50 -0
  19. data/lib/vagrant/ansible_auto/command/root.rb +59 -0
  20. data/lib/vagrant/ansible_auto/config.rb +78 -0
  21. data/lib/vagrant/ansible_auto/errors.rb +14 -0
  22. data/lib/vagrant/ansible_auto/host.rb +86 -0
  23. data/lib/vagrant/ansible_auto/inventory.rb +189 -0
  24. data/lib/vagrant/ansible_auto/plugin.rb +74 -0
  25. data/lib/vagrant/ansible_auto/provisioner.rb +181 -0
  26. data/lib/vagrant/ansible_auto/util.rb +24 -0
  27. data/lib/vagrant/ansible_auto/version.rb +6 -0
  28. data/lib/vagrant/ansible_auto.rb +5 -0
  29. data/playbooks/test.yml +4 -0
  30. data/spec/spec_helper.rb +93 -0
  31. data/spec/vagrant/ansible_auto/host_spec.rb +43 -0
  32. data/spec/vagrant/ansible_auto/inventory_spec.rb +79 -0
  33. data/vagrant-ansible_auto.gemspec +32 -0
  34. metadata +175 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 40fd0b7cb409371ac24b6e878076c7aa5020db70
4
+ data.tar.gz: 1ff945bf3f9f43324c504cb2a987c49f1d7eccce
5
+ SHA512:
6
+ metadata.gz: 0a4e2871cff450346b750f166c39d4730b97e41ba8c39476582cde9ec307d6a42035b99739590fe7dc9baadd181efaf5776d67152ba424b57a877ce87e6530e7
7
+ data.tar.gz: 5d13474ca2aed002005b23f2c028fe932470293914551e9ddf32b3de0f5fbdd9e9f9ad5a576c2cc4c0ddd8a2502cafb79c22c77639488da910d3247936b98439
data/Gemfile ADDED
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ source 'https://rubygems.org'
3
+
4
+ group :development do
5
+ gem 'pry'
6
+ gem 'vagrant', github: 'mitchellh/vagrant'
7
+ end
8
+
9
+ group :plugins do
10
+ gemspec
11
+ end
data/LICENSE.md ADDED
@@ -0,0 +1,23 @@
1
+ Copyright (c) 2014-2015 Ignacio Galindo
2
+ Copyright (c) 2016-2017 Matt Schreiber
3
+
4
+ MIT License
5
+
6
+ Permission is hereby granted, free of charge, to any person obtaining
7
+ a copy of this software and associated documentation files (the
8
+ "Software"), to deal in the Software without restriction, including
9
+ without limitation the rights to use, copy, modify, merge, publish,
10
+ distribute, sublicense, and/or sell copies of the Software, and to
11
+ permit persons to whom the Software is furnished to do so, subject to
12
+ the following conditions:
13
+
14
+ The above copyright notice and this permission notice shall be
15
+ included in all copies or substantial portions of the Software.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # Vagrant::AnsibleAuto
2
+
3
+ This Vagrant plugin provides the `ansible_auto` provisioner that automatically
4
+ sets up the provisioned guest as an Ansible control machine for the nodes
5
+ defined in your Vagrantfile. It also provides the `vagrant ansible` subcommand
6
+ that generates an inventory file for use on your Vagrant host machine.
7
+
8
+ ## Installation
9
+
10
+ Install with:
11
+
12
+ ```shell
13
+ $ vagrant plugin install vagrant-ansible_auto
14
+ ```
15
+
16
+ ## Usage
17
+
18
+ ### Inventory Generation
19
+
20
+ Say you have a Vagrantfile with the following contents:
21
+
22
+ ```ruby
23
+ Vagrant.configure(2) do |config|
24
+ config.vm.box = 'hashicorp/precise64'
25
+
26
+ (1..2).each do |i|
27
+ name = "ansible-test-worker-#{i}"
28
+ config.vm.define name do |target|
29
+ end
30
+ end
31
+
32
+ config.vm.define 'ansible-test-control' do |machine|
33
+ machine.vm.provision :ansible_auto do |ansible|
34
+ ansible.limit = '*'
35
+ ansible.playbook = 'playbooks/test.yml'
36
+ end
37
+ end
38
+
39
+ config.ansible.groups = {
40
+ 'control' => %w(ansible-test-control),
41
+ 'worker' => %w(ansible-test-worker-1 ansible-test-worker-2),
42
+ 'cluster:children' => %w(control worker),
43
+ }
44
+ end
45
+ ```
46
+
47
+ Running `vagrant ansible inventory` will print this Ansible inventory:
48
+
49
+ ```ini
50
+ ansible-test-worker-1 ansible_ssh_user=vagrant ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222 ansible_ssh_private_key_file=/home/matt/git/vagrant-ansible_inventory/.vagrant/machines/ansible-test-worker-1/virtualbox/private_key
51
+ ansible-test-worker-2 ansible_ssh_user=vagrant ansible_ssh_host=127.0.0.1 ansible_ssh_port=2200 ansible_ssh_private_key_file=/home/matt/git/vagrant-ansible_inventory/.vagrant/machines/ansible-test-worker-2/virtualbox/private_key
52
+ ansible-test-control ansible_ssh_user=vagrant ansible_ssh_host=127.0.0.1 ansible_ssh_port=2201 ansible_ssh_private_key_file=/home/matt/git/vagrant-ansible_inventory/.vagrant/machines/ansible-test-control/virtualbox/private_key
53
+ [control]
54
+ ansible-test-control
55
+ [worker]
56
+ ansible-test-worker-1
57
+ ansible-test-worker-2
58
+ [cluster:children]
59
+ control
60
+ worker
61
+ ```
62
+
63
+ ### Provisioning
64
+
65
+ The `ansible_auto` provisioner is an augmented version of the
66
+ [`ansible_local` provisioner included with Vagrant](https://www.vagrantup.com/docs/provisioning/ansible_local.html).
67
+ It accepts all options valid for that provisioner, and adds the following
68
+ options:
69
+
70
+ ```ruby
71
+ Vagrant.configure(2) do |config|
72
+ config.define 'ansible-control' do |machine|
73
+ machine.provision :ansible_auto do |ansible|
74
+ # Will show up in inventory as
75
+ # [control]
76
+ # ansible-control
77
+ ansible.groups = {
78
+ 'control' => %(ansible-control)
79
+ }
80
+
81
+ # Will show up in inventory as
82
+ # [dev:children]
83
+ # control
84
+ ansible.children = {
85
+ 'dev' => %w(control)
86
+ }
87
+
88
+ # Will show up in inventory as
89
+ # [dev:vars]
90
+ # ansible_port = 2222
91
+ ansible.vars = {
92
+ 'dev' => {
93
+ 'ansible_port' => 2222
94
+ }
95
+ }
96
+
97
+ # Enable or disable `StrictHostKeyChecking` SSH option.
98
+ # Disabled by default.
99
+ ansible.strict_host_key_checking = false
100
+
101
+ # The number of times to attempt to connect to a managed host from the
102
+ # Ansible control machine.
103
+ ansible.host_connect_tries = 10
104
+
105
+ # The number of seconds to delay between connection attempts.
106
+ ansible.host_connect_sleep = 5
107
+ end
108
+ end
109
+ end
110
+ ```
111
+
112
+ Each guest provisioned with `ansible_auto` will be set up as an Ansible
113
+ control machine with the ability to connect to other guests defined in the
114
+ `Vagrantfile`. This is facilitated by uploading the private keys of each guest
115
+ to a temporary path on the control machine and assigning this path as the
116
+ hostvar `ansible_ssh_private_key_file` to the relevant host in the generated
117
+ inventory.
118
+
119
+ ## Contributing
120
+
121
+ 1. Fork it ( https://github.com/joiggama/vagrant-ansible_auto/fork )
122
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
123
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
124
+ 4. Push to the branch (`git push origin my-new-feature`)
125
+ 5. Create a new Pull Request
126
+
127
+ ## License
128
+
129
+ [The MIT licence](LICENSE.md)
data/Rakefile ADDED
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.ruby_opts = "-w"
7
+ end
8
+
9
+ require "rubocop/rake_task"
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: [:rubocop, :spec]
data/TODO.md ADDED
@@ -0,0 +1,8 @@
1
+ # TODO
2
+
3
+ - See if it possible to Vagrant::Util::IsPortOpen instead of Bash/nc/etc for
4
+ checking whether a port is open. *Has to run on the guest*, so probably not
5
+ possible.
6
+ - Util::ScopedHashOverride for the key conversions done in Host?
7
+ - Util::HashWithIndifferentAccess for Host?
8
+ - default vaues for arguments to attr_writer methods in `Inventory`
data/Vagrantfile ADDED
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+ Vagrant.configure(2) do |config|
3
+ define_vm = lambda do |name, box, memory|
4
+ config.vm.define name do |instance|
5
+ instance.vm.box = box
6
+ instance.vm.hostname = name
7
+ instance.vm.network 'private_network', type: 'dhcp'
8
+ instance.vm.provider :virtualbox do |i|
9
+ i.name = name
10
+ i.memory = memory
11
+ end
12
+ end
13
+ end
14
+
15
+ define_vm.call 'master', 'ubuntu/trusty32', 256
16
+ define_vm.call 'slave-1', 'ubuntu/trusty32', 256
17
+ define_vm.call 'slave-2', 'ubuntu/trusty32', 256
18
+
19
+ config.ansible.groups = {
20
+ 'cluster:children' => %w(master slaves),
21
+ 'slaves' => ['slave-1', 'slave-2'],
22
+ }
23
+ end
data/Vagrantfile2 ADDED
@@ -0,0 +1,4 @@
1
+ Vagrant.configure(2) do |config|
2
+ config.vm.box = 'ubuntu/trusty64'
3
+ config.vm.network :private_network, type: :dhcp
4
+ end
data/Vagrantfile3 ADDED
@@ -0,0 +1,8 @@
1
+ Vagrant.configure(2) do |config|
2
+ config.vm.box = 'trusty64'
3
+ config.vm.network :private_network, type: :dhcp
4
+
5
+ config.ansible.groups = {
6
+ 'ubuntu' => ['default']
7
+ }
8
+ end
data/Vagrantfile4 ADDED
@@ -0,0 +1,31 @@
1
+ Vagrant.configure(2) do |config|
2
+ config.vm.box = 'hashicorp/precise64'
3
+
4
+ (1..2).each do |i|
5
+ name = "ansible-test-worker-#{i}"
6
+ config.vm.define name do |target|
7
+ end
8
+ end
9
+
10
+ config.vm.define 'ansible-test-control' do |machine|
11
+ machine.vm.provision :ansible_auto do |ansible|
12
+ ansible.limit = '*'
13
+ ansible.playbook = 'playbooks/test.yml'
14
+ end
15
+ end
16
+
17
+ config.ansible.groups = {
18
+ 'control' => %w(ansible-test-control),
19
+ 'worker' => %w(ansible-test-worker-1 ansible-test-worker-2),
20
+ 'cluster:children' => %w(control worker),
21
+ }
22
+
23
+ config.ansible.vars = {
24
+ 'control' => {
25
+ 'role' => 'ansible-control',
26
+ },
27
+ 'worker' => {
28
+ 'role' => 'ansible-worker',
29
+ }
30
+ }
31
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+ module VagrantPlugins
3
+ module AnsibleAuto
4
+ module Cap
5
+ module Guest
6
+ module POSIX
7
+ class BashInstalled
8
+ class << self
9
+ def bash_installed?(machine, version = nil)
10
+ machine.communicate.execute(%q(command bash -c 'printf -- "%s\t%s" "$BASH" "$BASH_VERSION"'), error_check: false) do |type, data|
11
+ data.chomp!
12
+
13
+ # Not sure why, but we always get an empty first line...
14
+ next if data.empty?
15
+
16
+ if type == :stdout
17
+ bash_path, bash_version = *data.split("\t")
18
+ return (!bash_path.empty? and (version.nil? or version == bash_version))
19
+ end
20
+ end
21
+
22
+ false
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+ require 'uri'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Cap
7
+ module Guest
8
+ module POSIX
9
+ class CheckOpenPort
10
+ class << self
11
+ def check_open_port(machine, host, port, proto = 'tcp')
12
+ return nil unless machine.communicate.test('bash')
13
+
14
+ # Check that we got a valid URI by constructing a URI object
15
+ # and watching for exceptions raised upon component assignment.
16
+ begin
17
+ uri = URI('').tap do |u|
18
+ u.host = host
19
+ u.port = port
20
+ end
21
+ rescue URI::InvalidComponentError
22
+ return nil
23
+ end
24
+
25
+ target = File.join('/dev/', proto, uri.host, uri.port.to_s).shellescape
26
+ machine.communicate.test("read < #{target}", shell: '/bin/bash')
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+ require 'shellwords'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Cap
7
+ module Guest
8
+ module POSIX
9
+ class ExecutableInstalled
10
+ class << self
11
+ def executable_installed?(machine, executable)
12
+ machine.communicate.test(%[test -x "$(command -v #{executable.shellescape})"], error_check: false)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+ require 'set'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Cap
7
+ module Guest
8
+ module POSIX
9
+ class GatewayAddresses
10
+ class << self
11
+ def gateway_addresses(machine)
12
+ with_default_gateway_addresses(machine).to_a.compact
13
+ end
14
+
15
+ private
16
+
17
+ def with_default_gateway_addresses(machine)
18
+ return enum_for(__method__, machine) unless block_given?
19
+
20
+ seen_addresses = Set.new
21
+ yield_unseen_address = lambda do |a|
22
+ yield a unless seen_addresses.include? a
23
+ seen_addresses << a
24
+ end
25
+
26
+ machine.communicate.execute('ip route show', error_check: false) do |type, data|
27
+ if type == :stdout
28
+ data.lines.each do |line|
29
+ if line.start_with?('default')
30
+ yield_unseen_address.call(line.split[2])
31
+ end
32
+ end
33
+ end
34
+ end
35
+
36
+ machine.communicate.execute('route -n', error_check: false) do |type, data|
37
+ if type == :stdout
38
+ data.lines.each do |line|
39
+ if line.start_with?('0.0.0.0')
40
+ yield_unseen_address.call(line.split[1])
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ machine.communicate.execute('netstat -rn', error_check: false) do |type, data|
47
+ if type == :stdout
48
+ data.lines.each do |line|
49
+ if line.start_with?('0.0.0.0')
50
+ yield_unseen_address.call(line.split[1])
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VagrantPlugins
4
+ module AnsibleAuto
5
+ module Cap
6
+ module Guest
7
+ module POSIX
8
+ class PrivateKey
9
+ class << self
10
+ def generate_private_key(machine, path, type = 'rsa', bits = '2048')
11
+ return unless machine.guest.capability?(:executable_installed?) \
12
+ && machine.guest.capability(:executable_installed?, 'ssh-keygen')
13
+
14
+ machine.communicate.execute("ssh-keygen -t #{type} -b #{bits} -C 'Vagrant-generated keypair' -f #{path}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module VagrantPlugins
4
+ module AnsibleAuto
5
+ module Cap
6
+ module Guest
7
+ module POSIX
8
+ class PrivateKey
9
+ class << self
10
+ def fetch_public_key(machine, path)
11
+ return unless machine.guest.capability?(:executable_installed?) \
12
+ && machine.guest.capability(:executable_installed?, 'ssh-keygen')
13
+
14
+ # TODO: handle bad status
15
+ public_key = ''
16
+ _status = machine.communicate.execute("ssh-keygen -f #{path} -y") do |data_type, data|
17
+ public_key += data if data_type == :stdout
18
+ end
19
+
20
+ public_key
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+ require 'set'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Cap
7
+ module Guest
8
+ module POSIX
9
+ class SSHServerAddress
10
+ class << self
11
+ def ssh_server_address(machine, target_machine = nil)
12
+ with_open_ports(machine, target_machine).first
13
+ end
14
+
15
+ private
16
+
17
+ def ssh_server_addresses(machine, target_machine = nil)
18
+ with_open_ports(machine, target_machine).to_a
19
+ end
20
+
21
+ def with_open_ports(machine, target_machine = nil)
22
+ return enum_for(__method__, machine, target_machine) unless block_given?
23
+
24
+ return unless machine.guest.capability?(:check_open_port)
25
+
26
+ target_machine ||= machine
27
+ ssh_info = target_machine.ssh_info
28
+ default_port = ssh_info.nil? ? 22 : ssh_info[:port]
29
+
30
+ with_candidate_addresses(target_machine) do |host, port|
31
+ port ||= default_port
32
+
33
+ if machine.guest.capability(:check_open_port, host, port)
34
+ yield host, port
35
+ end
36
+ end
37
+ end
38
+
39
+ network_type_precedence_map = Hash[[:forwarded_port, :public_network, :private_network].each_with_index.map { |type, i| [type, i] }]
40
+ define_method(:network_type_precedence) do |type|
41
+ network_type_precedence_map[type]
42
+ end
43
+
44
+ def with_candidate_addresses(machine)
45
+ return enum_for(__method__, machine) unless block_given?
46
+
47
+ seen_candidates = Set.new
48
+ yield_unseen_candidate = lambda do |host_and_port|
49
+ yield(*host_and_port) unless seen_candidates.include?(host_and_port)
50
+ seen_candidates << host_and_port
51
+ end
52
+
53
+ if machine.provider.capability?(:public_address)
54
+ yield_unseen_candidate.call([machine.provider.capability(:public_address)])
55
+ end
56
+
57
+ unless machine.ssh_info.nil?
58
+ yield_unseen_candidate.call([machine.ssh_info[:host]])
59
+ end
60
+
61
+ has_routable_ip = false
62
+ machine.config.vm.networks.sort_by { |(type, _)| network_type_precedence(type) }.each do |type, info|
63
+ case type
64
+ when :private_network, :public_network
65
+ has_routable_ip = true
66
+
67
+ yield_unseen_candidate.call([info[:ip]]) if info.key?(:ip)
68
+ when :forwarded_port
69
+ # TODO: the `:id' restriction might not be right.
70
+ if info[:protocol] == 'tcp' and info[:id] == 'ssh'
71
+ yield_unseen_candidate.call([info[:host_ip], info[:host]])
72
+ end
73
+ end
74
+ end
75
+
76
+ return if has_routable_ip or !machine.guest.capability?(:gateway_addresses)
77
+
78
+ machine.guest.capability(:gateway_addresses).each do |gateway_address|
79
+ yield_unseen_candidate.call(gateway_address)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+ require 'optparse'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Command
7
+ class Inventory < Vagrant.plugin(2, :command)
8
+ def self.synopsis
9
+ 'dynamic ansible inventory'
10
+ end
11
+
12
+ def execute
13
+ opts = OptionParser.new do |op|
14
+ op.banner = 'Usage: vagrant ansible inventory [<options>]'
15
+ op.separator ''
16
+ op.separator 'Available options:'
17
+
18
+ op.on('-l', '--list', 'List all hosts as json') do |_target|
19
+ @env.ui.info inventory.to_json, prefix: false
20
+ return 0
21
+ end
22
+
23
+ op.on('-h', '--help', 'Show this message') do
24
+ @env.ui.info opts.help, prefix: false
25
+ return 0
26
+ end
27
+ end
28
+
29
+ @argv = parse_options(opts)
30
+
31
+ @env.ui.info inventory.to_ini, prefix: false
32
+
33
+ 0
34
+ end
35
+
36
+ private
37
+
38
+ def inventory
39
+ @inventory = with_target_vms(@argv) {}.each_with_object(AnsibleAuto::Inventory.new) do |machine, inventory|
40
+ unless machine.state.id == :running
41
+ @env.ui.warn "machine #{machine.name} is not running; falling back to default hostvar values"
42
+ end
43
+ inventory.merge!(machine.config.ansible.inventory)
44
+ inventory.add_host(machine)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,59 @@
1
+ # frozen_string_literal: true
2
+ require 'optparse'
3
+
4
+ module VagrantPlugins
5
+ module AnsibleAuto
6
+ module Command
7
+ class Root < Vagrant.plugin(2, :command)
8
+ def self.synopsis
9
+ 'build ansible inventory'
10
+ end
11
+
12
+ def initialize(argv, env)
13
+ super
14
+
15
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
16
+
17
+ @subcommands = Vagrant::Registry.new
18
+
19
+ @subcommands.register(:inventory) do
20
+ require_relative 'inventory'
21
+ Inventory
22
+ end
23
+ end
24
+
25
+ def execute
26
+ if @main_args.include?('-h') || @main_args.include?('--help')
27
+ return help
28
+ end
29
+
30
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
31
+ return help if !command_class || !@sub_command
32
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
33
+
34
+ command_class.new(@sub_args, @env).execute
35
+ end
36
+
37
+ def help
38
+ opts = OptionParser.new do |o|
39
+ o.banner = 'Usage: vagrant ansible <subcommand> [<options>]'
40
+ o.separator ''
41
+ o.separator 'Available subcommands:'
42
+
43
+ keys = []
44
+ @subcommands.each { |key, _value| keys << key.to_s }
45
+
46
+ keys.sort.each do |key|
47
+ o.separator " #{key}"
48
+ end
49
+
50
+ o.separator ""
51
+ o.separator "For help on any individual subcommand run `vagrant ansible <subcommand> -h`"
52
+ end
53
+
54
+ @env.ui.info(opts.help, prefix: false)
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end