vagrant-config_builder 0.2.0 → 0.3.0
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.
- data/CHANGELOG +17 -0
- data/lib/config_builder/class_registry.rb +1 -0
- data/lib/config_builder/filter.rb +1 -0
- data/lib/config_builder/filter/boxes.rb +22 -0
- data/lib/config_builder/filter/roles.rb +50 -20
- data/lib/config_builder/filter_stack.rb +9 -3
- data/lib/config_builder/loader/yaml.rb +6 -1
- data/lib/config_builder/model/vm.rb +5 -0
- data/lib/config_builder/version.rb +1 -1
- data/spec/config_builder/filter/boxes_spec.rb +87 -0
- data/spec/config_builder/filter/roles_spec.rb +35 -8
- metadata +4 -2
data/CHANGELOG
CHANGED
@@ -1,6 +1,23 @@
|
|
1
1
|
CHANGELOG
|
2
2
|
=========
|
3
3
|
|
4
|
+
0.3.0
|
5
|
+
-----
|
6
|
+
|
7
|
+
This is a backwards compatible bugfix and feature release
|
8
|
+
|
9
|
+
### User notes
|
10
|
+
|
11
|
+
#### Enhancements
|
12
|
+
|
13
|
+
* (GH-6) New filter: `boxes`
|
14
|
+
* box_url is now a supported vm attribute
|
15
|
+
|
16
|
+
#### Bugfixes
|
17
|
+
|
18
|
+
* Better error handling when no configuration is set
|
19
|
+
* Add missing variable when raising ClassRegistry::DuplicateEntry error
|
20
|
+
|
4
21
|
0.2.0
|
5
22
|
-----
|
6
23
|
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class ConfigBuilder::Filter::Boxes
|
2
|
+
|
3
|
+
attr_reader :boxes
|
4
|
+
|
5
|
+
def set_config(root_config)
|
6
|
+
@root_config = root_config
|
7
|
+
@boxes = (@root_config.delete('boxes') || {})
|
8
|
+
end
|
9
|
+
|
10
|
+
def run
|
11
|
+
return @root_config if @root_config['vms'].nil?
|
12
|
+
|
13
|
+
@root_config['vms'].each { |vm_hash| filter_vm(vm_hash) }
|
14
|
+
@root_config
|
15
|
+
end
|
16
|
+
|
17
|
+
def filter_vm(vm_hash)
|
18
|
+
if (box_name = vm_hash['box'])
|
19
|
+
vm_hash['box_url'] ||= @boxes[box_name]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -12,7 +12,7 @@
|
|
12
12
|
# the order of declaration of roles does not matter.
|
13
13
|
#
|
14
14
|
# @example
|
15
|
-
# >>
|
15
|
+
# >> run()
|
16
16
|
# => {
|
17
17
|
# 'roles' => {
|
18
18
|
# 'webserver' => {
|
@@ -37,19 +37,29 @@
|
|
37
37
|
#
|
38
38
|
class ConfigBuilder::Filter::Roles
|
39
39
|
|
40
|
-
|
41
|
-
|
40
|
+
# @!attribute [r] roles
|
41
|
+
# @return [Hash<String, Object>]
|
42
|
+
attr_reader :roles
|
42
43
|
|
43
|
-
|
44
|
-
|
45
|
-
|
44
|
+
def set_config(root_config)
|
45
|
+
@root_config = root_config
|
46
|
+
@roles = @root_config.delete('roles')
|
47
|
+
@vms = @root_config.delete('vms')
|
46
48
|
end
|
47
49
|
|
48
|
-
|
50
|
+
def run
|
51
|
+
return @root_config if @vms.nil?
|
49
52
|
|
53
|
+
@root_config['vms'] = @vms.map { |vm_hash| filter_vm(vm_hash) }
|
54
|
+
@root_config
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param vm_hash [Hash]
|
58
|
+
#
|
59
|
+
# @return [Hash] The filtered VM
|
50
60
|
def filter_vm(old_vm)
|
51
61
|
role_list = old_vm.delete('roles')
|
52
|
-
node_stack =
|
62
|
+
node_stack = roles_by_name(role_list)
|
53
63
|
|
54
64
|
node_stack << old_vm
|
55
65
|
|
@@ -60,25 +70,45 @@ class ConfigBuilder::Filter::Roles
|
|
60
70
|
new_vm
|
61
71
|
end
|
62
72
|
|
73
|
+
# Fetch the role associated with the given name
|
74
|
+
#
|
75
|
+
# @param role_name [String]
|
76
|
+
#
|
77
|
+
# @return [Hash<String, Object>]
|
78
|
+
def role(name)
|
79
|
+
if (retval = @roles[name])
|
80
|
+
retval
|
81
|
+
else
|
82
|
+
raise ArgumentError, "Requested role #{name.inspect} is not defined, available roles: #{@roles.keys}."
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @overload roles_by_name(name)
|
87
|
+
# @param name [String] A single role name
|
88
|
+
# @return [Array<Hash>] An array containing the requested role
|
89
|
+
#
|
90
|
+
# @overload roles_by_name(names)
|
91
|
+
# @param names [Array<String>] A list of role names
|
92
|
+
# @return [Array<Hash>] An array containing all of the requested roles in the
|
93
|
+
# order requested.
|
94
|
+
#
|
95
|
+
# @overload roles_by_name(nothing)
|
96
|
+
# @param nothing [NilClass] nil
|
97
|
+
# @return [Array<>] An empty array
|
98
|
+
#
|
63
99
|
# @return [Array]
|
64
|
-
def
|
100
|
+
def roles_by_name(field)
|
65
101
|
|
66
|
-
case
|
67
|
-
when Array then names =
|
68
|
-
when String then names = [
|
102
|
+
case field
|
103
|
+
when Array then names = field
|
104
|
+
when String then names = [field]
|
69
105
|
when NilClass then names = []
|
70
106
|
end
|
71
107
|
|
72
|
-
names.map { |name|
|
108
|
+
names.map { |name| role(name) }
|
73
109
|
end
|
74
110
|
|
75
|
-
|
76
|
-
if (defn = @roles[name])
|
77
|
-
defn
|
78
|
-
else
|
79
|
-
raise "Couldn't find role named #{name.inspect} in roles #{@roles.keys.inspect}"
|
80
|
-
end
|
81
|
-
end
|
111
|
+
private
|
82
112
|
|
83
113
|
# Merge two node hash structures, with values in `right` overwriting values
|
84
114
|
# in `left`.
|
@@ -13,18 +13,24 @@ module ConfigBuilder
|
|
13
13
|
def filter(input)
|
14
14
|
set_filters(input.delete(:filters))
|
15
15
|
|
16
|
-
@filter_stack.inject(input) do |current_input, filter|
|
17
|
-
filter.
|
16
|
+
output = @filter_stack.inject(input) do |current_input, filter|
|
17
|
+
filter.set_config(current_input)
|
18
|
+
filter.run
|
18
19
|
end
|
20
|
+
|
21
|
+
output
|
19
22
|
end
|
20
23
|
|
21
24
|
private
|
22
25
|
|
26
|
+
# @note The implementation of this method is not final, use at your own peril.
|
27
|
+
# @api private
|
23
28
|
def set_filters(list)
|
24
29
|
if list.nil?
|
25
30
|
@filter_stack << ConfigBuilder::Filter::Roles.new
|
31
|
+
@filter_stack << ConfigBuilder::Filter::Boxes.new
|
26
32
|
else
|
27
|
-
|
33
|
+
@filter_stack = list
|
28
34
|
end
|
29
35
|
end
|
30
36
|
end
|
@@ -13,7 +13,12 @@ class ConfigBuilder::Loader::YAML
|
|
13
13
|
rv = {}
|
14
14
|
Dir.glob(glob_path).each do |file|
|
15
15
|
contents = ::YAML.load_file(file)
|
16
|
-
|
16
|
+
|
17
|
+
if contents.is_a? Hash
|
18
|
+
rv.merge! contents
|
19
|
+
else
|
20
|
+
# TODO warn on non-hash YAML
|
21
|
+
end
|
17
22
|
end
|
18
23
|
|
19
24
|
rv
|
@@ -66,6 +66,10 @@ class ConfigBuilder::Model::VM < ConfigBuilder::Model::Base
|
|
66
66
|
# @return [String] The name of the Vagrant box to instantiate for this VM
|
67
67
|
def_model_attribute :box
|
68
68
|
|
69
|
+
# @!attribute [rw] box_url
|
70
|
+
# @return [String] The source URL for the Vagrant box associated with this VM
|
71
|
+
def_model_attribute :box
|
72
|
+
|
69
73
|
# @!attribute [rw] name
|
70
74
|
# @return [String] The name of the instantiated box in this environment
|
71
75
|
def_model_attribute :name
|
@@ -89,6 +93,7 @@ class ConfigBuilder::Model::VM < ConfigBuilder::Model::Base
|
|
89
93
|
vm_config = config.vm
|
90
94
|
|
91
95
|
vm_config.box = attr(:box) if defined? attr(:box)
|
96
|
+
vm_config.box_url = attr(:box_url) if defined? attr(:box_url)
|
92
97
|
vm_config.hostname = attr(:hostname) if defined? attr(:hostname)
|
93
98
|
|
94
99
|
eval_models(vm_config)
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigBuilder::Filter::Boxes do
|
4
|
+
|
5
|
+
def dup(o)
|
6
|
+
Marshal.load(Marshal.dump(o))
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:boxes) do
|
10
|
+
{
|
11
|
+
'first_box' => 'http://box_host/first_box.box',
|
12
|
+
'second_box' => 'http://box_host/second_box.box',
|
13
|
+
'third_box' => 'http://box_host/third_box.box',
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let(:vms) do
|
18
|
+
[
|
19
|
+
{'name' => 'one', 'box' => 'first_box'},
|
20
|
+
{'name' => 'two', 'box' => 'second_box'},
|
21
|
+
{'name' => 'four', 'box' => 'fourth_box'},
|
22
|
+
{
|
23
|
+
'name' => 'five',
|
24
|
+
'box' => 'fifth_box',
|
25
|
+
'box_url' => 'https://another_box_host/fifth_box.box',
|
26
|
+
},
|
27
|
+
]
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'without a boxes key' do
|
31
|
+
let(:config) do
|
32
|
+
{
|
33
|
+
'vms' => vms,
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
before { subject.set_config(config) }
|
38
|
+
|
39
|
+
it "doesn't modify any boxes" do
|
40
|
+
input = dup(config)
|
41
|
+
output = subject.run
|
42
|
+
expect(output).to eq config
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe 'when the boxes key is given' do
|
47
|
+
let(:config) do
|
48
|
+
{
|
49
|
+
'boxes' => boxes,
|
50
|
+
'vms' => vms,
|
51
|
+
}
|
52
|
+
end
|
53
|
+
|
54
|
+
before { subject.set_config(config) }
|
55
|
+
|
56
|
+
it "removes the 'boxes' key" do
|
57
|
+
output = subject.run
|
58
|
+
expect(output).to_not have_key 'boxes'
|
59
|
+
end
|
60
|
+
|
61
|
+
it "adds the 'box_url' to VMs whose 'box' value is in the 'boxes' list" do
|
62
|
+
output = subject.run
|
63
|
+
vms = output['vms']
|
64
|
+
|
65
|
+
expect(vms[0]['box_url']).to eq 'http://box_host/first_box.box'
|
66
|
+
expect(vms[1]['box_url']).to eq 'http://box_host/second_box.box'
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "if the VM 'box' value doesn't have a match in the box list" do
|
70
|
+
it "doesn't modify the 'box_url'" do
|
71
|
+
output = subject.run
|
72
|
+
vms = output['vms']
|
73
|
+
|
74
|
+
expect(vms[2]['box_url']).to be_nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
describe "if the VM 'box_url' is already set" do
|
79
|
+
it "doesn't modify the 'box_url'" do
|
80
|
+
output = subject.run
|
81
|
+
vms = output['vms']
|
82
|
+
|
83
|
+
expect(vms[3]['box_url']).to eq 'https://another_box_host/fifth_box.box'
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -53,9 +53,13 @@ describe ConfigBuilder::Filter::Roles do
|
|
53
53
|
{'vms' => vms}
|
54
54
|
end
|
55
55
|
|
56
|
+
before do
|
57
|
+
subject.set_config(dup(config))
|
58
|
+
end
|
59
|
+
|
56
60
|
it "doesn't alter the structure" do
|
57
61
|
input = dup(config)
|
58
|
-
output = subject.run
|
62
|
+
output = subject.run
|
59
63
|
|
60
64
|
expect(output).to eq config
|
61
65
|
end
|
@@ -69,8 +73,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
69
73
|
}
|
70
74
|
end
|
71
75
|
|
76
|
+
before do
|
77
|
+
subject.set_config(dup(config))
|
78
|
+
end
|
79
|
+
|
72
80
|
it 'strips out the roles key' do
|
73
|
-
output = subject.run
|
81
|
+
output = subject.run
|
74
82
|
expect(output).to_not have_key 'roles'
|
75
83
|
end
|
76
84
|
end
|
@@ -85,9 +93,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
85
93
|
}
|
86
94
|
end
|
87
95
|
|
96
|
+
before do
|
97
|
+
subject.set_config(dup(config))
|
98
|
+
end
|
99
|
+
|
88
100
|
it "doesn't alter the vm" do
|
89
|
-
|
90
|
-
output = subject.run(input)
|
101
|
+
output = subject.run
|
91
102
|
expect(output['vms']).to eq vms
|
92
103
|
end
|
93
104
|
end
|
@@ -103,8 +114,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
103
114
|
}
|
104
115
|
end
|
105
116
|
|
117
|
+
before do
|
118
|
+
subject.set_config(dup(config))
|
119
|
+
end
|
120
|
+
|
106
121
|
let(:filtered_vm) do
|
107
|
-
output = subject.run
|
122
|
+
output = subject.run
|
108
123
|
output['vms'][0]
|
109
124
|
end
|
110
125
|
|
@@ -137,8 +152,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
137
152
|
}
|
138
153
|
end
|
139
154
|
|
155
|
+
before do
|
156
|
+
subject.set_config(dup(config))
|
157
|
+
end
|
158
|
+
|
140
159
|
let(:filtered_vm) do
|
141
|
-
output = subject.run
|
160
|
+
output = subject.run
|
142
161
|
output['vms'][0]
|
143
162
|
end
|
144
163
|
|
@@ -180,8 +199,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
180
199
|
}
|
181
200
|
end
|
182
201
|
|
202
|
+
before do
|
203
|
+
subject.set_config(dup(config))
|
204
|
+
end
|
205
|
+
|
183
206
|
let(:filtered_vms) do
|
184
|
-
output = subject.run
|
207
|
+
output = subject.run
|
185
208
|
output['vms']
|
186
209
|
end
|
187
210
|
|
@@ -237,8 +260,12 @@ describe ConfigBuilder::Filter::Roles do
|
|
237
260
|
'roles' => {'yep' => {'box' => 'moxxi'}}
|
238
261
|
}
|
239
262
|
|
263
|
+
before do
|
264
|
+
subject.set_config(dup(config))
|
265
|
+
end
|
266
|
+
|
240
267
|
it 'raises an error' do
|
241
|
-
expect { subject.run
|
268
|
+
expect { subject.run }.to raise_error, /Couldn't find role named .*nope.*/
|
242
269
|
end
|
243
270
|
end
|
244
271
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vagrant-config_builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-08-
|
12
|
+
date: 2013-08-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- lib/config_builder/class_registry.rb
|
45
45
|
- lib/config_builder/extension_handler.rb
|
46
46
|
- lib/config_builder/filter.rb
|
47
|
+
- lib/config_builder/filter/boxes.rb
|
47
48
|
- lib/config_builder/filter/roles.rb
|
48
49
|
- lib/config_builder/filter_stack.rb
|
49
50
|
- lib/config_builder/loader.rb
|
@@ -65,6 +66,7 @@ files:
|
|
65
66
|
- lib/config_builder/runner.rb
|
66
67
|
- lib/config_builder/version.rb
|
67
68
|
- lib/vagrant-config_builder.rb
|
69
|
+
- spec/config_builder/filter/boxes_spec.rb
|
68
70
|
- spec/config_builder/filter/roles_spec.rb
|
69
71
|
- spec/spec_helper.rb
|
70
72
|
- templates/locales/en.yml
|