vagrant-ansible_auto 0.1.5 → 0.2.1
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 +4 -4
- data/CHANGELOG.md +26 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +172 -0
- data/README.md +53 -12
- data/Rakefile +9 -7
- data/TODO.md +14 -0
- data/Vagrantfile +37 -15
- data/lib/vagrant/ansible_auto/cap/guest/posix/check_open_port.rb +22 -3
- data/lib/vagrant/ansible_auto/cap/guest/posix/executable_installed.rb +10 -2
- data/lib/vagrant/ansible_auto/cap/guest/posix/gateway_addresses.rb +8 -23
- data/lib/vagrant/ansible_auto/cap/guest/posix/private_key.rb +16 -1
- data/lib/vagrant/ansible_auto/cap/guest/posix/public_key.rb +18 -3
- data/lib/vagrant/ansible_auto/cap/guest/posix/ssh_server_address.rb +22 -12
- data/lib/vagrant/ansible_auto/cap/guest/posix.rb +16 -0
- data/lib/vagrant/ansible_auto/command/inventory.rb +37 -11
- data/lib/vagrant/ansible_auto/command/root.rb +34 -31
- data/lib/vagrant/ansible_auto/config.rb +74 -33
- data/lib/vagrant/ansible_auto/errors.rb +30 -1
- data/lib/vagrant/ansible_auto/host.rb +123 -34
- data/lib/vagrant/ansible_auto/inventory.rb +196 -34
- data/lib/vagrant/ansible_auto/plugin.rb +23 -8
- data/lib/vagrant/ansible_auto/provisioner.rb +121 -79
- data/lib/vagrant/ansible_auto/util/config.rb +61 -0
- data/lib/vagrant/ansible_auto/util/hash_with_indifferent_access.rb +58 -0
- data/lib/vagrant/ansible_auto/util/keys.rb +49 -0
- data/lib/vagrant/ansible_auto/util/shell_quote.rb +24 -0
- data/lib/vagrant/ansible_auto/version.rb +2 -1
- data/lib/vagrant/ansible_auto.rb +15 -0
- data/locales/en.yml +34 -0
- data/spec/spec_helper.rb +5 -85
- data/spec/support/context.rb +111 -0
- data/spec/support/matchers.rb +45 -0
- data/spec/unit/vagrant/ansible_auto/config_spec.rb +72 -0
- data/spec/unit/vagrant/ansible_auto/host_spec.rb +131 -0
- data/spec/unit/vagrant/ansible_auto/inventory_spec.rb +349 -0
- data/spec/unit/vagrant/ansible_auto/provisioner_spec.rb +248 -0
- data/spec/unit/vagrant/ansible_auto/util/config_spec.rb +63 -0
- data/spec/unit/vagrant/ansible_auto/util/keys_spec.rb +66 -0
- data/vagrant-ansible_auto.gemspec +6 -4
- data/vagrant-spec.config.rb +3 -0
- data/yard/extensions.rb +45 -0
- metadata +36 -11
- data/Vagrantfile2 +0 -4
- data/Vagrantfile3 +0 -8
- data/Vagrantfile4 +0 -31
- data/lib/vagrant/ansible_auto/cap/guest/posix/bash_installed.rb +0 -30
- data/lib/vagrant/ansible_auto/util.rb +0 -24
- data/spec/vagrant/ansible_auto/host_spec.rb +0 -43
- data/spec/vagrant/ansible_auto/inventory_spec.rb +0 -79
@@ -1,101 +1,178 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'set'
|
3
4
|
require 'json'
|
5
|
+
|
6
|
+
require 'vagrant/ansible_auto/errors'
|
4
7
|
require 'vagrant/ansible_auto/host'
|
8
|
+
require 'vagrant/ansible_auto/util/config'
|
9
|
+
require 'vagrant/ansible_auto/util/hash_with_indifferent_access'
|
5
10
|
|
6
11
|
module VagrantPlugins
|
7
12
|
module AnsibleAuto
|
13
|
+
# Class representing an Ansible inventory with hosts, groups, group
|
14
|
+
# children, and group variables
|
8
15
|
class Inventory
|
16
|
+
include VagrantPlugins::AnsibleAuto::Util::Config
|
17
|
+
|
18
|
+
UNNAMED_GROUP = '_'.freeze
|
19
|
+
|
20
|
+
# @return [Hash{String=>Set<Host>}] group names mapped to their members
|
9
21
|
def groups
|
10
|
-
|
22
|
+
if unset? @groups
|
23
|
+
@groups = Util::HashWithIndifferentAccess.new do |hash, key|
|
24
|
+
hash[key] = Set.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
11
28
|
@groups
|
12
29
|
end
|
13
30
|
|
31
|
+
# @return [Set<Host>] the hosts in the {Inventory}
|
14
32
|
def hosts
|
15
33
|
@hosts = Set.new if unset?(@hosts)
|
16
34
|
@hosts
|
17
35
|
end
|
18
36
|
|
37
|
+
# @return [Hash{String=>Hash}] group names mapped to their variables
|
19
38
|
def vars
|
20
|
-
|
39
|
+
if unset? @vars
|
40
|
+
@vars = Util::HashWithIndifferentAccess.new do |hash, key|
|
41
|
+
hash[key] = Util::HashWithIndifferentAccess.new
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
21
45
|
@vars
|
22
46
|
end
|
23
47
|
|
48
|
+
# @return [Hash{String=>Set}] group names mapped to their children
|
24
49
|
def children
|
25
|
-
|
50
|
+
if unset? @children
|
51
|
+
@children = Util::HashWithIndifferentAccess.new do |hash, key|
|
52
|
+
hash[key] = Set.new
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
26
56
|
@children
|
27
57
|
end
|
28
58
|
|
59
|
+
# Set the groups for the {Inventory}.
|
60
|
+
# @note overwrites the current {#groups}.
|
61
|
+
# @param [Hash{String=>Array,Hash}] new_groups the groups to assign to the
|
62
|
+
# {Inventory}
|
63
|
+
# @option new_groups [Array] group the hosts in +group+
|
64
|
+
# @option new_groups [Hash] group:vars the variables for +group+
|
65
|
+
# @option new_groups [Array] group:chilren the child groups for +group+
|
66
|
+
# @return [Hash{String=>Array,Hash}] the created groups
|
29
67
|
def groups=(new_groups)
|
30
68
|
@groups = nil
|
31
69
|
|
32
70
|
new_groups.each do |group_heading, entries|
|
33
|
-
group, type = group_heading
|
71
|
+
group, type = parse_group_heading(group_heading)
|
72
|
+
|
34
73
|
case type
|
35
74
|
when 'vars'
|
36
|
-
|
37
|
-
|
75
|
+
entries = {} if entries.nil?
|
76
|
+
vars_for(group, entries)
|
38
77
|
when 'children'
|
39
|
-
|
40
|
-
|
78
|
+
entries = [] if entries.nil?
|
79
|
+
children_of(group, *entries)
|
80
|
+
else
|
81
|
+
entries = [] if entries.nil?
|
82
|
+
if entries.is_a? Hash
|
83
|
+
add_complex_group(group, entries)
|
41
84
|
else
|
42
|
-
entries = [] if entries.nil?
|
43
85
|
add_group(group, *entries)
|
86
|
+
end
|
44
87
|
end
|
45
88
|
end
|
46
89
|
|
47
90
|
groups
|
48
91
|
end
|
49
92
|
|
50
|
-
|
93
|
+
# Set the hosts for the {Inventory}
|
94
|
+
# @note overwrites the current {#hosts}.
|
95
|
+
# @param [Hash{String=>Hash}] new_hosts the hosts in the inventory
|
96
|
+
# @option new_hosts [Hash{String=>Hash, nil}] host a host plus any hostvars
|
97
|
+
# @return [Hash{String=>Hash}] the created hosts
|
98
|
+
def hosts=(new_hosts)
|
51
99
|
@hosts = nil
|
52
100
|
|
53
|
-
|
54
|
-
hostvars
|
55
|
-
add_host(host, hostvars)
|
101
|
+
new_hosts.each do |host, hostvars|
|
102
|
+
add_host(host, hostvars || {})
|
56
103
|
end
|
57
104
|
|
58
105
|
hosts
|
59
106
|
end
|
60
107
|
|
108
|
+
# Set the variables for the groups in the {Inventory}
|
109
|
+
# @note overwrites the current {#vars}
|
110
|
+
# @param [Hash{String,Hash}] new_vars the variables to add to the
|
111
|
+
# {Inventory}
|
112
|
+
# @option new_vars [Hash{String,Hash}] group a group plus any group
|
113
|
+
# variables
|
114
|
+
# @return [Hash{String,Hash}] the created variables
|
61
115
|
def vars=(new_vars)
|
62
116
|
@vars = nil
|
63
117
|
|
64
|
-
new_vars.
|
118
|
+
new_vars.each do |group, group_vars|
|
65
119
|
vars_for(group, group_vars)
|
66
120
|
end
|
67
121
|
|
68
122
|
vars
|
69
123
|
end
|
70
124
|
|
125
|
+
# Set the children of the groups in the {Inventory}
|
126
|
+
# @note overwrites the currrent {#children}
|
127
|
+
# @param [Hash{String=>Array<String>}] new_children the group children to add to
|
128
|
+
# the {Inventory}
|
129
|
+
# @option new_children [Array<String>] group a group name and the list of
|
130
|
+
# its children
|
131
|
+
# @return [Hash{String=>Set<String>}] the created children
|
71
132
|
def children=(new_children)
|
72
133
|
@children = nil
|
73
134
|
|
74
|
-
new_children.
|
135
|
+
new_children.each do |group, group_children|
|
75
136
|
children_of(group, *group_children)
|
76
137
|
end
|
77
138
|
|
78
139
|
children
|
79
140
|
end
|
80
141
|
|
142
|
+
# Add a group to the {Inventory}
|
143
|
+
# @param [#to_s] group the name of the group
|
144
|
+
# @param [Array] members the hosts to add to the group
|
145
|
+
# @return [Set] the members of the added group
|
81
146
|
def add_group(group, *members)
|
147
|
+
raise InvalidGroupNameError, group: group if group.to_s == UNNAMED_GROUP
|
148
|
+
|
149
|
+
add_complex_group(group, members.pop) if members.last.is_a? Hash
|
150
|
+
|
82
151
|
groups[group.to_s].tap do |group_members|
|
83
152
|
group_members.merge(members)
|
84
153
|
return group_members
|
85
154
|
end
|
86
155
|
end
|
87
156
|
|
88
|
-
|
157
|
+
# Add a host to the {Inventory}
|
158
|
+
# @param [Host,String,Symbol,Vagrant::Machine] host the host to add
|
159
|
+
# @param [Hash] hostvars hostvars to assign to the host
|
160
|
+
def add_host(host, hostvars = nil)
|
89
161
|
hosts.add case host
|
90
162
|
when Host
|
91
|
-
host
|
163
|
+
host.tap { |h| h.hostvars = hostvars unless hostvars.nil? }
|
92
164
|
when String, Symbol
|
93
|
-
Host.new(host, hostvars)
|
165
|
+
Host.new(host, hostvars || {})
|
166
|
+
when Vagrant::Machine
|
167
|
+
HostMachine.new(host, hostvars || {})
|
94
168
|
else
|
95
|
-
|
169
|
+
raise Errors::InvalidHostTypeError, type: host.class.name
|
96
170
|
end
|
97
171
|
end
|
98
172
|
|
173
|
+
# Assign variables to a group
|
174
|
+
# @param [#to_s] group the name of the group
|
175
|
+
# @param [Hash] new_vars the variables to assign to the group
|
99
176
|
def vars_for(group, new_vars = {})
|
100
177
|
vars[group.to_s].tap do |group_vars|
|
101
178
|
group_vars.merge!(new_vars)
|
@@ -103,6 +180,9 @@ module VagrantPlugins
|
|
103
180
|
end
|
104
181
|
end
|
105
182
|
|
183
|
+
# Assign child groups to a group
|
184
|
+
# @param [#to_s] group the name of the group
|
185
|
+
# @param [Array] new_children the child groups to assign to the group
|
106
186
|
def children_of(group, *new_children)
|
107
187
|
children[group.to_s].tap do |group_children|
|
108
188
|
group_children.merge(new_children.map(&:to_s))
|
@@ -110,7 +190,12 @@ module VagrantPlugins
|
|
110
190
|
end
|
111
191
|
end
|
112
192
|
|
193
|
+
# Perform in-place merge of two {Inventory} instances
|
194
|
+
# @param [Inventory] other the inventory to merge into this one
|
195
|
+
# @return [self] the updated inventory
|
113
196
|
def merge!(other)
|
197
|
+
hosts.merge(other.hosts)
|
198
|
+
|
114
199
|
@groups = groups.merge(other.groups) do |_group, group_members, other_group_members|
|
115
200
|
group_members.merge(other_group_members)
|
116
201
|
end
|
@@ -126,34 +211,69 @@ module VagrantPlugins
|
|
126
211
|
self
|
127
212
|
end
|
128
213
|
|
214
|
+
# Merge two {Inventory} instances
|
215
|
+
# @param [Inventory] other the inventory to merge into this one
|
216
|
+
# @return [Inventory] the updated inventory
|
129
217
|
def merge(other)
|
130
218
|
clone.merge!(other)
|
131
219
|
end
|
132
220
|
|
221
|
+
# @return [Hash{String=>Hash}] the merged hostvars for all hosts in the
|
222
|
+
# inventory
|
133
223
|
def hostvars
|
134
|
-
hosts.
|
224
|
+
Hash[hosts.map { |h| [h.name, h.hostvars] }]
|
135
225
|
end
|
136
226
|
|
227
|
+
# A representation of an {Inventory} as a +Hash+
|
228
|
+
# @note the hosts in the inventory will be returned as +Hash+es under the
|
229
|
+
# key {UNNAMED_GROUP}
|
230
|
+
# @return [Hash{String=>Hash,Array}] a +Hash+ containing the hosts in the
|
231
|
+
# inventory (coerced to hashes) under the {UNNAMED_GROUP} key, as well
|
232
|
+
# as each group name mapped to a subhashes with hosts under the key
|
233
|
+
# +"hosts"+, variables under the key +"vars"+, and children under the
|
234
|
+
# key +"children"+
|
137
235
|
def to_h
|
138
|
-
{}.tap do |h|
|
139
|
-
h
|
140
|
-
|
141
|
-
|
142
|
-
|
236
|
+
Hash.new { |h, k| h[k] = {} }.tap do |h|
|
237
|
+
h[UNNAMED_GROUP] = hosts.map(&:to_h)
|
238
|
+
|
239
|
+
groups.each do |group, group_hosts|
|
240
|
+
h[group]['hosts'] = group_hosts.to_a
|
241
|
+
end
|
242
|
+
|
243
|
+
vars.each do |group, group_vars|
|
244
|
+
h[group]['vars'] = group_vars
|
245
|
+
end
|
246
|
+
|
247
|
+
children.each do |group, group_children|
|
248
|
+
h[group]['children'] = group_children.to_a
|
249
|
+
end
|
143
250
|
end
|
144
251
|
end
|
145
252
|
|
146
|
-
|
253
|
+
# @return [String] the {Inventory} represented as a JSON object in the
|
254
|
+
# form of a "Dynamic Inventory"
|
255
|
+
# @see http://docs.ansible.com/ansible/intro_dynamic_inventory.html
|
256
|
+
def to_json(*args)
|
147
257
|
to_h.tap do |h|
|
148
|
-
h.delete(
|
149
|
-
h['_meta'] = hostvars
|
150
|
-
end.to_json
|
258
|
+
h.delete(UNNAMED_GROUP)
|
259
|
+
h['_meta'] = { 'hostvars' => hostvars }
|
260
|
+
end.to_json(*args)
|
151
261
|
end
|
152
262
|
|
263
|
+
# Return the {Inventory} as an INI document
|
264
|
+
# @return [String] the inventory in a newline-separated string
|
153
265
|
def to_ini
|
154
266
|
with_ini_lines.to_a.join("\n")
|
155
267
|
end
|
156
268
|
|
269
|
+
# Iterate over the lines of the {Inventory} represented as an INI
|
270
|
+
# document
|
271
|
+
# @overload
|
272
|
+
# @return [Enumerator] the lines of the INI document
|
273
|
+
# @overload
|
274
|
+
# @yieldparam [String] each line in the INI document
|
275
|
+
# @see with_ini_lines_hosts
|
276
|
+
# @see with_ini_lines_groups
|
157
277
|
def with_ini_lines
|
158
278
|
return enum_for(__method__) unless block_given?
|
159
279
|
|
@@ -162,27 +282,69 @@ module VagrantPlugins
|
|
162
282
|
end
|
163
283
|
end
|
164
284
|
|
285
|
+
# Iterate over the hosts in the {Inventory} represented as an INI
|
286
|
+
# document
|
287
|
+
# @overload
|
288
|
+
# @return [Enumerator] the lines of the INI document
|
289
|
+
# @overload
|
290
|
+
# @yieldparam [String] each line in the INI document
|
165
291
|
def with_ini_lines_hosts
|
166
292
|
return enum_for(__method__) unless block_given?
|
167
293
|
hosts.each { |host| yield host.to_ini }
|
168
294
|
end
|
169
295
|
|
296
|
+
# Iterate over the groups in the {Inventory} represented as an INI
|
297
|
+
# document
|
298
|
+
# @overload
|
299
|
+
# @return [Enumerator] the lines of the INI document
|
300
|
+
# @overload
|
301
|
+
# @yieldparam [String] each line in the INI document
|
170
302
|
def with_ini_lines_groups
|
171
303
|
return enum_for(__method__) unless block_given?
|
172
304
|
|
173
|
-
to_h.tap { |h| h.delete(
|
305
|
+
to_h.tap { |h| h.delete(UNNAMED_GROUP) }.sort.each do |group, entries|
|
174
306
|
yield "[#{group}]"
|
175
307
|
|
176
|
-
|
177
|
-
|
308
|
+
entries.fetch('hosts', []).sort.each { |h| yield h }
|
309
|
+
|
310
|
+
if entries.key? 'children'
|
311
|
+
yield "[#{group}:children]"
|
312
|
+
entries['children'].sort.each { |c| yield c }
|
313
|
+
end
|
314
|
+
|
315
|
+
if entries.key? 'vars'
|
316
|
+
yield "[#{group}:vars]"
|
317
|
+
entries['vars'].sort.each { |k, v| yield "#{k} = #{v}" }
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
|
322
|
+
# A sanity check of the inventory's state
|
323
|
+
# @return [void]
|
324
|
+
# @raise [Errors::GroupMissingChildError] when a group has a child group
|
325
|
+
# that doesn't exist
|
326
|
+
def validate!
|
327
|
+
children.each do |group, group_children|
|
328
|
+
group_children.each do |child|
|
329
|
+
raise Errors::GroupMissingChildError, group: group, child: child unless groups.key? child
|
178
330
|
end
|
179
331
|
end
|
180
332
|
end
|
181
333
|
|
182
334
|
private
|
183
335
|
|
184
|
-
def
|
185
|
-
|
336
|
+
def parse_group_heading(group_heading)
|
337
|
+
group_elts = group_heading.to_s.split(/(?<!\\):/)
|
338
|
+
type = group_elts.length > 1 && %w[vars children].include?(group_elts.last) ? group_elts.pop.chomp.strip : nil
|
339
|
+
group = group_elts.join(':').chomp.strip
|
340
|
+
[group, type]
|
341
|
+
end
|
342
|
+
|
343
|
+
def add_complex_group(group, group_spec = {})
|
344
|
+
group_spec = Util::HashWithIndifferentAccess.new(group_spec)
|
345
|
+
vars_for(group, group_spec['vars']) if group_spec.key? 'vars'
|
346
|
+
children_of(group, *(group_spec['children'])) if group_spec.key? 'children'
|
347
|
+
add_group(group, *(group_spec['hosts'])) if group_spec.key? 'hosts'
|
186
348
|
end
|
187
349
|
end
|
188
350
|
end
|
@@ -1,8 +1,17 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Namespace for Vagrant plugins
|
2
4
|
module VagrantPlugins
|
5
|
+
# Namespace for the +ansible_auto+ provisioner and +ansible+ command
|
3
6
|
module AnsibleAuto
|
7
|
+
# Vagrant plugin class for the +ansible_auto+ provisioner and +ansible+
|
8
|
+
# command
|
4
9
|
class Plugin < Vagrant.plugin(2)
|
5
|
-
name 'ansible
|
10
|
+
name 'ansible auto'
|
11
|
+
description <<-DESC
|
12
|
+
Automatically generate Ansible inventories for use when running Ansible
|
13
|
+
on guest machines
|
14
|
+
DESC
|
6
15
|
|
7
16
|
config 'ansible' do
|
8
17
|
require_relative 'config'
|
@@ -35,7 +44,7 @@ module VagrantPlugins
|
|
35
44
|
Provisioner
|
36
45
|
end
|
37
46
|
|
38
|
-
guest_capability 'linux', :
|
47
|
+
guest_capability 'linux', :port_open? do
|
39
48
|
require_relative 'cap/guest/posix/check_open_port'
|
40
49
|
Cap::Guest::POSIX::CheckOpenPort
|
41
50
|
end
|
@@ -55,11 +64,6 @@ module VagrantPlugins
|
|
55
64
|
Cap::Guest::POSIX::ExecutableInstalled
|
56
65
|
end
|
57
66
|
|
58
|
-
guest_capability 'linux', :bash_installed? do
|
59
|
-
require_relative 'cap/guest/posix/bash_installed'
|
60
|
-
Cap::Guest::POSIX::BashInstalled
|
61
|
-
end
|
62
|
-
|
63
67
|
guest_capability 'linux', :generate_private_key do
|
64
68
|
require_relative 'cap/guest/posix/private_key'
|
65
69
|
Cap::Guest::POSIX::PrivateKey
|
@@ -67,7 +71,18 @@ module VagrantPlugins
|
|
67
71
|
|
68
72
|
guest_capability 'linux', :fetch_public_key do
|
69
73
|
require_relative 'cap/guest/posix/public_key'
|
70
|
-
Cap::Guest::POSIX::
|
74
|
+
Cap::Guest::POSIX::PublicKey
|
75
|
+
end
|
76
|
+
|
77
|
+
guest_capability 'linux', :authorized_key? do
|
78
|
+
require_relative 'cap/guest/posix/public_key'
|
79
|
+
Cap::Guest::POSIX::PublicKey
|
80
|
+
end
|
81
|
+
|
82
|
+
action_hook 'environment_plugins_loaded' do
|
83
|
+
require 'i18n'
|
84
|
+
I18n.load_path << VagrantPlugins::AnsibleAuto.source_root.join('locales/en.yml')
|
85
|
+
I18n.reload!
|
71
86
|
end
|
72
87
|
end
|
73
88
|
end
|