vagrant-ansible_auto 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/Gemfile +11 -0
- data/LICENSE.md +23 -0
- data/README.md +129 -0
- data/Rakefile +12 -0
- data/TODO.md +8 -0
- data/Vagrantfile +23 -0
- data/Vagrantfile2 +4 -0
- data/Vagrantfile3 +8 -0
- data/Vagrantfile4 +31 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/bash_installed.rb +30 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/check_open_port.rb +34 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/executable_installed.rb +20 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/gateway_addresses.rb +62 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/private_key.rb +22 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/public_key.rb +28 -0
- data/lib/vagrant/ansible_auto/cap/guest/posix/ssh_server_address.rb +88 -0
- data/lib/vagrant/ansible_auto/command/inventory.rb +50 -0
- data/lib/vagrant/ansible_auto/command/root.rb +59 -0
- data/lib/vagrant/ansible_auto/config.rb +78 -0
- data/lib/vagrant/ansible_auto/errors.rb +14 -0
- data/lib/vagrant/ansible_auto/host.rb +86 -0
- data/lib/vagrant/ansible_auto/inventory.rb +189 -0
- data/lib/vagrant/ansible_auto/plugin.rb +74 -0
- data/lib/vagrant/ansible_auto/provisioner.rb +181 -0
- data/lib/vagrant/ansible_auto/util.rb +24 -0
- data/lib/vagrant/ansible_auto/version.rb +6 -0
- data/lib/vagrant/ansible_auto.rb +5 -0
- data/playbooks/test.yml +4 -0
- data/spec/spec_helper.rb +93 -0
- data/spec/vagrant/ansible_auto/host_spec.rb +43 -0
- data/spec/vagrant/ansible_auto/inventory_spec.rb +79 -0
- data/vagrant-ansible_auto.gemspec +32 -0
- 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
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
data/Vagrantfile3
ADDED
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
|