ahamid-soloist 0.9.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm ruby-1.8.7-p299@soloist
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in soloist.gemspec
4
+ gemspec
5
+
6
+ gem "rspec", "2.4.0"
@@ -0,0 +1,73 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ soloist (0.9.0)
5
+ chef
6
+ json (>= 1.4.4, <= 1.5.2)
7
+
8
+ GEM
9
+ remote: http://rubygems.org/
10
+ specs:
11
+ bunny (0.7.1)
12
+ chef (0.10.2)
13
+ bunny (>= 0.6.0)
14
+ erubis
15
+ highline
16
+ json (>= 1.4.4, <= 1.5.2)
17
+ mixlib-authentication (>= 1.1.0)
18
+ mixlib-cli (>= 1.1.0)
19
+ mixlib-config (>= 1.1.2)
20
+ mixlib-log (>= 1.3.0)
21
+ moneta
22
+ net-ssh (~> 2.1.3)
23
+ net-ssh-multi (~> 1.0.1)
24
+ ohai (>= 0.6.0)
25
+ rest-client (>= 1.0.4, < 1.7.0)
26
+ treetop (~> 1.4.9)
27
+ uuidtools
28
+ diff-lcs (1.1.2)
29
+ erubis (2.7.0)
30
+ highline (1.6.2)
31
+ json (1.5.2)
32
+ mime-types (1.16)
33
+ mixlib-authentication (1.1.4)
34
+ mixlib-log
35
+ mixlib-cli (1.2.0)
36
+ mixlib-config (1.1.2)
37
+ mixlib-log (1.3.0)
38
+ moneta (0.6.0)
39
+ net-ssh (2.1.4)
40
+ net-ssh-gateway (1.1.0)
41
+ net-ssh (>= 1.99.1)
42
+ net-ssh-multi (1.0.1)
43
+ net-ssh (>= 1.99.2)
44
+ net-ssh-gateway (>= 0.99.0)
45
+ ohai (0.6.4)
46
+ mixlib-cli
47
+ mixlib-config
48
+ mixlib-log
49
+ systemu
50
+ yajl-ruby
51
+ polyglot (0.3.1)
52
+ rest-client (1.6.3)
53
+ mime-types (>= 1.16)
54
+ rspec (2.4.0)
55
+ rspec-core (~> 2.4.0)
56
+ rspec-expectations (~> 2.4.0)
57
+ rspec-mocks (~> 2.4.0)
58
+ rspec-core (2.4.0)
59
+ rspec-expectations (2.4.0)
60
+ diff-lcs (~> 1.1.2)
61
+ rspec-mocks (2.4.0)
62
+ systemu (2.2.0)
63
+ treetop (1.4.9)
64
+ polyglot (>= 0.3.1)
65
+ uuidtools (2.1.2)
66
+ yajl-ruby (0.8.2)
67
+
68
+ PLATFORMS
69
+ ruby
70
+
71
+ DEPENDENCIES
72
+ rspec (= 2.4.0)
73
+ soloist!
@@ -0,0 +1,20 @@
1
+ # Copyright (c) 2010, 2011 Matthew Kocher
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining
4
+ # a copy of this software and associated documentation files (the
5
+ # "Software"), to deal in the Software without restriction, including
6
+ # without limitation the rights to use, copy, modify, merge, publish,
7
+ # distribute, sublicense, and/or sell copies of the Software, and to
8
+ # permit persons to whom the Software is furnished to do so, subject to
9
+ # the following conditions:
10
+ #
11
+ # The above copyright notice and this permission notice shall be
12
+ # included in all copies or substantial portions of the Software.
13
+ #
14
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,106 @@
1
+ Soloist: Making chef-solo easier
2
+ ================================
3
+
4
+ # Why?
5
+ You just want to use chef solo, not worry about where your config files are, or what they should look like (too much). You might think that json is a data serialization format and not a config file format. You might think that having two config files that you have to pass to an executable every time you run it is two too many.
6
+
7
+ # How?
8
+ Soloist is a script packaged as a gem which when run recurses up the file tree looking for a soloistrc file. When it finds it, it uses it to determine 1) Where its cookbooks are and 2) What recipes to run. It generates the necessary config files for chef solo, and kicks it off.
9
+
10
+ # That's exactly what I've always wanted! How do I use it?
11
+ * (sudo) gem install soloist
12
+ * create a directory to store your cookbooks in, and get a cookbook:
13
+ sh -c 'mkdir -p chef/cookbooks/pivotal_workstation && cd chef/cookbooks/pivotal_workstation && curl -L http://github.com/pivotal/pivotal_workstation/tarball/master | gunzip | tar xvf - --strip=1'
14
+ * create your soloistrc file in the root of your project.
15
+
16
+ # What if I'm just setting up my own machine, and have many projects?
17
+ Just put your soloistrc file in your home directory, and point it to wherever you want to keep your cookbooks. Or just dedicate a git repo to it, and go into that directory before running soloist.
18
+
19
+ # How do I write a solistrc file?
20
+ It's a yaml file, currently with two lists to maintain:
21
+
22
+ The first, _cookbook\_paths_, should point (using an absolute or path relative to your soloistrc file) to the directory containing your cookbooks, such was pivotal_workstation.
23
+
24
+ The second, _recipes_ should be a list of recipes you wish to run.
25
+
26
+ # Then What?
27
+ $> soloist
28
+
29
+
30
+ Example soloistrc Files
31
+ =======================
32
+
33
+ directory layout:
34
+
35
+ /Users/mkocher/workspace/project/soloistrc <-Config File
36
+ /Users/mkocher/workspace/project/chef/
37
+ /Users/mkocher/workspace/project/chef/cookbooks/pivotal_workstation/
38
+
39
+
40
+ soloistrc
41
+ ---------
42
+ cookbook_paths:
43
+ - ./chef/cookbooks/
44
+ recipes:
45
+ - pivotal_workstation::ack
46
+ - pivotal_workstation::bash_path_order
47
+ - pivotal_workstation::bash_profile
48
+ - pivotal_workstation::bash_profile-better_history
49
+ - pivotal_workstation::defaults_fast_key_repeat_rate
50
+ - pivotal_workstation::dock_preferences
51
+ - pivotal_workstation::ec2_api_tools
52
+ - pivotal_workstation::finder_display_full_path
53
+ - pivotal_workstation::git
54
+ - pivotal_workstation::git_config_global_defaults
55
+ - pivotal_workstation::git_scripts
56
+ - pivotal_workstation::google_chrome
57
+ - pivotal_workstation::inputrc
58
+ - pivotal_workstation::mysql
59
+ - pivotal_workstation::osx_turn_on_locate
60
+ - pivotal_workstation::rvm
61
+ - pivotal_workstation::safari_preferences
62
+ - pivotal_workstation::set_multitouch_preferences
63
+ - pivotal_workstation::text_mate
64
+ - pivotal_workstation::textmate_set_defaults
65
+ - pivotal_workstation::turn_on_ssh
66
+ - pivotal_workstation::user_owns_usr_local
67
+ - pivotal_workstation::workspace_directory
68
+
69
+ Environment Variable Switching
70
+ ==============================
71
+ I'm trying out adding support in the soloistrc file for selecting recipes based on environment variables. Cap should allow setting environment variables fairly easily on deploy, and they can be set permanently on the machine if desired. To use these, add a env_variable_switches key to your soloistrc. They keys of the hash should be the environment variable you wish to change the configuration based on, and the value should be a hash keyed by the value of the variable. It's easier than it sounds - see the example below. (NB: Note that the CamelSnake is gone in the soloistrc, and while the basic config accepts the old keys, environment variable switching requires snake case keys)
72
+
73
+ cookbook_paths:
74
+ - ./chef/cookbooks/
75
+ recipes:
76
+ - pivotal_workstation::ack
77
+ env_variable_switches:
78
+ RACK_ENV:
79
+ production:
80
+ cookbook_paths:
81
+ - ./chef/production_cookbooks/
82
+ recipes:
83
+ - production::foo
84
+
85
+ The values are merged in, so this results in a cookbook path of
86
+ [
87
+ "./chef/cookbooks/",
88
+ "./chef/production_cookbooks/"
89
+ ]
90
+ and a recipe list of
91
+ [
92
+ "pivotal_workstation::ack",
93
+ "production::foo"
94
+ ]
95
+
96
+ Log Level
97
+ =========
98
+ Soloist runs chef at log level info by default. Debug is very verbose, but makes debugging chef recipes much easier. Just set the LOG_LEVEL environment variable to 'debug' (or other valid chef log level) and it will be passed through.
99
+
100
+ Local Overrides (experimental)
101
+ ==============================
102
+ Soloist is an easy way to share configuration across workstations. If you want to have configuration in chef that you don't want to share with the rest of the project, you can create a soloistrc_local file in addition to the soloistrc file. This file will be processed after the soloistrc, and everything in it will be added to the run list. Be careful that you are clear what goes where - if it's a dependency of the project, it should be checked into the soloistrc file in the project.
103
+
104
+ License
105
+ =======
106
+ Soloist is MIT Licensed. See MIT-LICENSE for details.
@@ -0,0 +1,2 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,31 @@
1
+ #!/usr/bin/env ruby
2
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'soloist')
3
+ require 'etc'
4
+
5
+ include Soloist::Util
6
+
7
+ log_level = ENV['LOG_LEVEL'] || "info"
8
+
9
+ soloistrc_contents, soloistrc_path = walk_up_and_find_file(with_or_without_dot("soloistrc"))
10
+ config_generator = Soloist::ChefConfigGenerator.new(YAML.load(soloistrc_contents), soloistrc_path)
11
+
12
+ soloistrc_contents, soloistrc_path = walk_up_and_find_file(with_or_without_dot("soloistrc_local"), :required => false)
13
+ config_generator.merge_config(YAML.load(soloistrc_contents), soloistrc_path) if soloistrc_contents
14
+
15
+ if ARGV.length >= 1
16
+ requested_recipe = ARGV[0]
17
+ raise "requested recipe '#{requested_recipe}' not in soloistrc or soloistrc_local" unless config_generator.recipes.include?(requested_recipe)
18
+ config_generator.recipes = [requested_recipe]
19
+ end
20
+
21
+ solo_rb = fileify(config_generator.solo_rb)
22
+ metadata_json = fileify(config_generator.json_file)
23
+
24
+ command = "bash -c '#{config_generator.preserved_environment_variables_string} chef-solo -j #{metadata_json.path} -c #{solo_rb.path} -l #{log_level}'"
25
+
26
+ if Etc.getlogin != "root"
27
+ command = 'sudo ' + command
28
+ end
29
+
30
+ puts "running chef: " + command
31
+ system(command) || exit(1)
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require "json"
3
+ require 'fileutils'
4
+ require 'yaml'
5
+ require 'tempfile'
6
+
7
+ require File.join(File.dirname(__FILE__), 'soloist', 'util')
8
+ require File.join(File.dirname(__FILE__), 'soloist', 'chef_config_generator')
9
+
@@ -0,0 +1,82 @@
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
+ merge_config(config, relative_path_to_soloistrc)
13
+ end
14
+
15
+ attr_reader :preserved_environment_variables, :cookbook_paths, :cookbook_gems
16
+ attr_accessor :recipes
17
+
18
+ def support_old_format(hash)
19
+ hash['recipes'] ||= hash.delete('Recipes')
20
+ hash['cookbook_paths'] ||= hash.delete('Cookbook_Paths')
21
+ hash
22
+ end
23
+
24
+ def append_path(paths, relative_path_to_soloistrc)
25
+ paths.map do |path|
26
+ path.slice(0,1) == '/' ? path : "#{FileUtils.pwd}/#{relative_path_to_soloistrc}/#{path}"
27
+ end
28
+ end
29
+
30
+ def merge_config(sub_hash, relative_path_to_soloistrc)
31
+ sub_hash = support_old_format(sub_hash)
32
+ if sub_hash["recipes"]
33
+ @recipes = (@recipes + sub_hash["recipes"]).uniq
34
+ end
35
+ if sub_hash["cookbook_paths"]
36
+ @cookbook_paths = (@cookbook_paths + append_path(sub_hash["cookbook_paths"], relative_path_to_soloistrc)).uniq
37
+ end
38
+ if sub_hash["cookbook_gems"]
39
+ (@cookbook_gems += sub_hash["cookbook_gems"]).uniq!
40
+ end
41
+ if sub_hash["env_variable_switches"]
42
+ merge_env_variable_switches(sub_hash["env_variable_switches"], relative_path_to_soloistrc)
43
+ end
44
+ end
45
+
46
+ def merge_env_variable_switches(hash_to_merge, relative_path_to_soloistrc)
47
+ hash_to_merge.keys.each do |variable|
48
+ @preserved_environment_variables << variable
49
+ ENV[variable] && ENV[variable].split(',').each do |env_variable_value|
50
+ sub_hash = hash_to_merge[variable] && hash_to_merge[variable][env_variable_value]
51
+ merge_config(sub_hash, relative_path_to_soloistrc) if sub_hash
52
+ end
53
+ end
54
+ end
55
+
56
+ def solo_rb
57
+ all_cookbook_paths = cookbook_paths
58
+ cookbook_gems.each do |gem_cookbook|
59
+ require gem_cookbook
60
+ all_cookbook_paths << Kernel.const_get(camelize(gem_cookbook)).const_get('COOKBOOK_PATH')
61
+ end
62
+ "cookbook_path #{all_cookbook_paths.inspect}"
63
+ end
64
+
65
+ def json_hash
66
+ {
67
+ "recipes" => @recipes
68
+ }
69
+ end
70
+
71
+ def json_file
72
+ json_hash.to_json
73
+ end
74
+
75
+ def preserved_environment_variables_string
76
+ variable_array = []
77
+ preserved_environment_variables.map do |env_variable|
78
+ "#{env_variable}=#{ENV[env_variable]}" unless ENV[env_variable].nil?
79
+ end.compact.join(" ")
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,41 @@
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
+ file << contents
10
+ file.flush
11
+ file
12
+ end
13
+
14
+ def walk_up_and_find_file(filenames, opts={})
15
+ pwd = FileUtils.pwd
16
+ file = nil
17
+ path_to_file = ""
18
+ while !file && FileUtils.pwd != '/'
19
+ file = filenames.detect { |f| File.exists?(f) }
20
+ FileUtils.cd("..")
21
+ path_to_file << "../" unless file
22
+ end
23
+ FileUtils.cd(pwd)
24
+ if file
25
+ file_contents = File.read(path_to_file + file) if file
26
+ [file_contents, path_to_file]
27
+ elsif opts[:required] == false
28
+ [nil, nil]
29
+ else
30
+ raise Errno::ENOENT, "#{filenames.join(" or ")} not found" unless file || opts[:required] == false
31
+ end
32
+ end
33
+
34
+ # stolen from activesupport
35
+ def camelize(term)
36
+ string = term.to_s
37
+ string = string.sub(/^[a-z\d]*/) { $&.capitalize }
38
+ string.gsub(/(?:_|(\/))([a-z\d]*)/i) { "#{$1}#{$2.capitalize}" }.gsub('/', '::')
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ module Soloist
2
+ VERSION = "0.9.3"
3
+ end
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "soloist/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "ahamid-soloist"
7
+ s.version = Soloist::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Matthew Kocher"]
10
+ s.email = ["kocher@gmail.com"]
11
+ s.homepage = "http://github.com/ahamid/soloist"
12
+ s.summary = %q{Soloist is a simple way of running chef-solo}
13
+ s.description = %q{Soloist is an easy way of running chef solo, but it's not doing much.}
14
+
15
+ s.rubyforge_project = "soloist"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ s.add_dependency "chef"
23
+ s.add_dependency "json", ">= 1.4.4", "<= 1.5.2"
24
+ end
@@ -0,0 +1,242 @@
1
+ require 'rspec'
2
+ require 'lib/soloist'
3
+
4
+ describe Soloist::ChefConfigGenerator do
5
+ describe "generation" do
6
+ before do
7
+ @config = <<-CONFIG
8
+ Cookbook_Paths:
9
+ - ./chef/cookbooks/
10
+ cookbook_gems:
11
+ - pivotal_workstation_cookbook
12
+ Recipes:
13
+ - pivotal_workstation::ack
14
+ CONFIG
15
+ @config = YAML.load(@config)
16
+ FileUtils.stub(:pwd).and_return("/current/working/directory")
17
+ @generator = Soloist::ChefConfigGenerator.new(@config, "../..")
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
+ it "can generate a solo.rb contents" do
31
+ module ::PivotalWorkstationCookbook
32
+ COOKBOOK_PATH = "/var/lib/ruby/gems/pivotal_workstation/cookbooks/"
33
+ end
34
+ @generator.solo_rb.should == 'cookbook_path ["/current/working/directory/../.././chef/cookbooks/", "/var/lib/ruby/gems/pivotal_workstation/cookbooks/"]'
35
+ end
36
+
37
+ it "can generate the json contents" do
38
+ @generator.json_hash.should == {
39
+ "recipes" => ['pivotal_workstation::ack']
40
+ }
41
+ end
42
+
43
+ it "can generate json files" do
44
+ JSON.parse(@generator.json_file).should == {
45
+ "recipes" => ['pivotal_workstation::ack']
46
+ }
47
+ end
48
+
49
+ describe "passing env variables to chef-solo through sudo" do
50
+ it "has a list of env variables which are passed through" do
51
+ @generator.preserved_environment_variables.should == %w{PATH BUNDLE_PATH GEM_HOME GEM_PATH RAILS_ENV RACK_ENV}
52
+ end
53
+
54
+ it "can generate an env_variable_string which is passed through sudo to chef-solo" do
55
+ ENV["FOO"]="BAR"
56
+ ENV["FAZ"]="FUZ"
57
+ @generator.stub!(:preserved_environment_variables).and_return(["FOO", "FAZ"])
58
+ @generator.preserved_environment_variables_string.should == "FOO=BAR FAZ=FUZ"
59
+ end
60
+
61
+ it "adds any environment variables that are switched in the config" do
62
+ @config = <<-CONFIG
63
+ cookbook_paths:
64
+ - ./chef/cookbooks/
65
+ recipes:
66
+ - pivotal_workstation::ack
67
+ env_variable_switches:
68
+ ME_TOO:
69
+ development:
70
+ cookbook_paths:
71
+ - ./chef/dev_cookbooks/
72
+ recipes:
73
+ - pivotal_dev::foo
74
+ CONFIG
75
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
76
+ @generator.preserved_environment_variables.should =~ %w{PATH BUNDLE_PATH GEM_HOME GEM_PATH RAILS_ENV RACK_ENV ME_TOO}
77
+ end
78
+ end
79
+ end
80
+
81
+ describe "yaml config values" do
82
+ before do
83
+ FileUtils.stub(:pwd).and_return("/")
84
+ end
85
+
86
+ it "accepts Cookbook_Paths, because the CamelSnake is a typo that must be supported" do
87
+ @config = "Cookbook_Paths:\n- ./chef/cookbooks/\n"
88
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "..")
89
+ @generator.cookbook_paths.should == ["//.././chef/cookbooks/"]
90
+ end
91
+
92
+ it "accepts cookbook_paths, because it is sane" do
93
+ @config = "cookbook_paths:\n- ./chef/cookbooks/\n"
94
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "..")
95
+ @generator.cookbook_paths.should == ["//.././chef/cookbooks/"]
96
+ end
97
+
98
+ it "accepts Recipes, because that's the way it was" do
99
+ @config = "Recipes:\n- pivotal_workstation::ack"
100
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
101
+ @generator.json_hash.should == { "recipes" => ["pivotal_workstation::ack"]}
102
+ end
103
+
104
+ it "accepts recipes, because it's snake now" do
105
+ @config = "recipes:\n- pivotal_workstation::ack"
106
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "")
107
+ @generator.json_hash.should == { "recipes" => ["pivotal_workstation::ack"]}
108
+ end
109
+ end
110
+
111
+ describe "environment variable merging" do
112
+ before do
113
+ FileUtils.stub(:pwd).and_return("/")
114
+ end
115
+
116
+ it "merges in if the variable is set to the the value" do
117
+ @config = <<-CONFIG
118
+ cookbook_paths:
119
+ - ./chef/cookbooks/
120
+ recipes:
121
+ - pivotal_workstation::ack
122
+ env_variable_switches:
123
+ RACK_ENV:
124
+ development:
125
+ cookbook_paths:
126
+ - ./chef/dev_cookbooks/
127
+ recipes:
128
+ - pivotal_dev::foo
129
+ CONFIG
130
+ ENV["RACK_ENV"]="development"
131
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
132
+ @generator.cookbook_paths.should == [
133
+ "//../.././chef/cookbooks/",
134
+ "//../.././chef/dev_cookbooks/"
135
+ ]
136
+ @generator.json_hash["recipes"].should == [
137
+ "pivotal_workstation::ack",
138
+ "pivotal_dev::foo"
139
+ ]
140
+ end
141
+
142
+ it "merges cookbook_gems" do
143
+ @config = <<-CONFIG
144
+ cookbook_gems:
145
+ - pivotal_shared
146
+ env_variable_switches:
147
+ RACK_ENV:
148
+ development:
149
+ cookbook_gems:
150
+ - pivotal_shared
151
+ - pivotal_workstation
152
+ CONFIG
153
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
154
+ @generator.cookbook_gems.should =~ [
155
+ "pivotal_shared",
156
+ "pivotal_workstation"
157
+ ]
158
+ end
159
+
160
+ it "splits the value on comma and applies all matching" do
161
+ ENV["ROLES"]="application,database"
162
+ @config = <<-CONFIG
163
+ cookbook_paths:
164
+ - ./chef/cookbooks/
165
+ recipes:
166
+ - pivotal_workstation::ack
167
+ env_variable_switches:
168
+ ROLES:
169
+ application:
170
+ cookbook_paths:
171
+ - ./chef/app_cookbooks/
172
+ recipes:
173
+ - pivotal_app::application
174
+ database:
175
+ cookbook_paths:
176
+ - ./chef/db_cookbooks/
177
+ recipes:
178
+ - pivotal_db::database
179
+ CONFIG
180
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(@config), "../..")
181
+ @generator.cookbook_paths.should =~ [
182
+ "//../.././chef/cookbooks/",
183
+ "//../.././chef/app_cookbooks/",
184
+ "//../.././chef/db_cookbooks/"
185
+ ]
186
+ @generator.json_hash["recipes"].should =~ [
187
+ "pivotal_workstation::ack",
188
+ "pivotal_app::application",
189
+ "pivotal_db::database",
190
+ ]
191
+ end
192
+
193
+ it "can deal with empty env switched variables, and passes them through" do
194
+ config = <<-CONFIG
195
+ env_variable_switches:
196
+ RACK_ENV:
197
+ CONFIG
198
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
199
+ @generator.preserved_environment_variables.should include("RACK_ENV")
200
+ end
201
+
202
+
203
+ it "can deal with only having environment switched recipes/cookbooks" do
204
+ config = <<-CONFIG
205
+ env_variable_switches:
206
+ RACK_ENV:
207
+ development:
208
+ cookbook_paths:
209
+ - ./chef/development_cookbooks/
210
+ recipes:
211
+ - pivotal_development::foo
212
+ CONFIG
213
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
214
+ @generator.cookbook_paths.should == [
215
+ "//../.././chef/development_cookbooks/"
216
+ ]
217
+ @generator.json_hash["recipes"].should == [
218
+ "pivotal_development::foo"
219
+ ]
220
+ end
221
+ it "can deal with only having empty recipes/cookbooks" do
222
+ config = <<-CONFIG
223
+ cookbook_paths:
224
+ recipes:
225
+ env_variable_switches:
226
+ RACK_ENV:
227
+ development:
228
+ cookbook_paths:
229
+ - ./chef/development_cookbooks/
230
+ recipes:
231
+ - pivotal_development::foo
232
+ CONFIG
233
+ @generator = Soloist::ChefConfigGenerator.new(YAML.load(config), "../..")
234
+ @generator.cookbook_paths.should == [
235
+ "//../.././chef/development_cookbooks/"
236
+ ]
237
+ @generator.json_hash["recipes"].should == [
238
+ "pivotal_development::foo"
239
+ ]
240
+ end
241
+ end
242
+ end
@@ -0,0 +1 @@
1
+ # this file is loaded by the tests instead of the actual pivotal_workstation_cookbook
@@ -0,0 +1,20 @@
1
+ require 'rspec'
2
+ require 'lib/soloist'
3
+
4
+ describe Soloist::Util do
5
+ class TestClass
6
+ extend Soloist::Util
7
+ end
8
+
9
+ describe "walk_up_and_find_file" do
10
+ it "raises an error when the file isn't found" do
11
+ lambda do
12
+ TestClass.walk_up_and_find_file(["file_not_on_the_filesystem"])
13
+ end.should raise_error(Errno::ENOENT, "No such file or directory - file_not_on_the_filesystem not found")
14
+ end
15
+
16
+ it "doesn't raise an error if :required => false is passed" do
17
+ TestClass.walk_up_and_find_file(["file_not_on_the_filesystem"], :required => false).should == [nil, nil]
18
+ end
19
+ end
20
+ end
metadata ADDED
@@ -0,0 +1,96 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ahamid-soloist
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.9.3
6
+ platform: ruby
7
+ authors:
8
+ - Matthew Kocher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-07-31 00:00:00 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: chef
17
+ prerelease: false
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ version_requirements: *id001
26
+ - !ruby/object:Gem::Dependency
27
+ name: json
28
+ prerelease: false
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: 1.4.4
35
+ - - <=
36
+ - !ruby/object:Gem::Version
37
+ version: 1.5.2
38
+ type: :runtime
39
+ version_requirements: *id002
40
+ description: Soloist is an easy way of running chef solo, but it's not doing much.
41
+ email:
42
+ - kocher@gmail.com
43
+ executables:
44
+ - soloist
45
+ extensions: []
46
+
47
+ extra_rdoc_files: []
48
+
49
+ files:
50
+ - .gitignore
51
+ - .rvmrc
52
+ - Gemfile
53
+ - Gemfile.lock
54
+ - MIT-LICENSE
55
+ - README.markdown
56
+ - Rakefile
57
+ - bin/soloist
58
+ - lib/soloist.rb
59
+ - lib/soloist/chef_config_generator.rb
60
+ - lib/soloist/util.rb
61
+ - lib/soloist/version.rb
62
+ - soloist.gemspec
63
+ - spec/chef_config_generator_spec.rb
64
+ - spec/pivotal_workstation_cookbook.rb
65
+ - spec/util_spec.rb
66
+ homepage: http://github.com/ahamid/soloist
67
+ licenses: []
68
+
69
+ post_install_message:
70
+ rdoc_options: []
71
+
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: "0"
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: "0"
86
+ requirements: []
87
+
88
+ rubyforge_project: soloist
89
+ rubygems_version: 1.8.4
90
+ signing_key:
91
+ specification_version: 3
92
+ summary: Soloist is a simple way of running chef-solo
93
+ test_files:
94
+ - spec/chef_config_generator_spec.rb
95
+ - spec/pivotal_workstation_cookbook.rb
96
+ - spec/util_spec.rb