soloist-rvm 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/.pairs +14 -0
- data/.rspec +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +8 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +121 -0
- data/Guardfile +17 -0
- data/LICENSE +20 -0
- data/README.md +116 -0
- data/Vagrantfile +21 -0
- data/bin/soloist +4 -0
- data/examples/Guardfile +13 -0
- data/examples/soloistrc +2 -0
- data/lib/soloist.rb +2 -0
- data/lib/soloist/cli.rb +78 -0
- data/lib/soloist/config.rb +118 -0
- data/lib/soloist/remote.rb +66 -0
- data/lib/soloist/remote_config.rb +62 -0
- data/lib/soloist/royal_crown.rb +56 -0
- data/lib/soloist/spotlight.rb +41 -0
- data/lib/soloist/version.rb +3 -0
- data/script/bootstrap.sh +54 -0
- data/script/ci.sh +3 -0
- data/soloist-rvm.gemspec +34 -0
- data/spec/helpers/net_ssh_test_helper.rb +8 -0
- data/spec/helpers/net_ssh_test_patch.rb +38 -0
- data/spec/lib/soloist/cli_spec.rb +171 -0
- data/spec/lib/soloist/config_spec.rb +196 -0
- data/spec/lib/soloist/remote_config_spec.rb +84 -0
- data/spec/lib/soloist/remote_spec.rb +135 -0
- data/spec/lib/soloist/royal_crown_spec.rb +76 -0
- data/spec/lib/soloist/spotlight_spec.rb +66 -0
- data/spec/spec_helper.rb +15 -0
- metadata +297 -0
data/.gitignore
ADDED
data/.pairs
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
# This file is managed by chef! Override node.default["git_pairs_authors"] in attributes/git_pairs.rb to modify.
|
2
|
+
|
3
|
+
pairs:
|
4
|
+
mk: Matthew Kocher; mkocher
|
5
|
+
bc: Brian Cunnie; cunnie
|
6
|
+
dr: Doc Ritezel; doc
|
7
|
+
ap: aram price; aram
|
8
|
+
sc: Santa Claus
|
9
|
+
|
10
|
+
email:
|
11
|
+
prefix: pair
|
12
|
+
domain: pivotallabs.com
|
13
|
+
|
14
|
+
global: true
|
data/.rspec
ADDED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm --create use ruby-1.9.3-p327@soloist
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
soloist (1.0.0)
|
5
|
+
awesome_print
|
6
|
+
chef
|
7
|
+
hashie (~> 1.2)
|
8
|
+
librarian
|
9
|
+
net-ssh
|
10
|
+
thor
|
11
|
+
|
12
|
+
GEM
|
13
|
+
remote: http://rubygems.org/
|
14
|
+
specs:
|
15
|
+
archive-tar-minitar (0.5.2)
|
16
|
+
awesome_print (1.1.0)
|
17
|
+
chef (11.4.0)
|
18
|
+
erubis
|
19
|
+
highline (>= 1.6.9)
|
20
|
+
json (>= 1.4.4, <= 1.7.7)
|
21
|
+
mixlib-authentication (>= 1.3.0)
|
22
|
+
mixlib-cli (~> 1.3.0)
|
23
|
+
mixlib-config (>= 1.1.2)
|
24
|
+
mixlib-log (>= 1.3.0)
|
25
|
+
mixlib-shellout
|
26
|
+
net-ssh (~> 2.6)
|
27
|
+
net-ssh-multi (~> 1.1.0)
|
28
|
+
ohai (>= 0.6.0)
|
29
|
+
rest-client (>= 1.0.4, < 1.7.0)
|
30
|
+
yajl-ruby (~> 1.1)
|
31
|
+
coderay (1.0.8)
|
32
|
+
diff-lcs (1.1.3)
|
33
|
+
erubis (2.7.0)
|
34
|
+
gem-release (0.4.1)
|
35
|
+
guard (1.5.4)
|
36
|
+
listen (>= 0.4.2)
|
37
|
+
lumberjack (>= 1.0.2)
|
38
|
+
pry (>= 0.9.10)
|
39
|
+
thor (>= 0.14.6)
|
40
|
+
guard-bundler (1.0.0)
|
41
|
+
bundler (~> 1.0)
|
42
|
+
guard (~> 1.1)
|
43
|
+
guard-rspec (2.2.0)
|
44
|
+
guard (>= 1.1)
|
45
|
+
rspec (~> 2.11)
|
46
|
+
guard-shell (0.5.1)
|
47
|
+
guard (>= 1.1.0)
|
48
|
+
hashie (1.2.0)
|
49
|
+
highline (1.6.16)
|
50
|
+
ipaddress (0.8.0)
|
51
|
+
json (1.7.7)
|
52
|
+
json (1.7.7-java)
|
53
|
+
librarian (0.0.26)
|
54
|
+
archive-tar-minitar (>= 0.5.2)
|
55
|
+
chef (>= 0.10)
|
56
|
+
highline
|
57
|
+
thor (~> 0.15)
|
58
|
+
listen (0.6.0)
|
59
|
+
lumberjack (1.0.2)
|
60
|
+
method_source (0.8.1)
|
61
|
+
mime-types (1.21)
|
62
|
+
mixlib-authentication (1.3.0)
|
63
|
+
mixlib-log
|
64
|
+
mixlib-cli (1.3.0)
|
65
|
+
mixlib-config (1.1.2)
|
66
|
+
mixlib-log (1.4.1)
|
67
|
+
mixlib-shellout (1.1.0)
|
68
|
+
net-ssh (2.6.6)
|
69
|
+
net-ssh-gateway (1.2.0)
|
70
|
+
net-ssh (>= 2.6.5)
|
71
|
+
net-ssh-multi (1.1)
|
72
|
+
net-ssh (>= 2.1.4)
|
73
|
+
net-ssh-gateway (>= 0.99.0)
|
74
|
+
ohai (6.16.0)
|
75
|
+
ipaddress
|
76
|
+
mixlib-cli
|
77
|
+
mixlib-config
|
78
|
+
mixlib-log
|
79
|
+
mixlib-shellout
|
80
|
+
systemu
|
81
|
+
yajl-ruby
|
82
|
+
pry (0.9.10)
|
83
|
+
coderay (~> 1.0.5)
|
84
|
+
method_source (~> 0.8)
|
85
|
+
slop (~> 3.3.1)
|
86
|
+
pry (0.9.10-java)
|
87
|
+
coderay (~> 1.0.5)
|
88
|
+
method_source (~> 0.8)
|
89
|
+
slop (~> 3.3.1)
|
90
|
+
spoon (~> 0.0)
|
91
|
+
rb-fsevent (0.9.2)
|
92
|
+
rest-client (1.6.7)
|
93
|
+
mime-types (>= 1.16)
|
94
|
+
rspec (2.12.0)
|
95
|
+
rspec-core (~> 2.12.0)
|
96
|
+
rspec-expectations (~> 2.12.0)
|
97
|
+
rspec-mocks (~> 2.12.0)
|
98
|
+
rspec-core (2.12.0)
|
99
|
+
rspec-expectations (2.12.0)
|
100
|
+
diff-lcs (~> 1.1.3)
|
101
|
+
rspec-mocks (2.12.0)
|
102
|
+
slop (3.3.3)
|
103
|
+
spoon (0.0.1)
|
104
|
+
systemu (2.5.2)
|
105
|
+
terminal-notifier-guard (1.5.3)
|
106
|
+
thor (0.16.0)
|
107
|
+
yajl-ruby (1.1.0)
|
108
|
+
|
109
|
+
PLATFORMS
|
110
|
+
java
|
111
|
+
ruby
|
112
|
+
|
113
|
+
DEPENDENCIES
|
114
|
+
gem-release
|
115
|
+
guard-bundler
|
116
|
+
guard-rspec
|
117
|
+
guard-shell
|
118
|
+
rb-fsevent
|
119
|
+
rspec
|
120
|
+
soloist!
|
121
|
+
terminal-notifier-guard
|
data/Guardfile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
guard 'rspec', :cli => '--fail-fast --tag ~@slow:true' do
|
4
|
+
watch(%r{^spec/.+_spec\.rb$})
|
5
|
+
watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
6
|
+
watch('spec/spec_helper.rb') { "spec" }
|
7
|
+
end
|
8
|
+
|
9
|
+
guard 'bundler' do
|
10
|
+
watch('Gemfile')
|
11
|
+
watch('soloist.gemspec')
|
12
|
+
end
|
13
|
+
|
14
|
+
guard 'shell' do
|
15
|
+
watch('Vagrantfile') { system("unset RUBYOPT; vagrant provision") }
|
16
|
+
watch('script/bootstrap.sh') { system("unset RUBYOPT; vagrant provision") }
|
17
|
+
end
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Copyright (c) 2012 Matthew Kocher and Doc Ritezel
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
# Soloist
|
2
|
+
|
3
|
+
[![Build Status](https://secure.travis-ci.org/mkocher/soloist.png)](http://travis-ci.org/mkocher/soloist) [![Code Climate](https://codeclimate.com/github/mkocher/soloist.png)](https://codeclimate.com/github/mkocher/soloist)
|
4
|
+
|
5
|
+
Soloist lets you quickly and easily converge [Chef](http://opscode.com/chef) recipes using [chef-solo](http://wiki.opscode.com/display/chef/Chef+Solo). It does not require a Chef server, but can exploit [community cookbooks](http://community.opscode.com/cookbooks), github-hosted cookbooks and locally-sourced cookbooks through [Librarian](https://github.com/applicationsonline/librarian).
|
6
|
+
|
7
|
+
Soloist was originally built to support the [Pivotal Labs Workstation Cookbook](https://github.com/pivotal/pivotal_workstation).
|
8
|
+
|
9
|
+
|
10
|
+
Using Soloist
|
11
|
+
-------------
|
12
|
+
|
13
|
+
Let's say you want to converge the Pivotal Labs Workstation default recipe and install Sublime Text 2.
|
14
|
+
|
15
|
+
1. You'll need to have Soloist installed:
|
16
|
+
|
17
|
+
$ gem install soloist
|
18
|
+
|
19
|
+
1. You'll need a `Cheffile` in your home directory that points Librarian to all the cookbooks you've included:
|
20
|
+
|
21
|
+
$ cat /Users/pivotal/Cheffile
|
22
|
+
site "http://community.opscode.com/api/v1"
|
23
|
+
cookbook "pivotal_workstation",
|
24
|
+
:git => "https://github.com/pivotal/pivotal_workstation"
|
25
|
+
|
26
|
+
1. You'll need to create a `soloistrc` file in your home directory to tell Chef which recipes to converge:
|
27
|
+
|
28
|
+
$ cat /Users/pivotal/soloistrc
|
29
|
+
recipes:
|
30
|
+
- pivotal_workstation::default
|
31
|
+
- pivotal_workstation::sublime_text
|
32
|
+
|
33
|
+
1. You'll need to run `soloist` for anything to happen:
|
34
|
+
|
35
|
+
$ soloist
|
36
|
+
|
37
|
+
|
38
|
+
Examples
|
39
|
+
--------
|
40
|
+
|
41
|
+
##### Running a set of recipes
|
42
|
+
|
43
|
+
Here's an example of a `soloistrc`:
|
44
|
+
|
45
|
+
cookbook_paths:
|
46
|
+
- /opt/beans
|
47
|
+
recipes:
|
48
|
+
- beans::chili
|
49
|
+
- beans::food_fight
|
50
|
+
- napkins
|
51
|
+
|
52
|
+
This tells Soloist to search in both `/opt/beans` and `./cookbooks` (relative to the `soloistrc`) for cookbooks to run. Then, it attempts to converge the `beans::chili`, `beans::food_fight` and `napkins` recipes.
|
53
|
+
|
54
|
+
|
55
|
+
##### Setting node attributes
|
56
|
+
|
57
|
+
Soloist lets you override node attributes. Let's say we've got a `bash::prompt` recipe for which we want to set `node['bash']['prompt']['color']='p!nk'`. No problem!
|
58
|
+
|
59
|
+
recipes:
|
60
|
+
- bash::prompt
|
61
|
+
node_attributes:
|
62
|
+
bash:
|
63
|
+
prompt:
|
64
|
+
color: p!nk
|
65
|
+
|
66
|
+
|
67
|
+
##### Conditionally modifying Soloist
|
68
|
+
|
69
|
+
Soloist allows conditionally switching on environment variables. Let's say we only want to include the `embarrassment::parental` recipe when the `MEGA_PRODUCTION` environment variable is set to `juggalos`. Here's the `soloistrc`:
|
70
|
+
|
71
|
+
cookbook_paths:
|
72
|
+
- /fresno
|
73
|
+
recipes:
|
74
|
+
- disaster
|
75
|
+
env_variable_switches:
|
76
|
+
MEGA_PRODUCTION:
|
77
|
+
juggalos:
|
78
|
+
recipes:
|
79
|
+
- embarrassment::parental
|
80
|
+
|
81
|
+
So now, this is the result of our Soloist run:
|
82
|
+
|
83
|
+
$ MEGA_PRODUCTION=juggalos soloist
|
84
|
+
Installing disaster (1.0.0)
|
85
|
+
Installing embarrassment (1.0.0)
|
86
|
+
… chef output …
|
87
|
+
INFO: Run List expands to [disaster, embarrassment::parental, faygo]
|
88
|
+
… chef output …
|
89
|
+
|
90
|
+
If we set `MEGA_PRODUCTION=godspeed`, the `embarrassment::parental` recipe is not converged.
|
91
|
+
|
92
|
+
|
93
|
+
##### Running one-off recipes
|
94
|
+
|
95
|
+
Soloist can also run one-off recipes:
|
96
|
+
|
97
|
+
$ soloist run_recipe lice::box
|
98
|
+
Installing lice (1.0.0)
|
99
|
+
… chef output …
|
100
|
+
INFO: Run List expands to [lice::box]
|
101
|
+
… chef output …
|
102
|
+
|
103
|
+
This just runs the `lice::box` recipe from your current set of cookbooks. It still uses all the `node_attributes` and `env_variable_switches` logic.
|
104
|
+
|
105
|
+
|
106
|
+
##### Chef logging
|
107
|
+
|
108
|
+
Soloist runs `chef-solo` at log level `info` by default, which is helpful when you need to see what your Chef run is doing. If you need more information, you can set the `LOG_LEVEL` environment variable:
|
109
|
+
|
110
|
+
$ LOG_LEVEL=debug soloist
|
111
|
+
|
112
|
+
|
113
|
+
License
|
114
|
+
=======
|
115
|
+
|
116
|
+
See LICENSE for details.
|
data/Vagrantfile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
Vagrant::Config.run do |config|
|
4
|
+
ssh_key = File.read(File.expand_path("~/.ssh/id_rsa.pub"))
|
5
|
+
|
6
|
+
config.vm.box = "precise64"
|
7
|
+
config.vm.box_url = "http://files.vagrantup.com/#{config.vm.box}.box"
|
8
|
+
config.vm.network :hostonly, "192.168.6.66"
|
9
|
+
|
10
|
+
config.vm.provision :shell, :inline => "test -d /etc/skel/.ssh || mkdir /etc/skel/.ssh"
|
11
|
+
config.vm.provision :shell do |shell|
|
12
|
+
shell.inline = "echo $@ | tee /etc/skel/.ssh/authorized_keys"
|
13
|
+
shell.args = ssh_key
|
14
|
+
end
|
15
|
+
config.vm.provision :shell do |shell|
|
16
|
+
shell.path = File.expand_path("../script/bootstrap.sh", __FILE__)
|
17
|
+
shell.args = `whoami`.chomp
|
18
|
+
end
|
19
|
+
config.vm.provision :shell, :inline => "bash -lc 'rvm use --install --default ruby-1.9.3'"
|
20
|
+
config.vm.provision :shell, :inline => "bash -lc 'gem install chef --no-rdoc --no-ri'"
|
21
|
+
end
|
data/bin/soloist
ADDED
data/examples/Guardfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
guard 'bundler' do
|
4
|
+
watch('../Gemfile')
|
5
|
+
watch('../soloist.gemspec')
|
6
|
+
end
|
7
|
+
|
8
|
+
guard 'shell' do
|
9
|
+
watch('soloistrc') { system("../bin/soloist -r 192.168.6.66") }
|
10
|
+
watch(%r{^cookbooks/(.+)\.rb$}) { system("unset RUBYOPT; bundle exec ../bin/soloist -r 192.168.6.66") }
|
11
|
+
watch('Vagrantfile') { system("unset RUBYOPT; vagrant provision") }
|
12
|
+
watch('script/bootstrap.sh') { system("unset RUBYOPT; vagrant provision") }
|
13
|
+
end
|
data/examples/soloistrc
ADDED
data/lib/soloist.rb
ADDED
data/lib/soloist/cli.rb
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
require "librarian/chef/cli"
|
2
|
+
require "soloist/remote_config"
|
3
|
+
require "soloist/spotlight"
|
4
|
+
require "awesome_print"
|
5
|
+
require "thor"
|
6
|
+
|
7
|
+
module Soloist
|
8
|
+
class CLI < Thor
|
9
|
+
attr_writer :soloist_config
|
10
|
+
default_task :chef
|
11
|
+
|
12
|
+
desc "chef", "Run chef-solo"
|
13
|
+
method_option :remote, :aliases => "-r", :desc => "Run chef-solo on user@host"
|
14
|
+
method_option :identity, :aliases => "-i", :desc => "The SSH identity file"
|
15
|
+
def chef
|
16
|
+
install_cookbooks if cheffile_exists?
|
17
|
+
soloist_config.run_chef
|
18
|
+
end
|
19
|
+
|
20
|
+
desc "run_recipe [cookbook::recipe, ...]", "Run individual recipes"
|
21
|
+
method_option :remote, :aliases => "-r", :desc => "Run recipes on user@host"
|
22
|
+
method_option :identity, :aliases => "-i", :desc => "The SSH identity file"
|
23
|
+
def run_recipe(*recipes)
|
24
|
+
soloist_config.royal_crown.recipes = recipes
|
25
|
+
chef
|
26
|
+
end
|
27
|
+
|
28
|
+
desc "config", "Dumps configuration data for Soloist"
|
29
|
+
def config
|
30
|
+
Kernel.ap(soloist_config.as_node_json)
|
31
|
+
end
|
32
|
+
|
33
|
+
no_tasks do
|
34
|
+
def install_cookbooks
|
35
|
+
Dir.chdir(File.dirname(rc_path)) do
|
36
|
+
Librarian::Chef::Cli.with_environment do
|
37
|
+
Librarian::Chef::Cli.new.install
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def soloist_config
|
43
|
+
@soloist_config ||= if options[:remote]
|
44
|
+
Soloist::RemoteConfig.from_file(rc_path, remote)
|
45
|
+
else
|
46
|
+
Soloist::Config.from_file(rc_path)
|
47
|
+
end.tap do |config|
|
48
|
+
config.merge!(rc_local) if rc_local_path
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
def rc_local
|
55
|
+
Soloist::Config.from_file(rc_local_path)
|
56
|
+
end
|
57
|
+
|
58
|
+
def remote
|
59
|
+
@remote ||= if options[:identity]
|
60
|
+
Soloist::Remote.from_uri(options[:remote], options[:identity])
|
61
|
+
else
|
62
|
+
Soloist::Remote.from_uri(options[:remote])
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def cheffile_exists?
|
67
|
+
File.exists?(File.expand_path("../Cheffile", rc_path))
|
68
|
+
end
|
69
|
+
|
70
|
+
def rc_path
|
71
|
+
@rc_path ||= Soloist::Spotlight.find!("soloistrc", ".soloistrc")
|
72
|
+
end
|
73
|
+
|
74
|
+
def rc_local_path
|
75
|
+
@rc_local_path ||= Soloist::Spotlight.find("soloistrc_local", ".soloistrc_local")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|