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 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
 
@@ -29,6 +29,7 @@ module ConfigBuilder
29
29
  def register(identifier, klass)
30
30
  if @klasses[identifier]
31
31
  raise DuplicateEntry, :registry => @name,
32
+ :identifier => identifier.inspect,
32
33
  :identifiers => @klasses.keys
33
34
  else
34
35
  @klasses[identifier] = klass
@@ -1,5 +1,6 @@
1
1
  module ConfigBuilder
2
2
  module Filter
3
3
  require 'config_builder/filter/roles'
4
+ require 'config_builder/filter/boxes'
4
5
  end
5
6
  end
@@ -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
- # >> hash_config
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
- def run(hash_config)
41
- @roles = hash_config.delete('roles')
40
+ # @!attribute [r] roles
41
+ # @return [Hash<String, Object>]
42
+ attr_reader :roles
42
43
 
43
- hash_config['vms'].map! { |vm_hash| filter_vm(vm_hash) }
44
-
45
- hash_config
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
- private
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 = roles_for_vm(role_list)
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 roles_for_vm(role_field)
100
+ def roles_by_name(field)
65
101
 
66
- case role_field
67
- when Array then names = role_field
68
- when String then names = [role_field]
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| role_definition(name) }
108
+ names.map { |name| role(name) }
73
109
  end
74
110
 
75
- def role_definition(name)
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.run(current_input)
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
- raise NotImplementedError, "Custom lists of filters not implemented."
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
- rv.merge!(contents)
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)
@@ -1,3 +1,3 @@
1
1
  module ConfigBuilder
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
@@ -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(input)
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(config)
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
- input = dup(config)
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(config)
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(config)
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(config)
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(config) }.to raise_error, /Couldn't find role named .*nope.*/
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.2.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-17 00:00:00.000000000 Z
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