soloist 0.9.7 → 1.0.0.pre

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.
@@ -1,80 +0,0 @@
1
- require 'yaml'
2
-
3
- module Soloist
4
- class Soloist::ChefConfigGenerator
5
- include Soloist::Util
6
-
7
- def initialize(config, relative_path_to_soloistrc)
8
- @recipes = []
9
- @cookbook_paths = []
10
- @cookbook_gems = []
11
- @preserved_environment_variables = %w{PATH BUNDLE_PATH GEM_HOME GEM_PATH RAILS_ENV RACK_ENV}
12
- @node_attributes = config['node_attributes'] || {}
13
- merge_config(config, relative_path_to_soloistrc)
14
- end
15
-
16
- attr_reader :preserved_environment_variables, :cookbook_paths, :cookbook_gems
17
- attr_accessor :recipes
18
-
19
- def support_old_format(hash)
20
- hash['recipes'] ||= hash.delete('Recipes')
21
- hash['cookbook_paths'] ||= hash.delete('Cookbook_Paths')
22
- hash
23
- end
24
-
25
- def append_path(paths, relative_path_to_soloistrc)
26
- paths.map do |path|
27
- path.slice(0,1) == '/' ? path : "#{FileUtils.pwd}/#{relative_path_to_soloistrc}/#{path}"
28
- end
29
- end
30
-
31
- def merge_config(sub_hash, relative_path_to_soloistrc)
32
- sub_hash = support_old_format(sub_hash)
33
- if sub_hash["recipes"]
34
- @recipes = (@recipes + sub_hash["recipes"]).uniq
35
- end
36
- if sub_hash["cookbook_paths"]
37
- @cookbook_paths = (@cookbook_paths + append_path(sub_hash["cookbook_paths"], relative_path_to_soloistrc)).uniq
38
- end
39
- if sub_hash["cookbook_gems"]
40
- (@cookbook_gems += sub_hash["cookbook_gems"]).uniq!
41
- end
42
- if sub_hash["env_variable_switches"]
43
- merge_env_variable_switches(sub_hash["env_variable_switches"], relative_path_to_soloistrc)
44
- end
45
- end
46
-
47
- def merge_env_variable_switches(hash_to_merge, relative_path_to_soloistrc)
48
- hash_to_merge.keys.each do |variable|
49
- @preserved_environment_variables << variable
50
- ENV[variable] && ENV[variable].split(',').each do |env_variable_value|
51
- sub_hash = hash_to_merge[variable] && hash_to_merge[variable][env_variable_value]
52
- merge_config(sub_hash, relative_path_to_soloistrc) if sub_hash
53
- end
54
- end
55
- end
56
-
57
- def solo_rb
58
- linker = CookbookGemLinker.new(cookbook_gems)
59
- linker.link_gem_cookbooks
60
- "cookbook_path #{(cookbook_paths+[linker.cookbook_gem_temp_dir]).inspect}"
61
- end
62
-
63
- def json_hash
64
- {
65
- "recipes" => @recipes
66
- }.merge(@node_attributes)
67
- end
68
-
69
- def json_file
70
- json_hash.to_json
71
- end
72
-
73
- def preserved_environment_variables_string
74
- variable_array = []
75
- preserved_environment_variables.map do |env_variable|
76
- "#{env_variable}=#{ENV[env_variable]}" unless ENV[env_variable].nil?
77
- end.compact.join(" ")
78
- end
79
- end
80
- end
@@ -1,54 +0,0 @@
1
- class CookbookGemLinker
2
- include Soloist::Util
3
- attr_reader :gems_and_dependencies
4
- def initialize(gems=[])
5
- @gems = gems
6
- end
7
-
8
- def link_gem_cookbooks
9
- gems_and_dependencies.each do |gem_cookbook|
10
- link_cookbook(gem_cookbook)
11
- end
12
- end
13
-
14
- def gems_and_dependencies
15
- unless @gems_and_dependencies
16
- @gems_and_dependencies = Set.new
17
- calculate_gems_and_dependencies
18
- end
19
- @gems_and_dependencies
20
- end
21
-
22
- def cookbook_gem_temp_dir
23
- @cookbook_gem_temp_dir ||= Dir.mktmpdir
24
- end
25
-
26
- def path_to(gem_name)
27
- require gem_name
28
- path = Kernel.const_get(camelize(gem_name)).const_get('COOKBOOK_PATH')
29
- end
30
-
31
- def link_cookbook(gem_name)
32
- File.symlink(path_to(gem_name), File.join(cookbook_gem_temp_dir, gem_name.chomp("_cookbook")))
33
- end
34
-
35
- private
36
-
37
- def dependencies_of(gem_name)
38
- if Gem::Specification.respond_to?(:find_by_name)
39
- Gem::Specification.find_by_name(gem_name)
40
- else
41
- Gem.searcher.find(gem_name)
42
- end.dependencies.map(&:name)
43
- end
44
-
45
- def calculate_gems_and_dependencies(gems=@gems)
46
- gems.each do |gem_cookbook|
47
- @gems_and_dependencies.add(gem_cookbook)
48
- dependencies_of(gem_cookbook).each do |dependency|
49
- @gems_and_dependencies.add(dependency)
50
- calculate_gems_and_dependencies([dependency])
51
- end
52
- end
53
- end
54
- end
data/lib/soloist/util.rb DELETED
@@ -1,42 +0,0 @@
1
- module Soloist
2
- module Util
3
- def with_or_without_dot(file_name)
4
- [file_name, ".#{file_name}"]
5
- end
6
-
7
- def fileify(contents)
8
- file = Tempfile.new("soloist")
9
- puts "==== Temp File Contents ====\n#{contents}" if ENV['LOG_LEVEL'] == 'debug'
10
- file << contents
11
- file.flush
12
- file
13
- end
14
-
15
- def walk_up_and_find_file(filenames, opts={})
16
- pwd = FileUtils.pwd
17
- file = nil
18
- path_to_file = ""
19
- while !file && FileUtils.pwd != '/'
20
- file = filenames.detect { |f| File.exists?(f) }
21
- FileUtils.cd("..")
22
- path_to_file << "../" unless file
23
- end
24
- FileUtils.cd(pwd)
25
- if file
26
- file_contents = File.read(path_to_file + file) if file
27
- [file_contents, path_to_file]
28
- elsif opts[:required] == false
29
- [nil, nil]
30
- else
31
- raise Errno::ENOENT, "#{filenames.join(" or ")} not found" unless file || opts[:required] == false
32
- end
33
- end
34
-
35
- # stolen from activesupport
36
- def camelize(term)
37
- string = term.to_s
38
- string = string.sub(/^[a-z\d]*/) { $&.capitalize }
39
- string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
40
- end
41
- end
42
- end
@@ -1,252 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Soloist::ChefConfigGenerator do
4
- describe "generation" do
5
- before do
6
- @config = <<-CONFIG
7
- Cookbook_Paths:
8
- - ./chef/cookbooks/
9
- cookbook_gems:
10
- - pivotal_workstation_cookbook
11
- Recipes:
12
- - pivotal_workstation::ack
13
- CONFIG
14
- @config = YAML.load(@config)
15
- FileUtils.stub(:pwd).and_return("/current/working/directory")
16
- @generator = Soloist::ChefConfigGenerator.new(@config, "../..")
17
- mock_gem("pivotal_workstation_cookbook")
18
- end
19
-
20
- it "appends the current path and relative path to the cookbooks directory" do
21
- @generator.cookbook_paths.should == ["/current/working/directory/../.././chef/cookbooks/"]
22
- end
23
-
24
- it "does not append if an absolute path is given" do
25
- @config['cookbook_paths'] = ["/foo/bar"]
26
- @generator = Soloist::ChefConfigGenerator.new(@config, "../..")
27
- @generator.cookbook_paths.should == ["/foo/bar"]
28
- end
29
-
30
- describe ".solo_rb" do
31
- it "can generate a solo.rb contents" do
32
- @generator.solo_rb.should =~ %r{cookbook_path \["/current/working/directory/../.././chef/cookbooks/"}
33
- end
34
-
35
- it "should include a tempdir with pivotal_workstation in it" do
36
- @generator.solo_rb.match(%r{cookbook_path \[".*", "(.*)"\]})
37
- File.exist?("#{$1}/pivotal_workstation").should be
38
- end
39
- end
40
-
41
- it "can generate the json contents" do
42
- @generator.json_hash.should == {
43
- "recipes" => ['pivotal_workstation::ack']
44
- }
45
- end
46
-
47
- it "can generate json files" do
48
- JSON.parse(@generator.json_file).should == {
49
- "recipes" => ['pivotal_workstation::ack']
50
- }
51
- end
52
-
53
- describe "passing env variables to chef-solo through sudo" do
54
- it "has a list of env variables which are passed through" do
55
- @generator.preserved_environment_variables.should == %w{PATH BUNDLE_PATH GEM_HOME GEM_PATH RAILS_ENV RACK_ENV}
56
- end
57
-
58
- it "can generate an env_variable_string which is passed through sudo to chef-solo" do
59
- ENV["FOO"]="BAR"
60
- ENV["FAZ"]="FUZ"
61
- @generator.stub!(:preserved_environment_variables).and_return(["FOO", "FAZ"])
62
- @generator.preserved_environment_variables_string.should == "FOO=BAR FAZ=FUZ"
63
- end
64
-
65
- it "adds any environment variables that are switched in the config" do
66
- @config = <<-CONFIG
67
- cookbook_paths:
68
- - ./chef/cookbooks/
69
- recipes:
70
- - pivotal_workstation::ack
71
- env_variable_switches:
72
- ME_TOO:
73
- development:
74
- cookbook_paths:
75
- - ./chef/dev_cookbooks/
76
- recipes:
77
- - pivotal_dev::foo
78
- CONFIG
79
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
80
- @generator.preserved_environment_variables.should =~ %w{PATH BUNDLE_PATH GEM_HOME GEM_PATH RAILS_ENV RACK_ENV ME_TOO}
81
- end
82
- end
83
- end
84
-
85
- describe "yaml config values" do
86
- before do
87
- FileUtils.stub(:pwd).and_return("/")
88
- end
89
-
90
- it "accepts Cookbook_Paths, because the CamelSnake is a typo that must be supported" do
91
- @config = "Cookbook_Paths:\n- ./chef/cookbooks/\n"
92
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "..")
93
- @generator.cookbook_paths.should == ["//.././chef/cookbooks/"]
94
- end
95
-
96
- it "accepts cookbook_paths, because it is sane" do
97
- @config = "cookbook_paths:\n- ./chef/cookbooks/\n"
98
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "..")
99
- @generator.cookbook_paths.should == ["//.././chef/cookbooks/"]
100
- end
101
-
102
- it "accepts Recipes, because that's the way it was" do
103
- @config = "Recipes:\n- pivotal_workstation::ack"
104
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
105
- @generator.json_hash.should == { "recipes" => ["pivotal_workstation::ack"]}
106
- end
107
-
108
- it "accepts recipes, because it's snake now" do
109
- @config = "recipes:\n- pivotal_workstation::ack"
110
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
111
- @generator.json_hash.should == { "recipes" => ["pivotal_workstation::ack"]}
112
- end
113
-
114
- it "should set node attributes" do
115
- @config = "node_attributes:\n github_username: avh4"
116
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
117
- @generator.json_hash.should == { "recipes" => [], "github_username" => "avh4" }
118
- end
119
- end
120
-
121
- describe "environment variable merging" do
122
- before do
123
- FileUtils.stub(:pwd).and_return("/")
124
- end
125
-
126
- it "merges in if the variable is set to the the value" do
127
- @config = <<-CONFIG
128
- cookbook_paths:
129
- - ./chef/cookbooks/
130
- recipes:
131
- - pivotal_workstation::ack
132
- env_variable_switches:
133
- RACK_ENV:
134
- development:
135
- cookbook_paths:
136
- - ./chef/dev_cookbooks/
137
- recipes:
138
- - pivotal_dev::foo
139
- CONFIG
140
- ENV["RACK_ENV"]="development"
141
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
142
- @generator.cookbook_paths.should == [
143
- "//../.././chef/cookbooks/",
144
- "//../.././chef/dev_cookbooks/"
145
- ]
146
- @generator.json_hash["recipes"].should == [
147
- "pivotal_workstation::ack",
148
- "pivotal_dev::foo"
149
- ]
150
- end
151
-
152
- it "merges cookbook_gems" do
153
- @config = <<-CONFIG
154
- cookbook_gems:
155
- - pivotal_shared
156
- env_variable_switches:
157
- RACK_ENV:
158
- development:
159
- cookbook_gems:
160
- - pivotal_shared
161
- - pivotal_workstation
162
- CONFIG
163
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
164
- @generator.cookbook_gems.should =~ [
165
- "pivotal_shared",
166
- "pivotal_workstation"
167
- ]
168
- end
169
-
170
- it "splits the value on comma and applies all matching" do
171
- ENV["ROLES"]="application,database"
172
- @config = <<-CONFIG
173
- cookbook_paths:
174
- - ./chef/cookbooks/
175
- recipes:
176
- - pivotal_workstation::ack
177
- env_variable_switches:
178
- ROLES:
179
- application:
180
- cookbook_paths:
181
- - ./chef/app_cookbooks/
182
- recipes:
183
- - pivotal_app::application
184
- database:
185
- cookbook_paths:
186
- - ./chef/db_cookbooks/
187
- recipes:
188
- - pivotal_db::database
189
- CONFIG
190
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
191
- @generator.cookbook_paths.should =~ [
192
- "//../.././chef/cookbooks/",
193
- "//../.././chef/app_cookbooks/",
194
- "//../.././chef/db_cookbooks/"
195
- ]
196
- @generator.json_hash["recipes"].should =~ [
197
- "pivotal_workstation::ack",
198
- "pivotal_app::application",
199
- "pivotal_db::database",
200
- ]
201
- end
202
-
203
- it "can deal with empty env switched variables, and passes them through" do
204
- config = <<-CONFIG
205
- env_variable_switches:
206
- RACK_ENV:
207
- CONFIG
208
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
209
- @generator.preserved_environment_variables.should include("RACK_ENV")
210
- end
211
-
212
-
213
- it "can deal with only having environment switched recipes/cookbooks" do
214
- config = <<-CONFIG
215
- env_variable_switches:
216
- RACK_ENV:
217
- development:
218
- cookbook_paths:
219
- - ./chef/development_cookbooks/
220
- recipes:
221
- - pivotal_development::foo
222
- CONFIG
223
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
224
- @generator.cookbook_paths.should == [
225
- "//../.././chef/development_cookbooks/"
226
- ]
227
- @generator.json_hash["recipes"].should == [
228
- "pivotal_development::foo"
229
- ]
230
- end
231
- it "can deal with only having empty recipes/cookbooks" do
232
- config = <<-CONFIG
233
- cookbook_paths:
234
- recipes:
235
- env_variable_switches:
236
- RACK_ENV:
237
- development:
238
- cookbook_paths:
239
- - ./chef/development_cookbooks/
240
- recipes:
241
- - pivotal_development::foo
242
- CONFIG
243
- @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
244
- @generator.cookbook_paths.should == [
245
- "//../.././chef/development_cookbooks/"
246
- ]
247
- @generator.json_hash["recipes"].should == [
248
- "pivotal_development::foo"
249
- ]
250
- end
251
- end
252
- end
@@ -1,64 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe CookbookGemLinker do
4
- let(:linker) { CookbookGemLinker.new(["pivotal_workstation_cookbook"]) }
5
-
6
- describe ".cookbook_gem_temp_dir" do
7
- it "returns a tmpdir" do
8
- Dir.should_receive(:mktmpdir).once.and_return("/tmp/foo")
9
- 2.times { linker.cookbook_gem_temp_dir.should == "/tmp/foo" }
10
- end
11
- end
12
-
13
- describe ".path_to" do
14
- it "returns the path to the gem" do
15
- linker.path_to("pivotal_workstation_cookbook").should == File.expand_path('../..', __FILE__)
16
- end
17
- end
18
-
19
- describe ".link_cookbook" do
20
- it "creates a symbolic link in the tempdir" do
21
- linker.link_cookbook("pivotal_workstation_cookbook")
22
- File.exist?(File.expand_path('pivotal_workstation', linker.cookbook_gem_temp_dir)).should be
23
- end
24
- end
25
-
26
- describe '.gems_and_dependencies' do
27
- it "returns what you pass in dependencies" do
28
- mock_gem("pivotal_workstation_cookbook")
29
-
30
- linker.gems_and_dependencies.to_a.should == ["pivotal_workstation_cookbook"]
31
- end
32
-
33
- it "gets the dependencies from rubygems" do
34
- mock_gem("pivotal_workstation_cookbook", ['osx_dmg_cookbook'])
35
- mock_gem("osx_dmg_cookbook")
36
-
37
- linker.gems_and_dependencies.to_a.should =~ ["pivotal_workstation_cookbook", 'osx_dmg_cookbook']
38
- end
39
-
40
- it "gets dependencies for dependencies" do
41
- mock_gem("pivotal_workstation_cookbook", ['osx_dmg_cookbook'])
42
- mock_gem("osx_dmg_cookbook", ["osx_installer_thing"])
43
- mock_gem("osx_installer_thing")
44
-
45
- linker.gems_and_dependencies.to_a.should =~ ["pivotal_workstation_cookbook", 'osx_dmg_cookbook', 'osx_installer_thing']
46
- end
47
-
48
- it "works on old rubygems" do
49
- Gem::Specification.stub('respond_to?').with(:find_by_name).and_return(false)
50
- Gem::Specification.should_receive(:find_by_name).exactly(0).times
51
- mock_gem("pivotal_workstation_cookbook")
52
-
53
- linker.gems_and_dependencies.to_a.should == ["pivotal_workstation_cookbook"]
54
- end
55
- end
56
-
57
- describe ".link_gem_cookbooks" do
58
- it "creates a directory of symlinks" do
59
- mock_gem("pivotal_workstation_cookbook")
60
- linker.link_gem_cookbooks
61
- File.exist?(File.expand_path('pivotal_workstation', linker.cookbook_gem_temp_dir)).should be
62
- end
63
- end
64
- end
@@ -1,6 +0,0 @@
1
- # this file is loaded by the tests instead of the actual pivotal_workstation_cookbook
2
-
3
- module PivotalWorkstationCookbook
4
- COOKBOOK_PATH = File.expand_path('../..', __FILE__)
5
- VERSION = "1.0.0"
6
- end
data/spec/util_spec.rb DELETED
@@ -1,19 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe Soloist::Util do
4
- class TestClass
5
- extend Soloist::Util
6
- end
7
-
8
- describe "walk_up_and_find_file" do
9
- it "raises an error when the file isn't found" do
10
- lambda do
11
- TestClass.walk_up_and_find_file(["file_not_on_the_filesystem"])
12
- end.should raise_error(Errno::ENOENT, "No such file or directory - file_not_on_the_filesystem not found")
13
- end
14
-
15
- it "doesn't raise an error if :required => false is passed" do
16
- TestClass.walk_up_and_find_file(["file_not_on_the_filesystem"], :required => false).should == [nil, nil]
17
- end
18
- end
19
- end