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
@@ -0,0 +1,78 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'vagrant/ansible_auto/inventory'
|
3
|
+
require 'vagrant/ansible_auto/errors'
|
4
|
+
require 'vagrant/util/deep_merge'
|
5
|
+
|
6
|
+
require 'vagrant'
|
7
|
+
require Vagrant.source_root + 'plugins/provisioners/ansible/config/guest'
|
8
|
+
|
9
|
+
module VagrantPlugins
|
10
|
+
module AnsibleAuto
|
11
|
+
class Config < VagrantPlugins::Ansible::Config::Guest
|
12
|
+
attr_accessor :inventory, :groups, :vars, :children,
|
13
|
+
:strict_host_key_checking, :host_connect_tries, :host_connect_sleep
|
14
|
+
|
15
|
+
protected(:inventory=)
|
16
|
+
|
17
|
+
def initialize
|
18
|
+
super
|
19
|
+
@inventory = Inventory.new
|
20
|
+
@groups = UNSET_VALUE
|
21
|
+
@vars = UNSET_VALUE
|
22
|
+
@children = UNSET_VALUE
|
23
|
+
@strict_host_key_checking = UNSET_VALUE
|
24
|
+
@host_connect_tries = UNSET_VALUE
|
25
|
+
@host_connect_sleep = UNSET_VALUE
|
26
|
+
@__errors = []
|
27
|
+
end
|
28
|
+
|
29
|
+
def finalize!
|
30
|
+
super
|
31
|
+
@inventory.groups = @groups unless @groups == UNSET_VALUE
|
32
|
+
@inventory.vars = @vars unless @vars == UNSET_VALUE
|
33
|
+
@inventory.children = @children unless @children == UNSET_VALUE
|
34
|
+
@strict_host_key_checking = false if @strict_host_key_checking == UNSET_VALUE
|
35
|
+
@host_connect_tries = 10 if @host_connect_tries == UNSET_VALUE
|
36
|
+
@host_connect_sleep = 2 if @host_connect_sleep == UNSET_VALUE
|
37
|
+
rescue Errors::InventoryError => e
|
38
|
+
@__errors << e.message
|
39
|
+
end
|
40
|
+
|
41
|
+
def validate(machine)
|
42
|
+
super
|
43
|
+
|
44
|
+
errors = _detected_errors + @__errors
|
45
|
+
|
46
|
+
# TODO: -- test that `host_wait...' values are integers
|
47
|
+
unless @strict_host_key_checking == true or @strict_host_key_checking == false
|
48
|
+
errors << "strict_host_key_checking must be either true or false"
|
49
|
+
end
|
50
|
+
|
51
|
+
{ 'ansible_auto' => errors }
|
52
|
+
end
|
53
|
+
|
54
|
+
def merge(other)
|
55
|
+
return super if other.nil?
|
56
|
+
|
57
|
+
super.tap do |result|
|
58
|
+
result.groups = conditional_merge(groups, other.groups)
|
59
|
+
result.vars = conditional_merge(vars, other.vars)
|
60
|
+
result.children = conditional_merge(children, other.children)
|
61
|
+
result.inventory = inventory.merge(other.inventory)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
def conditional_merge(a, b)
|
68
|
+
if b.nil? or b == UNSET_VALUE
|
69
|
+
a
|
70
|
+
elsif a.nil? or a == UNSET_VALUE
|
71
|
+
b
|
72
|
+
else
|
73
|
+
Vagrant::Util::DeepMerge.deep_merge(a, b)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module VagrantPlugins
|
3
|
+
module AnsibleAuto
|
4
|
+
module Errors
|
5
|
+
class InventoryError < Vagrant::Errors::VagrantError
|
6
|
+
error_namespace('vagrant.provisioners.ansible_auto')
|
7
|
+
end
|
8
|
+
|
9
|
+
class MissingGroupError < InventoryError
|
10
|
+
error_key(:missing_group)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'vagrant'
|
3
|
+
require 'vagrant/ansible_auto/util'
|
4
|
+
|
5
|
+
module VagrantPlugins
|
6
|
+
module AnsibleAuto
|
7
|
+
class Host
|
8
|
+
include VagrantPlugins::AnsibleAuto::Util
|
9
|
+
|
10
|
+
ANSIBLE_HOSTVARS = [:ssh_user, :ssh_host, :ssh_port, :ssh_private_key_file, :connection].freeze
|
11
|
+
|
12
|
+
attr_writer(*ANSIBLE_HOSTVARS)
|
13
|
+
|
14
|
+
def initialize(name, hostvars = {})
|
15
|
+
@name = name
|
16
|
+
|
17
|
+
# Convert keys to symbols
|
18
|
+
@hostvars = hostvars.each_with_object({}) { |(k, v), acc| acc[k.to_sym] = v }
|
19
|
+
end
|
20
|
+
|
21
|
+
def name
|
22
|
+
@name ||= 'default'
|
23
|
+
end
|
24
|
+
|
25
|
+
def ssh_user
|
26
|
+
@ssh_user ||= @hostvars[:ssh_user] || 'vagrant'
|
27
|
+
end
|
28
|
+
|
29
|
+
def ssh_host
|
30
|
+
@ssh_host ||= @hostvars[:ssh_host] || '127.0.0.1'
|
31
|
+
end
|
32
|
+
|
33
|
+
def ssh_port
|
34
|
+
@ssh_port ||= @hostvars[:ssh_port] || 22
|
35
|
+
end
|
36
|
+
|
37
|
+
def ssh_private_key_file
|
38
|
+
@ssh_private_key_file ||= @hostvars[:ssh_private_key_file]
|
39
|
+
end
|
40
|
+
|
41
|
+
def connection
|
42
|
+
@connection ||= @hostvars[:connection]
|
43
|
+
end
|
44
|
+
|
45
|
+
def hostvars
|
46
|
+
ANSIBLE_HOSTVARS.each_with_object({}) do |m, acc|
|
47
|
+
value = send(m)
|
48
|
+
acc["ansible_#{m}"] = value unless value.nil?
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def to_h
|
53
|
+
{ name => hostvars }
|
54
|
+
end
|
55
|
+
|
56
|
+
def to_ini
|
57
|
+
[name, *hostvars.reject { |_, value| value.nil? }.map { |key, value| "#{key}=#{value}" }].join(' ')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class HostMachine < Host
|
62
|
+
def initialize(machine, hostvars = {})
|
63
|
+
super(machine.name, hostvars)
|
64
|
+
@machine = machine
|
65
|
+
@ssh_info = machine.ssh_info || {}
|
66
|
+
end
|
67
|
+
|
68
|
+
def ssh_user
|
69
|
+
@ssh_user ||= @hostvars[:ssh_user] || @ssh_info[:username] || super
|
70
|
+
end
|
71
|
+
|
72
|
+
def ssh_host
|
73
|
+
@ssh_host ||= @hostvars[:ssh_host] || @ssh_info[:host] || super
|
74
|
+
end
|
75
|
+
|
76
|
+
def ssh_port
|
77
|
+
@ssh_port ||= @hostvars[:ssh_port] || @ssh_info[:port] || super
|
78
|
+
end
|
79
|
+
|
80
|
+
# TODO: better inference of which private key to use
|
81
|
+
def ssh_private_key_file
|
82
|
+
@ssh_private_key_file ||= @hostvars[:ssh_private_key_file] || fetch_private_key(@machine)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'set'
|
3
|
+
require 'json'
|
4
|
+
require 'vagrant/ansible_auto/host'
|
5
|
+
|
6
|
+
module VagrantPlugins
|
7
|
+
module AnsibleAuto
|
8
|
+
class Inventory
|
9
|
+
def groups
|
10
|
+
@groups = Hash.new { |hash, key| hash[key] = Set.new } if unset?(@groups)
|
11
|
+
@groups
|
12
|
+
end
|
13
|
+
|
14
|
+
def hosts
|
15
|
+
@hosts = Set.new if unset?(@hosts)
|
16
|
+
@hosts
|
17
|
+
end
|
18
|
+
|
19
|
+
def vars
|
20
|
+
@vars = Hash.new { |hash, key| hash[key] = {} } if unset?(@vars)
|
21
|
+
@vars
|
22
|
+
end
|
23
|
+
|
24
|
+
def children
|
25
|
+
@children = Hash.new { |hash, key| hash[key] = Set.new } if unset?(@children)
|
26
|
+
@children
|
27
|
+
end
|
28
|
+
|
29
|
+
def groups=(new_groups)
|
30
|
+
@groups = nil
|
31
|
+
|
32
|
+
new_groups.each do |group_heading, entries|
|
33
|
+
group, type = group_heading.to_s.split(':')
|
34
|
+
case type
|
35
|
+
when 'vars'
|
36
|
+
entries = {} if entries.nil?
|
37
|
+
vars_for(group, entries)
|
38
|
+
when 'children'
|
39
|
+
entries = [] if entries.nil?
|
40
|
+
children_of(group, *entries)
|
41
|
+
else
|
42
|
+
entries = [] if entries.nil?
|
43
|
+
add_group(group, *entries)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
groups
|
48
|
+
end
|
49
|
+
|
50
|
+
def hosts=(_new_hosts)
|
51
|
+
@hosts = nil
|
52
|
+
|
53
|
+
news_hosts.each do |host, hostvars|
|
54
|
+
hostvars = {} if hostvars.nil?
|
55
|
+
add_host(host, hostvars)
|
56
|
+
end
|
57
|
+
|
58
|
+
hosts
|
59
|
+
end
|
60
|
+
|
61
|
+
def vars=(new_vars)
|
62
|
+
@vars = nil
|
63
|
+
|
64
|
+
new_vars.each_pair do |group, group_vars|
|
65
|
+
vars_for(group, group_vars)
|
66
|
+
end
|
67
|
+
|
68
|
+
vars
|
69
|
+
end
|
70
|
+
|
71
|
+
def children=(new_children)
|
72
|
+
@children = nil
|
73
|
+
|
74
|
+
new_children.each_pair do |group, group_children|
|
75
|
+
children_of(group, *group_children)
|
76
|
+
end
|
77
|
+
|
78
|
+
children
|
79
|
+
end
|
80
|
+
|
81
|
+
def add_group(group, *members)
|
82
|
+
groups[group.to_s].tap do |group_members|
|
83
|
+
group_members.merge(members)
|
84
|
+
return group_members
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def add_host(host, hostvars = {})
|
89
|
+
hosts.add case host
|
90
|
+
when Host
|
91
|
+
host
|
92
|
+
when String, Symbol
|
93
|
+
Host.new(host, hostvars)
|
94
|
+
else
|
95
|
+
HostMachine.new(host, hostvars)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
def vars_for(group, new_vars = {})
|
100
|
+
vars[group.to_s].tap do |group_vars|
|
101
|
+
group_vars.merge!(new_vars)
|
102
|
+
return group_vars
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def children_of(group, *new_children)
|
107
|
+
children[group.to_s].tap do |group_children|
|
108
|
+
group_children.merge(new_children.map(&:to_s))
|
109
|
+
return group_children
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def merge!(other)
|
114
|
+
@groups = groups.merge(other.groups) do |_group, group_members, other_group_members|
|
115
|
+
group_members.merge(other_group_members)
|
116
|
+
end
|
117
|
+
|
118
|
+
@vars = vars.merge(other.vars) do |_group, group_vars, other_group_vars|
|
119
|
+
group_vars.merge(other_group_vars)
|
120
|
+
end
|
121
|
+
|
122
|
+
@children = children.merge(other.children) do |_group, group_children, other_group_children|
|
123
|
+
group_children.merge(other_group_children)
|
124
|
+
end
|
125
|
+
|
126
|
+
self
|
127
|
+
end
|
128
|
+
|
129
|
+
def merge(other)
|
130
|
+
clone.merge!(other)
|
131
|
+
end
|
132
|
+
|
133
|
+
def hostvars
|
134
|
+
hosts.each_with_object({}) { |host, acc| acc.merge!(host.hostvars) }
|
135
|
+
end
|
136
|
+
|
137
|
+
def to_h
|
138
|
+
{}.tap do |h|
|
139
|
+
h.merge!(Hash[groups.map { |group, members| [group, members.to_a] }])
|
140
|
+
h['_'] = hosts.map(&:to_h)
|
141
|
+
h.merge!(Hash[vars.map { |group, group_vars| ["#{group}:vars", group_vars] }])
|
142
|
+
h.merge!(Hash[children.map { |group, group_children| ["#{group}:children", group_children.to_a] }])
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_json
|
147
|
+
to_h.tap do |h|
|
148
|
+
h.delete('_')
|
149
|
+
h['_meta'] = hostvars
|
150
|
+
end.to_json
|
151
|
+
end
|
152
|
+
|
153
|
+
def to_ini
|
154
|
+
with_ini_lines.to_a.join("\n")
|
155
|
+
end
|
156
|
+
|
157
|
+
def with_ini_lines
|
158
|
+
return enum_for(__method__) unless block_given?
|
159
|
+
|
160
|
+
[with_ini_lines_hosts, with_ini_lines_groups].each do |e|
|
161
|
+
e.each { |line| yield line }
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def with_ini_lines_hosts
|
166
|
+
return enum_for(__method__) unless block_given?
|
167
|
+
hosts.each { |host| yield host.to_ini }
|
168
|
+
end
|
169
|
+
|
170
|
+
def with_ini_lines_groups
|
171
|
+
return enum_for(__method__) unless block_given?
|
172
|
+
|
173
|
+
to_h.tap { |h| h.delete('_') }.each do |group, entries|
|
174
|
+
yield "[#{group}]"
|
175
|
+
|
176
|
+
(entries.is_a?(Hash) ? entries.map { |entry, value| "#{entry}=#{value}" } : entries).each do |entry|
|
177
|
+
yield entry
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
private
|
183
|
+
|
184
|
+
def unset?(obj)
|
185
|
+
defined?(obj).nil? or obj.nil?
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module VagrantPlugins
|
3
|
+
module AnsibleAuto
|
4
|
+
class Plugin < Vagrant.plugin(2)
|
5
|
+
name 'ansible inventory'
|
6
|
+
|
7
|
+
config 'ansible' do
|
8
|
+
require_relative 'config'
|
9
|
+
Config
|
10
|
+
end
|
11
|
+
|
12
|
+
command 'ansible' do
|
13
|
+
require_relative 'command/root'
|
14
|
+
Command::Root
|
15
|
+
end
|
16
|
+
|
17
|
+
config('ansible_auto', :provisioner) do
|
18
|
+
require_relative 'config'
|
19
|
+
Config
|
20
|
+
end
|
21
|
+
|
22
|
+
provisioner 'ansible_auto' do
|
23
|
+
require_relative 'provisioner'
|
24
|
+
Provisioner
|
25
|
+
end
|
26
|
+
|
27
|
+
# Compatibility with Vagrantfiles from before name change to ansible_auto
|
28
|
+
config('ansible_inventory', :provisioner) do
|
29
|
+
require_relative 'config'
|
30
|
+
Config
|
31
|
+
end
|
32
|
+
|
33
|
+
provisioner 'ansible_inventory' do
|
34
|
+
require_relative 'provisioner'
|
35
|
+
Provisioner
|
36
|
+
end
|
37
|
+
|
38
|
+
guest_capability 'linux', :check_open_port do
|
39
|
+
require_relative 'cap/guest/posix/check_open_port'
|
40
|
+
Cap::Guest::POSIX::CheckOpenPort
|
41
|
+
end
|
42
|
+
|
43
|
+
guest_capability 'linux', :gateway_addresses do
|
44
|
+
require_relative 'cap/guest/posix/gateway_addresses'
|
45
|
+
Cap::Guest::POSIX::GatewayAddresses
|
46
|
+
end
|
47
|
+
|
48
|
+
guest_capability 'linux', :ssh_server_address do
|
49
|
+
require_relative 'cap/guest/posix/ssh_server_address'
|
50
|
+
Cap::Guest::POSIX::SSHServerAddress
|
51
|
+
end
|
52
|
+
|
53
|
+
guest_capability 'linux', :executable_installed? do
|
54
|
+
require_relative 'cap/guest/posix/executable_installed'
|
55
|
+
Cap::Guest::POSIX::ExecutableInstalled
|
56
|
+
end
|
57
|
+
|
58
|
+
guest_capability 'linux', :bash_installed? do
|
59
|
+
require_relative 'cap/guest/posix/bash_installed'
|
60
|
+
Cap::Guest::POSIX::BashInstalled
|
61
|
+
end
|
62
|
+
|
63
|
+
guest_capability 'linux', :generate_private_key do
|
64
|
+
require_relative 'cap/guest/posix/private_key'
|
65
|
+
Cap::Guest::POSIX::PrivateKey
|
66
|
+
end
|
67
|
+
|
68
|
+
guest_capability 'linux', :fetch_public_key do
|
69
|
+
require_relative 'cap/guest/posix/public_key'
|
70
|
+
Cap::Guest::POSIX::PrivateKey
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
require 'vagrant'
|
3
|
+
require Vagrant.source_root + 'plugins/provisioners/ansible/provisioner/guest'
|
4
|
+
require 'vagrant/util/keypair'
|
5
|
+
|
6
|
+
require 'vagrant/ansible_auto/util'
|
7
|
+
|
8
|
+
require 'log4r'
|
9
|
+
require 'shellwords'
|
10
|
+
|
11
|
+
module VagrantPlugins
|
12
|
+
module AnsibleAuto
|
13
|
+
class Provisioner < VagrantPlugins::Ansible::Provisioner::Guest
|
14
|
+
include Vagrant::Util::Retryable
|
15
|
+
include VagrantPlugins::AnsibleAuto::Util
|
16
|
+
|
17
|
+
def initialize(machine, config)
|
18
|
+
super
|
19
|
+
@logger = Log4r::Logger.new('vagrant::provisioners::ansible_auto')
|
20
|
+
end
|
21
|
+
|
22
|
+
def configure(root_config)
|
23
|
+
super
|
24
|
+
@__ansible_config = root_config.ansible
|
25
|
+
end
|
26
|
+
|
27
|
+
def provision
|
28
|
+
@config = @__ansible_config.merge(config)
|
29
|
+
|
30
|
+
remote_priv_key_path, _remote_pub_key_path, openssh = configure_keypair!
|
31
|
+
|
32
|
+
# TODO: figure out how to access ansible_auto configuration done
|
33
|
+
# on the `other' machine.
|
34
|
+
# @config = other.config.ansible.merge(merged_config)
|
35
|
+
if machine.guest.capability?(:ssh_server_address)
|
36
|
+
|
37
|
+
with_active_machines do |other, name, provider|
|
38
|
+
# We're dealing with the machine doing the provisining
|
39
|
+
if name == machine.name
|
40
|
+
other_hostvars = { connection: 'local' }
|
41
|
+
elsif other.nil?
|
42
|
+
machine.ui.warn "Machine #{name} is not configured for this environment; omitting it from the inventory"
|
43
|
+
else
|
44
|
+
# The machines we are trying to manage might not yet be ready to
|
45
|
+
# connect -- retry a configurable number of times/durations until
|
46
|
+
# we can connect; otherwise raise an exception.
|
47
|
+
private_key_paths = []
|
48
|
+
retryable(on: Vagrant::Errors::SSHNotReady, tries: @config.host_connect_tries, sleep: @config.host_connect_sleep) do
|
49
|
+
raise Vagrant::Errors::SSHNotReady unless other.communicate.ready? and !other.ssh_info.nil?
|
50
|
+
|
51
|
+
private_key_paths = other.ssh_info.fetch(:private_key_path, [])
|
52
|
+
raise Vagrant::Errors::SSHNotReady if private_key_paths.empty?
|
53
|
+
|
54
|
+
if other.config.ssh.insert_key
|
55
|
+
raise Vagrant::Errors::SSHNotReady unless private_key_paths.any? { |k| !insecure_key?(k) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
ssh_host, ssh_port = machine.guest.capability(:ssh_server_address, other)
|
60
|
+
other_hostvars = { ssh_host: ssh_host, ssh_port: ssh_port }
|
61
|
+
|
62
|
+
if private_key_paths.empty?
|
63
|
+
machine.ui.warn "No private keys available for machine #{name}; provisioner will likely fail"
|
64
|
+
end
|
65
|
+
|
66
|
+
source_priv_key_path = fetch_private_key(other)
|
67
|
+
|
68
|
+
if source_priv_key_path.nil?
|
69
|
+
machine.ui.warn "Private key for #{name} not available for upload; provisioner will likely fail"
|
70
|
+
else
|
71
|
+
machine.ui.info "Adding #{name} to Ansible inventory"
|
72
|
+
|
73
|
+
if other.guest.capability?(:insert_public_key)
|
74
|
+
other.guest.capability(:insert_public_key, openssh)
|
75
|
+
else
|
76
|
+
remote_priv_key_path = File.join(@config.tmp_path, 'ssh', name.to_s, provider.to_s, File.basename(source_priv_key_path))
|
77
|
+
create_and_chown_and_chmod_remote_file(source_priv_key_path, remote_priv_key_path)
|
78
|
+
end
|
79
|
+
|
80
|
+
other_hostvars[:ssh_private_key_file] = remote_priv_key_path
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
@config.inventory.add_host(other, other_hostvars || {})
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
super
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def configure_keypair!
|
94
|
+
# FIXME
|
95
|
+
remote_priv_key_path = "~#{machine.ssh_info[:username]}/.ssh/id_rsa"
|
96
|
+
remote_pub_key_path = "#{remote_priv_key_path}.pub"
|
97
|
+
|
98
|
+
# Check whether user has a private key already
|
99
|
+
if !machine.communicate.test("test -f #{remote_priv_key_path}") or !machine.communicate.test("test -f #{remote_pub_key_path}")
|
100
|
+
_pub, priv, openssh = Vagrant::Util::Keypair.create
|
101
|
+
write_and_chown_and_chmod_remote_file(priv, remote_priv_key_path)
|
102
|
+
write_and_chown_and_chmod_remote_file(openssh, remote_pub_key_path)
|
103
|
+
elsif machine.guest.capability?(:fetch_public_key)
|
104
|
+
openssh = machine.guest.capability(:fetch_public_key, remote_priv_key_path)
|
105
|
+
end
|
106
|
+
|
107
|
+
[remote_priv_key_path, remote_pub_key_path, openssh]
|
108
|
+
end
|
109
|
+
|
110
|
+
def handle_remote_file(to, _owner = machine.ssh_info[:username], mode = 0o600)
|
111
|
+
machine.communicate.tap do |comm|
|
112
|
+
create_and_chown_remote_folder(File.dirname(to))
|
113
|
+
|
114
|
+
yield comm, to
|
115
|
+
|
116
|
+
comm.sudo("chown -h #{machine.ssh_info[:username]} #{to}")
|
117
|
+
comm.sudo("chmod #{format('0%o', mode)} #{to}")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def create_and_chown_and_chmod_remote_file(from, to, mode = 0o600)
|
122
|
+
handle_remote_file(to, mode) do |comm, target|
|
123
|
+
comm.upload(from, target)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def write_and_chown_and_chmod_remote_file(contents, to, mode = 0o600)
|
128
|
+
handle_remote_file(to, mode) do |comm, _target|
|
129
|
+
contents = contents.strip << "\n"
|
130
|
+
|
131
|
+
to_parent = File.dirname(to)
|
132
|
+
|
133
|
+
remote_path = "/tmp/vagrant-temp-asset-#{Time.now.to_i}"
|
134
|
+
Tempfile.open("vagrant-temp-asset") do |f|
|
135
|
+
f.binmode
|
136
|
+
f.write(contents)
|
137
|
+
f.fsync
|
138
|
+
f.close
|
139
|
+
machine.ui.info("uploading #{f.path} to #{remote_path}")
|
140
|
+
comm.upload(f.path, remote_path)
|
141
|
+
end
|
142
|
+
|
143
|
+
# FIXME: configure perms on parent dir
|
144
|
+
comm.execute <<-EOH.gsub(/^ */, "")
|
145
|
+
mkdir #{to_parent}
|
146
|
+
mv #{remote_path} #{to}
|
147
|
+
EOH
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def generate_inventory_machines
|
152
|
+
if config.strict_host_key_checking
|
153
|
+
machine_format = '%s'
|
154
|
+
else
|
155
|
+
machine_format = "%s ansible_ssh_extra_args='-o UserKnownHostsFile=/dev/null -o IdentitiesOnly=yes -o StrictHostKeyChecking=no'"
|
156
|
+
end
|
157
|
+
|
158
|
+
config.inventory.with_ini_lines_hosts.map do |host_spec|
|
159
|
+
machine_format % host_spec
|
160
|
+
end.join("\n") + "\n"
|
161
|
+
end
|
162
|
+
|
163
|
+
def generate_inventory_groups
|
164
|
+
config.inventory.with_ini_lines_groups.to_a.join("\n") + "\n"
|
165
|
+
end
|
166
|
+
|
167
|
+
def with_active_machines
|
168
|
+
return enum_for(__method__) unless block_given?
|
169
|
+
|
170
|
+
machine.env.active_machines.each do |name, provider|
|
171
|
+
begin
|
172
|
+
yield machine.env.machine(name, provider), name, provider
|
173
|
+
rescue Vagrant::Errors::MachineNotFound, CommunicatorWinRM::Errors::WinRMNotReady => e
|
174
|
+
machine.ui.warn "unable to find machine #{name} (#{e.message})"
|
175
|
+
return nil, name, provider
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module VagrantPlugins
|
3
|
+
module AnsibleAuto
|
4
|
+
module Util
|
5
|
+
# Adapted from VagrantPlugins::CommunicatorSSH::Communicator#insecure_key?.
|
6
|
+
# This will test whether +path+ is the Vagrant insecure private key.
|
7
|
+
#
|
8
|
+
# @param [String] path
|
9
|
+
def insecure_key?(path)
|
10
|
+
return false if path.nil? or !File.file?(path)
|
11
|
+
@__insecure_key ||= Vagrant.source_root.join('keys/vagrant').read.chomp
|
12
|
+
File.read(path).chomp == @_insecure_key
|
13
|
+
end
|
14
|
+
|
15
|
+
def fetch_private_key(machine)
|
16
|
+
if machine.config.ssh.insert_key && !machine.ssh_info.nil?
|
17
|
+
machine.ssh_info.fetch(:private_key_path, []).find { |k| !insecure_key?(k) }
|
18
|
+
else
|
19
|
+
machine.env.default_private_key_path
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/playbooks/test.yml
ADDED