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.
- 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
|