soloist-rvm 0.0.1

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.
@@ -0,0 +1,8 @@
1
+ def make_story_channel(&block)
2
+ story do |session|
3
+ channel = session.opens_channel
4
+ block.call(channel)
5
+ channel.gets_close
6
+ channel.sends_close
7
+ end
8
+ end
@@ -0,0 +1,38 @@
1
+ require "net/ssh/test"
2
+
3
+ class Net::SSH::Test::Packet
4
+ alias :original_types :types
5
+ def types
6
+ @types ||= case @type
7
+ when CHANNEL_EXTENDED_DATA then [:long, :long, :string]
8
+ else original_types
9
+ end
10
+ end
11
+ end
12
+
13
+ class Net::SSH::Test::Script
14
+ def gets_channel_extended_data(channel, data)
15
+ events << Net::SSH::Test::RemotePacket.new(:channel_extended_data, channel.local_id, 1, data)
16
+ end
17
+ end
18
+
19
+ class Net::SSH::Test::Channel
20
+ def gets_extended_data(data)
21
+ script.gets_channel_extended_data(self, data)
22
+ end
23
+ end
24
+
25
+ class Net::SSH::Test::Kex
26
+ def exchange_keys
27
+ result = Net::SSH::Buffer.from(:byte, NEWKEYS)
28
+ @connection.send_message(result)
29
+
30
+ buffer = @connection.next_message
31
+ raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
32
+
33
+ { :session_id => "abc-xyz",
34
+ :server_key => OpenSSL::PKey::RSA.new(512),
35
+ :shared_secret => OpenSSL::BN.new("1234567890", 10),
36
+ :hashing_algorithm => OpenSSL::Digest::SHA1 }
37
+ end
38
+ end
@@ -0,0 +1,171 @@
1
+ require "spec_helper"
2
+
3
+ describe Soloist::CLI do
4
+ let(:cli) { Soloist::CLI.new }
5
+ let(:base_path) { RSpec.configuration.tempdir }
6
+ let(:soloistrc_path) { File.expand_path("soloistrc", base_path) }
7
+
8
+ before do
9
+ FileUtils.mkdir_p(base_path)
10
+ Soloist::Config.any_instance.stub(:exec)
11
+ end
12
+
13
+ describe "#chef" do
14
+ it "receives the outside environment" do
15
+ FileUtils.touch(soloistrc_path)
16
+ Dir.chdir(base_path) do
17
+ ENV["AUTREYISM"] = "pathological-yodeling"
18
+ cli.soloist_config.should_receive(:exec) do |chef_solo|
19
+ `#{chef_solo}`.chomp.should == "pathological-yodeling"
20
+ end
21
+ cli.soloist_config.stub(:chef_solo).and_return('echo $AUTREYISM')
22
+ cli.chef
23
+ end
24
+ end
25
+
26
+ context "when the soloistrc file does not exist" do
27
+ it "raises an error" do
28
+ expect do
29
+ begin
30
+ Dir.chdir(base_path) { cli.chef }
31
+ rescue Soloist::NotFound => e
32
+ e.message.should == "Could not find soloistrc or .soloistrc"
33
+ raise
34
+ end
35
+ end.to raise_error(Soloist::NotFound)
36
+ end
37
+ end
38
+
39
+ context "when the soloistrc file exists" do
40
+ before do
41
+ File.open(soloistrc_path, "w") do |file|
42
+ file.write(YAML.dump("recipes" => ["stinky::feet"]))
43
+ end
44
+ cli.soloist_config = nil
45
+ Dir.chdir(base_path) { cli.soloist_config.stub(:exec) }
46
+ end
47
+
48
+ it "runs the proper recipes" do
49
+ cli.chef
50
+ cli.soloist_config.royal_crown.recipes.should =~ ["stinky::feet"]
51
+ end
52
+
53
+ context "when a soloistrc_local file exists" do
54
+ let(:soloistrc_local_path) { File.expand_path("soloistrc_local", base_path) }
55
+
56
+ before do
57
+ File.open(soloistrc_local_path, "w") do |file|
58
+ file.write(YAML.dump("recipes" => ["stinky::socks"]))
59
+ end
60
+ cli.soloist_config = nil
61
+ Dir.chdir(base_path) { cli.soloist_config.stub(:exec) }
62
+ end
63
+
64
+ it "installs the proper recipes" do
65
+ cli.chef
66
+ cli.soloist_config.royal_crown.recipes.should =~ ["stinky::feet", "stinky::socks"]
67
+ end
68
+ end
69
+
70
+ context "when the Cheffile does not exist" do
71
+ it "runs chef" do
72
+ cli.soloist_config.should_receive(:exec)
73
+ cli.chef
74
+ end
75
+
76
+ it "does not run librarian" do
77
+ Librarian::Chef::Cli.should_not_receive(:with_environment)
78
+ cli.chef
79
+ end
80
+ end
81
+
82
+ context "when the Cheffile exists" do
83
+ let(:cli_instance) { double(:cli_instance) }
84
+
85
+ before { FileUtils.touch(File.expand_path("Cheffile", base_path)) }
86
+
87
+ it "runs librarian" do
88
+ Librarian::Chef::Cli.should_receive(:with_environment).and_yield
89
+ Librarian::Chef::Cli.should_receive(:new).and_return(cli_instance)
90
+ cli_instance.should_receive(:install)
91
+ cli.chef
92
+ end
93
+
94
+ context "when the user is not root" do
95
+ context "when rvm is not present" do
96
+ before do
97
+ cli.soloist_config.stub(:rvm?).and_return(false)
98
+ end
99
+ it "creates the cache path using sudo" do
100
+ cli.soloist_config.should_receive(:exec) do |command|
101
+ command.should =~ /^sudo -E/
102
+ end
103
+ cli.chef
104
+ end
105
+ end
106
+
107
+ context "when rvm is present" do
108
+ before do
109
+ cli.soloist_config.stub(:rvm?).and_return(true)
110
+ end
111
+ it "creates the cache path using rvmsudo" do
112
+ cli.soloist_config.should_receive(:exec) do |command|
113
+ command.should =~ /rvmsudo -E/
114
+ end
115
+ cli.chef
116
+ end
117
+ end
118
+ end
119
+
120
+ context "when the user is root" do
121
+ before { Process.stub(:uid => 0) }
122
+
123
+ it "creates the cache path" do
124
+ cli.soloist_config.should_receive(:exec) do |command|
125
+ command.should_not =~ /^sudo -E/
126
+ end
127
+ cli.chef
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ describe "#run_recipe" do
135
+ context "when the soloistrc does not exist" do
136
+ it "raises an error" do
137
+ expect do
138
+ Dir.chdir(base_path) { cli.run_recipe("pineapple::wut") }
139
+ end.to raise_error(Soloist::NotFound)
140
+ end
141
+ end
142
+
143
+ context "when the soloistrc file exists" do
144
+ before do
145
+ File.open(soloistrc_path, "w") do |file|
146
+ file.write(YAML.dump("recipes" => ["pineapple::wutcake"]))
147
+ end
148
+ end
149
+
150
+ it "sets a recipe to run" do
151
+ Dir.chdir(base_path) do
152
+ cli.should_receive(:chef)
153
+ cli.run_recipe("angst::teenage", "ennui::default")
154
+ cli.soloist_config.royal_crown.recipes.should =~ ["angst::teenage", "ennui::default"]
155
+ end
156
+ end
157
+ end
158
+ end
159
+
160
+ describe "#config" do
161
+ let(:royal_crown) { Soloist::RoyalCrown.new(:node_attributes => {"a" => "b"}) }
162
+ let(:config) { Soloist::Config.new(royal_crown) }
163
+
164
+ before { cli.stub(:soloist_config => config) }
165
+
166
+ it "prints the hash render of the RoyalCrown" do
167
+ Kernel.should_receive(:ap).with({"recipes"=>[], "a" => "b"})
168
+ cli.config
169
+ end
170
+ end
171
+ end
@@ -0,0 +1,196 @@
1
+ require "spec_helper"
2
+
3
+ describe Soloist::Config do
4
+ let(:soloist_rc_path) { File.expand_path("soloistrc", RSpec.configuration.tempdir) }
5
+ let(:soloist_rc) { Soloist::RoyalCrown.new(:path => soloist_rc_path) }
6
+ let(:config) { Soloist::Config.new(soloist_rc) }
7
+ let(:cookbook_path) { File.expand_path("cookbooks", RSpec.configuration.tempdir) }
8
+ let(:nested_cookbook_path) { File.expand_path("whoa/cookbooks", RSpec.configuration.tempdir) }
9
+
10
+ describe "#as_solo_rb" do
11
+ subject { config.as_solo_rb }
12
+
13
+ it { should include 'file_cache_path "/var/chef/cache"' }
14
+ it { should include %(json_attribs "#{config.node_json_path}") }
15
+ end
16
+
17
+ describe "#cookbook_paths" do
18
+ subject { config.cookbook_paths }
19
+
20
+ context "when the default cookbook path does not exist" do
21
+ it { should have(0).paths }
22
+ end
23
+
24
+ context "when the default cookbook path exists" do
25
+ before { FileUtils.mkdir_p(cookbook_path) }
26
+
27
+ it { should have(1).path }
28
+ it { should =~ [cookbook_path] }
29
+
30
+ context "when the default cookbook path is specified" do
31
+ before { soloist_rc.cookbook_paths = [cookbook_path] }
32
+
33
+ it { should have(1).path }
34
+ it { should =~ [cookbook_path] }
35
+ end
36
+
37
+ context "with a specified cookbook path" do
38
+ before { soloist_rc.cookbook_paths = [nested_cookbook_path] }
39
+
40
+ context "when the specified path exists" do
41
+ before { FileUtils.mkdir_p(nested_cookbook_path) }
42
+
43
+ it { should have(2).paths }
44
+ it { should =~ [cookbook_path, nested_cookbook_path] }
45
+
46
+ context "with duplicate cookbook paths" do
47
+ before { soloist_rc.cookbook_paths = [nested_cookbook_path, nested_cookbook_path] }
48
+
49
+ it { should have(2).paths }
50
+ it { should =~ [cookbook_path, nested_cookbook_path] }
51
+ end
52
+ end
53
+
54
+ context "when the specified path does not exist" do
55
+ it { should have(1).path }
56
+ it { should =~ [cookbook_path] }
57
+ end
58
+ end
59
+ end
60
+
61
+ context "with relative paths" do
62
+ before do
63
+ soloist_rc.cookbook_paths = ["./whoa/cookbooks"]
64
+ FileUtils.mkdir_p(nested_cookbook_path)
65
+ end
66
+
67
+ it { should have(1).path }
68
+ it { should =~ [nested_cookbook_path] }
69
+ end
70
+
71
+ context "with unixisms in the cookbook path" do
72
+ let(:home) { File.expand_path("~") }
73
+
74
+ before { soloist_rc.cookbook_paths = ["~"] }
75
+
76
+ it { should have(1).path }
77
+ it { should =~ [home] }
78
+ end
79
+ end
80
+
81
+ describe "#as_node_json" do
82
+ let(:soloist_rc) do
83
+ Soloist::RoyalCrown.new(
84
+ :path => soloist_rc_path,
85
+ :recipes => ["waffles"],
86
+ :node_attributes => { "gargling" => "cool", "birds" => {"nested" => "cheep"} }
87
+ )
88
+ end
89
+
90
+ describe "node_attributes" do
91
+ subject { config.as_node_json }
92
+
93
+ it { should include "gargling" => "cool" }
94
+ it { should include "birds" => { "nested" => "cheep" } }
95
+ end
96
+
97
+ describe "recipes" do
98
+ subject { config.as_node_json["recipes"] }
99
+
100
+ it { should have(1).recipe }
101
+ it { should =~ ["waffles"] }
102
+ end
103
+ end
104
+
105
+ describe "#compiled" do
106
+ let(:nested) { {} }
107
+ let(:switch) do
108
+ {
109
+ "TONGUES" => {
110
+ "FINE" => {
111
+ "recipes" => ["hobo_fist"],
112
+ "env_variable_switches" => nested
113
+ }
114
+ }
115
+ }
116
+ end
117
+
118
+ before { config.royal_crown.env_variable_switches = switch }
119
+
120
+ context "when the switch is inactive" do
121
+ before { ENV.stub(:[]).and_return("LOLWUT") }
122
+
123
+ it "does not merge the attribute" do
124
+ config.compiled["recipes"].should be_empty
125
+ end
126
+ end
127
+
128
+ context "when a switch is active" do
129
+ before { ENV.stub(:[]).and_return("FINE") }
130
+
131
+ it "merges the attributes" do
132
+ config.compiled.recipes.should =~ ["hobo_fist"]
133
+ end
134
+
135
+ context "when an inactive switch is nested" do
136
+ let(:nested) { {"BEANS" => {"EW" => {"recipes" => ["slammin"]}}} }
137
+
138
+ it "does not merge the attributes" do
139
+ config.compiled.recipes.should =~ ["hobo_fist"]
140
+ end
141
+ end
142
+
143
+ context "when an active switch is nested" do
144
+ let(:nested) { {"BEANS" => {"FINE" => {"recipes" => ["slammin"]}}} }
145
+
146
+ it "merges the attributes" do
147
+ config.compiled.recipes.should =~ ["slammin"]
148
+ end
149
+ end
150
+ end
151
+ end
152
+
153
+ describe "#merge!" do
154
+ let(:soloist_rc) { Soloist::RoyalCrown.new(:recipes => ["guts"], :node_attributes => {:reliable => "maybe"}) }
155
+ let(:other_rc) { Soloist::RoyalCrown.new(:recipes => ["chum"], :node_attributes => {:tasty => "maybe"}) }
156
+ let(:other_config) { Soloist::Config.new(other_rc) }
157
+
158
+ it "merges another config into the current one" do
159
+ config.merge!(other_config)
160
+ config.royal_crown.recipes.should =~ ["guts", "chum"]
161
+ config.royal_crown.node_attributes.keys.should =~ [:reliable, :tasty]
162
+ end
163
+
164
+ it "does not trample the other config" do
165
+ config.merge!(other_config)
166
+ other_config.royal_crown.recipes.should =~ ["chum"]
167
+ other_config.royal_crown.node_attributes.should == {:tasty => "maybe"}
168
+ end
169
+ end
170
+
171
+ describe "#log_level" do
172
+ subject { config.log_level }
173
+
174
+ context "when LOG_LEVEL is not set" do
175
+ it { should == "info" }
176
+ end
177
+
178
+ context "when LOG_LEVEL is set" do
179
+ before { ENV.stub(:[] => "BEANS") }
180
+ it { should == "BEANS" }
181
+ end
182
+ end
183
+
184
+ describe "#debug?" do
185
+ subject { config.debug? }
186
+
187
+ context "when log_level is not debug" do
188
+ it { should_not be }
189
+ end
190
+
191
+ context "when log_level is debug" do
192
+ before { config.stub(:log_level => "debug") }
193
+ it { should be }
194
+ end
195
+ end
196
+ end
@@ -0,0 +1,84 @@
1
+ require "spec_helper"
2
+
3
+ describe Soloist::RemoteConfig do
4
+ let(:royal_crown_path) { File.expand_path("soloistrc", RSpec.configuration.tempdir) }
5
+ let(:royal_crown) { Soloist::RoyalCrown.new(:path => royal_crown_path) }
6
+ let(:remote) { Soloist::Remote.new("user", "host", "key") }
7
+ let(:remote_config) { Soloist::RemoteConfig.new(royal_crown, remote) }
8
+
9
+ before { remote.stub(:backtick => "", :system => 0) }
10
+
11
+ def commands_for(method)
12
+ [].tap do |commands|
13
+ remote.stub(:system) { |c| commands << c; 0 }
14
+ remote.stub(:backtick) { |c| commands << c; "" }
15
+ remote_config.send(method)
16
+ end
17
+ end
18
+
19
+ describe "#run_chef" do
20
+ it "runs chef" do
21
+ commands_for(:run_chef).last.should include "chef-solo"
22
+ end
23
+ end
24
+
25
+ describe "#solo_rb_path" do
26
+ it "sets the path to /etc/chef/solo.rb" do
27
+ remote_config.solo_rb_path.should == "/etc/chef/solo.rb"
28
+ end
29
+
30
+ it "sets up solo.rb remotely" do
31
+ commands_for(:solo_rb_path).last.should =~ /sudo -E tee \/etc\/chef\/solo\.rb$/
32
+ end
33
+ end
34
+
35
+ describe "#node_json_path" do
36
+ it "sets the path" do
37
+ remote_config.node_json_path.should == "/etc/chef/node.json"
38
+ end
39
+
40
+ it "sets up node.json remotely" do
41
+ commands_for(:node_json_path).last.should =~ /sudo -E tee \/etc\/chef\/node\.json$/
42
+ end
43
+ end
44
+
45
+ describe "#chef_config_path" do
46
+ it "sets the path" do
47
+ remote_config.chef_config_path.should == "/etc/chef"
48
+ end
49
+
50
+ it "creates the path remotely" do
51
+ commands_for(:chef_config_path).tap do |commands|
52
+ commands.should have(1).command
53
+ commands.first.should =~ /mkdir .*? -p \/etc\/chef$/
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "#chef_cache_path" do
59
+ it "sets the path" do
60
+ remote_config.chef_cache_path.should == "/var/chef/cache"
61
+ end
62
+
63
+ it "creates the path remotely" do
64
+ commands_for(:chef_cache_path).tap do |commands|
65
+ commands.should have(1).command
66
+ commands.first.should =~ /mkdir .*? -p \/var\/chef\/cache$/
67
+ end
68
+ end
69
+ end
70
+
71
+ describe "#cookbook_paths" do
72
+ it "sets the path" do
73
+ remote_config.cookbook_paths.should have(1).path
74
+ remote_config.cookbook_paths.should =~ ["/var/chef/cookbooks"]
75
+ end
76
+
77
+ it "creates the path remotely" do
78
+ commands_for(:cookbook_paths).tap do |commands|
79
+ commands.should have(1).command
80
+ commands.first.should =~ /mkdir .*? -p \/var\/chef\/cookbooks$/
81
+ end
82
+ end
83
+ end
84
+ end