motherbrain 0.14.4 → 0.14.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/Gemfile +1 -1
- data/lib/mb/berkshelf.rb +31 -0
- data/lib/mb/bootstrap/manager.rb +3 -3
- data/lib/mb/cli/sub_command/plugin.rb +16 -6
- data/lib/mb/group.rb +2 -2
- data/lib/mb/node_querier.rb +1 -10
- data/lib/mb/plugin.rb +20 -7
- data/lib/mb/upgrade/worker.rb +1 -1
- data/lib/mb/version.rb +1 -1
- data/lib/motherbrain.rb +1 -0
- data/motherbrain.gemspec +1 -0
- data/spec/fixtures/myface-0.1.0/Berksfile.lock +3 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/unit/mb/berkshelf_spec.rb +17 -0
- data/spec/unit/mb/bootstrap/manager_spec.rb +12 -1
- data/spec/unit/mb/group_spec.rb +3 -3
- data/spec/unit/mb/plugin_spec.rb +4 -0
- data/spec/unit/mb/upgrade/worker_spec.rb +11 -1
- metadata +18 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 45f24209faef88c327c3979ebdf59cdc961bf530
|
4
|
+
data.tar.gz: 49f3bbdb3c81b052aa3a1eddfdc1256427818653
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e50ad349193026c2bd4c221e6ec3e9a78729c6dc1304bfe130a6f0be20d2011d3f480f708926a3cb73410790e833b98b9da2aec831d881948ab1ad3d23273145
|
7
|
+
data.tar.gz: e32e2999bbfb6157237bfffd0a3fc1320f0bd1ce4164ee35960fd6c0b3046ceb77b490d538f31e53aa2d5fbf5638227d297fa98a46d2b803f47f4179d14ec466
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/lib/mb/berkshelf.rb
CHANGED
@@ -46,5 +46,36 @@ module MotherBrain
|
|
46
46
|
Pathname.new(Application.config.berkshelf.path || default_path)
|
47
47
|
end
|
48
48
|
end
|
49
|
+
|
50
|
+
# A wrapper around the berkshelf's Berkshelf::Lockfile
|
51
|
+
class Lockfile
|
52
|
+
include MB::Logging
|
53
|
+
|
54
|
+
BERKSFILE_LOCK = 'Berksfile.lock'.freeze
|
55
|
+
|
56
|
+
class << self
|
57
|
+
def from_path(root_path)
|
58
|
+
new(File.join(root_path, BERKSFILE_LOCK))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :berksfile_lock
|
63
|
+
|
64
|
+
def initialize(berksfile_lock_path)
|
65
|
+
@berksfile_lock = ::Berkshelf::Lockfile.from_file(berksfile_lock_path)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Return a hash of all of the cookbook versions found in the Berksfile.lock
|
69
|
+
# The key is the name of the cookbook and the value is the version as a
|
70
|
+
# String. If there is no lockfile an empty hash is returned.
|
71
|
+
#
|
72
|
+
# @return [Hash]
|
73
|
+
def locked_versions
|
74
|
+
berksfile_lock.graph.locks.inject({}) do |hash, (name, dependency)|
|
75
|
+
hash[name] = dependency.locked_version.to_s
|
76
|
+
hash
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
49
80
|
end
|
50
81
|
end
|
data/lib/mb/bootstrap/manager.rb
CHANGED
@@ -76,7 +76,6 @@ module MotherBrain
|
|
76
76
|
# @see {#async_bootstrap} for options
|
77
77
|
def bootstrap(job, environment, manifest, plugin, options = {})
|
78
78
|
options = options.reverse_merge(
|
79
|
-
cookbook_versions: Hash.new,
|
80
79
|
component_versions: Hash.new,
|
81
80
|
environment_attributes: Hash.new,
|
82
81
|
hints: Hash.new,
|
@@ -104,9 +103,10 @@ module MotherBrain
|
|
104
103
|
set_component_versions(environment, plugin, options[:component_versions])
|
105
104
|
end
|
106
105
|
|
107
|
-
|
106
|
+
cookbook_versions = options[:cookbook_versions] || plugin.cookbook_versions
|
107
|
+
if cookbook_versions.any?
|
108
108
|
job.set_status("Setting cookbook versions")
|
109
|
-
set_cookbook_versions(environment,
|
109
|
+
set_cookbook_versions(environment, cookbook_versions)
|
110
110
|
end
|
111
111
|
|
112
112
|
if options[:environment_attributes].any?
|
@@ -61,6 +61,7 @@ module MotherBrain
|
|
61
61
|
aliases: "--components"
|
62
62
|
method_option :cookbook_versions,
|
63
63
|
type: :hash,
|
64
|
+
hidden: true,
|
64
65
|
desc: "The cookbook versions to set on the environment",
|
65
66
|
aliases: "--cookbooks"
|
66
67
|
method_option :environment_attributes,
|
@@ -84,6 +85,8 @@ module MotherBrain
|
|
84
85
|
boot_options = Hash.new.merge(options).deep_symbolize_keys
|
85
86
|
manifest = MB::Bootstrap::Manifest.from_file(manifest_file)
|
86
87
|
|
88
|
+
cookbooks_option_deprecated(options)
|
89
|
+
|
87
90
|
job = bootstrapper.async_bootstrap(
|
88
91
|
environment.freeze,
|
89
92
|
manifest.freeze,
|
@@ -103,6 +106,7 @@ module MotherBrain
|
|
103
106
|
aliases: "--components"
|
104
107
|
method_option :cookbook_versions,
|
105
108
|
type: :hash,
|
109
|
+
hidden: true,
|
106
110
|
desc: "The cookbook versions to set on the environment",
|
107
111
|
aliases: "--cookbooks"
|
108
112
|
method_option :environment_attributes,
|
@@ -129,6 +133,8 @@ module MotherBrain
|
|
129
133
|
prov_options = Hash.new.merge(options).deep_symbolize_keys
|
130
134
|
manifest = Provisioner::Manifest.from_file(manifest_file)
|
131
135
|
|
136
|
+
cookbooks_option_deprecated(options)
|
137
|
+
|
132
138
|
job = provisioner.async_provision(
|
133
139
|
environment.freeze,
|
134
140
|
manifest.freeze,
|
@@ -170,6 +176,7 @@ module MotherBrain
|
|
170
176
|
aliases: "--components"
|
171
177
|
method_option :cookbook_versions,
|
172
178
|
type: :hash,
|
179
|
+
hide: true,
|
173
180
|
desc: "The cookbook versions to set on the environment",
|
174
181
|
aliases: "--cookbooks"
|
175
182
|
method_option :environment_attributes,
|
@@ -196,12 +203,7 @@ module MotherBrain
|
|
196
203
|
define_method(:upgrade) do
|
197
204
|
upgrade_options = Hash.new.merge(options).deep_symbolize_keys
|
198
205
|
|
199
|
-
|
200
|
-
:component_versions,
|
201
|
-
:cookbook_versions,
|
202
|
-
:environment_attributes,
|
203
|
-
:environment_attributes_file
|
204
|
-
]
|
206
|
+
cookbooks_option_deprecated(options)
|
205
207
|
|
206
208
|
job = upgrade_manager.async_upgrade(
|
207
209
|
environment.freeze,
|
@@ -220,6 +222,14 @@ module MotherBrain
|
|
220
222
|
ui.say plugin.metadata.attributes.to_yaml
|
221
223
|
end
|
222
224
|
end
|
225
|
+
|
226
|
+
no_commands do
|
227
|
+
def cookbooks_option_deprecated(options)
|
228
|
+
if options[:cookbook_versions]
|
229
|
+
ui.deprecated "--cookbooks option is deprecated in favor of loading versions from Berksfile.lock"
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
223
233
|
end
|
224
234
|
|
225
235
|
klass
|
data/lib/mb/group.rb
CHANGED
@@ -57,8 +57,8 @@ module MotherBrain
|
|
57
57
|
"#{attribute_escape(key)}:#{value}"
|
58
58
|
end
|
59
59
|
|
60
|
-
items += roles.collect { |role| "
|
61
|
-
items += recipes.collect { |recipe| "
|
60
|
+
items += roles.collect { |role| "run_list:#{solr_escape('role['+role+']')}" }
|
61
|
+
items += recipes.collect { |recipe| "run_list:#{solr_escape('recipe['+recipe+']')}" }
|
62
62
|
|
63
63
|
items.join(' AND ')
|
64
64
|
end
|
data/lib/mb/node_querier.rb
CHANGED
@@ -50,7 +50,7 @@ module MotherBrain
|
|
50
50
|
node_failures_count = 0
|
51
51
|
node_failures = Array.new
|
52
52
|
|
53
|
-
futures = nodes.map { |node| node_querier.future(:chef_run, node.public_hostname,
|
53
|
+
futures = nodes.map { |node| node_querier.future(:chef_run, node.public_hostname, override_recipes: override_recipes) }
|
54
54
|
|
55
55
|
futures.each do |future|
|
56
56
|
begin
|
@@ -125,21 +125,12 @@ module MotherBrain
|
|
125
125
|
end
|
126
126
|
|
127
127
|
response = if options[:override_recipes]
|
128
|
-
node = options[:node_object]
|
129
|
-
node.reload
|
130
|
-
old_recipes = node.automatic_attributes.recipes
|
131
128
|
override_recipes = options[:override_recipes]
|
132
129
|
|
133
130
|
cmd_recipe_syntax = override_recipes.join(',') { |recipe| "recipe[#{recipe}]" }
|
134
131
|
log.info { "Running Chef client with override runlist '#{cmd_recipe_syntax}' on: #{host}" }
|
135
132
|
chef_run_response = chef_connection.node.execute_command(host, "chef-client --override-runlist #{cmd_recipe_syntax}")
|
136
133
|
|
137
|
-
# reset the run list
|
138
|
-
node.reload
|
139
|
-
log.info { "Resetting node's recipes attribute back to #{old_recipes}" }
|
140
|
-
node.automatic_attributes.recipes = old_recipes
|
141
|
-
node.save
|
142
|
-
|
143
134
|
chef_run_response
|
144
135
|
else
|
145
136
|
log.info { "Running Chef client on: #{host}" }
|
data/lib/mb/plugin.rb
CHANGED
@@ -4,18 +4,24 @@ module MotherBrain
|
|
4
4
|
# Create a new plugin instance from the given content
|
5
5
|
#
|
6
6
|
# @param [MB::CookbookMetadata] metadata
|
7
|
+
# @param [Hash<String, String>] cookbook_versions
|
8
|
+
# The cookbook dependencies which this plugin depends on. Key is
|
9
|
+
# the cookbook name and the value is the version of the cookbook.
|
7
10
|
#
|
8
11
|
# @raise [PluginLoadError]
|
9
12
|
#
|
10
13
|
# @yieldreturn [MotherBrain::Plugin]
|
11
|
-
def load(metadata, &block)
|
12
|
-
new(metadata, &block).validate!
|
14
|
+
def load(metadata, cookbook_versions = {}, &block)
|
15
|
+
new(metadata, cookbook_versions, &block).validate!
|
13
16
|
rescue PluginSyntaxError => ex
|
14
17
|
ErrorHandler.wrap(ex)
|
15
18
|
end
|
16
19
|
|
17
20
|
# Load the contents of a directory into an instance of MB::Plugin
|
18
21
|
#
|
22
|
+
# The cookbook dependencies of this plugin will be loaded from the
|
23
|
+
# Berksfile.lock if it is found.
|
24
|
+
#
|
19
25
|
# @param [#to_s] path
|
20
26
|
# a path to a directory containing a motherbrain plugin file and cookbook
|
21
27
|
# metadata file
|
@@ -31,8 +37,9 @@ module MotherBrain
|
|
31
37
|
plugin_filename = File.join(path, PLUGIN_FILENAME)
|
32
38
|
plugin_contents = File.read(plugin_filename)
|
33
39
|
metadata = CookbookMetadata.from_path(path)
|
40
|
+
berksfile_lock = Berkshelf::Lockfile.from_path(path)
|
34
41
|
|
35
|
-
load(metadata) { eval(plugin_contents, binding, plugin_filename, 1) }
|
42
|
+
load(metadata, berksfile_lock.locked_versions) { eval(plugin_contents, binding, plugin_filename, 1) }
|
36
43
|
rescue PluginSyntaxError => ex
|
37
44
|
raise PluginSyntaxError, ErrorHandler.new(ex, file_path: plugin_filename).message
|
38
45
|
end
|
@@ -58,6 +65,8 @@ module MotherBrain
|
|
58
65
|
attr_reader :components
|
59
66
|
# @return [Set<MB::Command>]
|
60
67
|
attr_reader :commands
|
68
|
+
# @return [Hash<String, String>]
|
69
|
+
attr_reader :cookbook_versions
|
61
70
|
|
62
71
|
def_delegator :metadata, :name
|
63
72
|
def_delegator :metadata, :maintainer
|
@@ -68,10 +77,14 @@ module MotherBrain
|
|
68
77
|
def_delegator :metadata, :version
|
69
78
|
|
70
79
|
# @param [MB::CookbookMetadata] metadata
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
80
|
+
# @param [Hash<String, String>] cookbook_versions
|
81
|
+
# The cookbook dependencies which this plugin depends on. Key is
|
82
|
+
# the cookbook name and the value is the version of the cookbook.
|
83
|
+
def initialize(metadata, cookbook_versions = {}, &block)
|
84
|
+
@metadata = metadata
|
85
|
+
@cookbook_versions = cookbook_versions
|
86
|
+
@components = Set.new
|
87
|
+
@commands = Set.new
|
75
88
|
|
76
89
|
if block_given?
|
77
90
|
dsl_eval(&block)
|
data/lib/mb/upgrade/worker.rb
CHANGED
data/lib/mb/version.rb
CHANGED
data/lib/motherbrain.rb
CHANGED
data/motherbrain.gemspec
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -13,6 +13,7 @@ require 'motherbrain'
|
|
13
13
|
require 'chef_zero/server'
|
14
14
|
|
15
15
|
def setup_rspec
|
16
|
+
require File.expand_path('../../spec/support/berkshelf.rb', __FILE__)
|
16
17
|
Dir[File.join(File.expand_path("../../spec/support/**/*.rb", __FILE__))].each { |f| require f }
|
17
18
|
|
18
19
|
RSpec.configure do |config|
|
@@ -35,4 +35,21 @@ describe MB::Berkshelf do
|
|
35
35
|
subject.should be_a(Pathname)
|
36
36
|
end
|
37
37
|
end
|
38
|
+
|
39
|
+
describe MB::Berkshelf::Lockfile do
|
40
|
+
describe "#locked_versions" do
|
41
|
+
|
42
|
+
let(:plugin_path) { '/foo' }
|
43
|
+
subject { MB::Berkshelf::Lockfile.from_path(plugin_path) }
|
44
|
+
|
45
|
+
context "when there is no lockfile present" do
|
46
|
+
its(:locked_versions) { should == {} }
|
47
|
+
end
|
48
|
+
|
49
|
+
context "when there is a lockfile present" do
|
50
|
+
let(:plugin_path) { fixtures_path.join('myface-0.1.0') }
|
51
|
+
its(:locked_versions) { should == {'cookbook1' => '2.0.1', 'cookbook2' => '1.0.13'}}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
38
55
|
end
|
@@ -8,8 +8,10 @@ describe MB::Bootstrap::Manager do
|
|
8
8
|
MB::CookbookMetadata.from_file(fixtures_path.join('cb_metadata.rb'))
|
9
9
|
}
|
10
10
|
|
11
|
+
let(:cookbook_versions) { {} }
|
12
|
+
|
11
13
|
let(:plugin) {
|
12
|
-
MB::Plugin.new(cookbook_metadata) do
|
14
|
+
MB::Plugin.new(cookbook_metadata, cookbook_versions) do
|
13
15
|
component "activemq" do
|
14
16
|
group "master"
|
15
17
|
group "slave"
|
@@ -132,6 +134,15 @@ describe MB::Bootstrap::Manager do
|
|
132
134
|
end
|
133
135
|
end
|
134
136
|
|
137
|
+
context "when the plugin has cookbook version dependencies set" do
|
138
|
+
let(:cookbook_versions) { {'cookbook1' => '1.2.3', 'cookbook2' => '4.5.6'} }
|
139
|
+
|
140
|
+
it "should set the cookbook versions on the environment" do
|
141
|
+
manager.should_receive(:set_cookbook_versions).with(environment, cookbook_versions)
|
142
|
+
run
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
135
146
|
context "when :environment_attributes_file is passed as an option" do
|
136
147
|
let(:filepath) { double }
|
137
148
|
|
data/spec/unit/mb/group_spec.rb
CHANGED
@@ -189,7 +189,7 @@ describe MB::Group do
|
|
189
189
|
end
|
190
190
|
|
191
191
|
it "returns them escaped and joined together by AND" do
|
192
|
-
expect(subject).to eql("chef_environment:#{environment} AND
|
192
|
+
expect(subject).to eql("chef_environment:#{environment} AND run_list:recipe\\[pvpnet\\:\\:default\\] AND run_list:recipe\\[pvpnet\\:\\:database\\]")
|
193
193
|
end
|
194
194
|
end
|
195
195
|
|
@@ -201,7 +201,7 @@ describe MB::Group do
|
|
201
201
|
end
|
202
202
|
|
203
203
|
it "does not escape the dash" do
|
204
|
-
expect(subject).to eql("chef_environment:#{environment} AND
|
204
|
+
expect(subject).to eql("chef_environment:#{environment} AND run_list:recipe\\[build-essential\\]")
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
@@ -214,7 +214,7 @@ describe MB::Group do
|
|
214
214
|
end
|
215
215
|
|
216
216
|
it "returns them escaped and joined together by AND" do
|
217
|
-
expect(subject).to eql("chef_environment:#{environment} AND
|
217
|
+
expect(subject).to eql("chef_environment:#{environment} AND run_list:role\\[app_server\\] AND run_list:role\\[database_server\\]")
|
218
218
|
end
|
219
219
|
end
|
220
220
|
end
|
data/spec/unit/mb/plugin_spec.rb
CHANGED
@@ -107,6 +107,10 @@ describe MB::Plugin do
|
|
107
107
|
it "returns a MB::Plugin from the given directory" do
|
108
108
|
subject.should be_a(MB::Plugin)
|
109
109
|
end
|
110
|
+
|
111
|
+
it "sets the cookbook_versions from the Berksfile.lock" do
|
112
|
+
subject.cookbook_versions.should == {'cookbook1' => '2.0.1', 'cookbook2' => '1.0.13'}
|
113
|
+
end
|
110
114
|
end
|
111
115
|
end
|
112
116
|
|
@@ -15,7 +15,8 @@ describe MB::Upgrade::Worker do
|
|
15
15
|
let(:job) { job_double }
|
16
16
|
let(:options) { Hash.new }
|
17
17
|
let(:nodes) { %w[node1 node2 node3] }
|
18
|
-
let(:
|
18
|
+
let(:locked_versions) { {} }
|
19
|
+
let(:plugin) { double MB::Plugin, name: plugin_name, cookbook_versions: locked_versions }
|
19
20
|
let(:plugin_name) { "plugin_name" }
|
20
21
|
|
21
22
|
before do
|
@@ -61,6 +62,15 @@ describe MB::Upgrade::Worker do
|
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
65
|
+
context "when cookbooks are found in the Berksfile.lock" do
|
66
|
+
let(:locked_versions) { {'foo' => '1.2.3', 'bar' => '4.5.6'} }
|
67
|
+
it "updates the cookbook versions from the lockfile" do
|
68
|
+
worker.should_receive(:set_cookbook_versions).with(environment_name, locked_versions)
|
69
|
+
run
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
64
74
|
context "when only cookbook_versions is passed as an option" do
|
65
75
|
before do
|
66
76
|
options[:cookbook_versions] = cookbook_versions
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motherbrain
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.14.
|
4
|
+
version: 0.14.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jamie Winsor
|
@@ -15,7 +15,7 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date: 2014-03-
|
18
|
+
date: 2014-03-25 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: celluloid
|
@@ -283,6 +283,20 @@ dependencies:
|
|
283
283
|
- - ~>
|
284
284
|
- !ruby/object:Gem::Version
|
285
285
|
version: 0.6.0
|
286
|
+
- !ruby/object:Gem::Dependency
|
287
|
+
name: berkshelf
|
288
|
+
requirement: !ruby/object:Gem::Requirement
|
289
|
+
requirements:
|
290
|
+
- - ~>
|
291
|
+
- !ruby/object:Gem::Version
|
292
|
+
version: 3.0.0.beta7
|
293
|
+
type: :runtime
|
294
|
+
prerelease: false
|
295
|
+
version_requirements: !ruby/object:Gem::Requirement
|
296
|
+
requirements:
|
297
|
+
- - ~>
|
298
|
+
- !ruby/object:Gem::Version
|
299
|
+
version: 3.0.0.beta7
|
286
300
|
description: An orchestrator for Chef
|
287
301
|
email:
|
288
302
|
- jamie@vialstudios.com
|
@@ -459,6 +473,7 @@ files:
|
|
459
473
|
- spec/fixtures/cb_metadata.rb
|
460
474
|
- spec/fixtures/fake_id_rsa
|
461
475
|
- spec/fixtures/fake_key.pem
|
476
|
+
- spec/fixtures/myface-0.1.0/Berksfile.lock
|
462
477
|
- spec/fixtures/myface-0.1.0/metadata.rb
|
463
478
|
- spec/fixtures/myface-0.1.0/motherbrain.rb
|
464
479
|
- spec/fixtures/test_env.json
|
@@ -607,6 +622,7 @@ test_files:
|
|
607
622
|
- spec/fixtures/cb_metadata.rb
|
608
623
|
- spec/fixtures/fake_id_rsa
|
609
624
|
- spec/fixtures/fake_key.pem
|
625
|
+
- spec/fixtures/myface-0.1.0/Berksfile.lock
|
610
626
|
- spec/fixtures/myface-0.1.0/metadata.rb
|
611
627
|
- spec/fixtures/myface-0.1.0/motherbrain.rb
|
612
628
|
- spec/fixtures/test_env.json
|