spatula 0.0.1 → 0.0.2
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.
- data/README.textile +13 -3
- data/bin/spatula +1 -1
- data/lib/spatula/cook.rb +31 -0
- data/lib/spatula/prepare.rb +27 -0
- data/lib/spatula/search.rb +26 -0
- data/lib/spatula.rb +115 -44
- metadata +15 -5
data/README.textile
CHANGED
@@ -4,16 +4,26 @@ Spatula is a command line helper app for use with "Chef":http://www.opscode.com/
|
|
4
4
|
|
5
5
|
Spatula is really, really alpha. It does not handle errors at all, but it works pretty well given that you hand it the correct input. Please give it a try and pretty please fork it and make it better.
|
6
6
|
|
7
|
+
h1. Installation
|
8
|
+
|
9
|
+
You can get spatula from gemcutter.
|
10
|
+
|
11
|
+
<pre>
|
12
|
+
# Gemcutter:
|
13
|
+
# Follow the instructions on http://gemcutter.org/ then...
|
14
|
+
gem install spatula
|
15
|
+
</pre>
|
16
|
+
|
7
17
|
h1. Usage
|
8
18
|
|
9
19
|
Spatula currently supports 3 commands: search, show, and install.
|
10
20
|
|
11
21
|
<pre>
|
12
|
-
$
|
22
|
+
$ spatula search apache2
|
13
23
|
apache2 Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
|
14
24
|
... more output ...
|
15
25
|
|
16
|
-
$
|
26
|
+
$ spatula show apache2
|
17
27
|
name: apache2
|
18
28
|
average_rating:
|
19
29
|
category: Web Servers
|
@@ -25,7 +35,7 @@ external_url:
|
|
25
35
|
versions: http://cookbooks.opscode.com/api/v1/cookbooks/apache2/versions/0_9_1
|
26
36
|
description: Installs and configures all aspects of apache2 using Debian style symlinks with helper definitions
|
27
37
|
|
28
|
-
$
|
38
|
+
$ spatula install apache2
|
29
39
|
... downloads the apache2 cookbook and installs it into $(pwd)/cookbooks ...
|
30
40
|
... also creates a $(pwd)/cookbook_tarballs dir to store the download ...
|
31
41
|
</pre>
|
data/bin/spatula
CHANGED
data/lib/spatula/cook.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
module Spatula
|
2
|
+
# TODO: Set REMOTE_CHEF_PATH using value for file_cache_path
|
3
|
+
REMOTE_CHEF_PATH = "/tmp/chef-solo" # Where to find upstream cookbooks
|
4
|
+
|
5
|
+
class Cook
|
6
|
+
Spatula.register("cook", self)
|
7
|
+
|
8
|
+
def self.run(*args)
|
9
|
+
new(*args).run
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(server, node, port=22)
|
13
|
+
@server = server
|
14
|
+
@node = node
|
15
|
+
@port = port
|
16
|
+
end
|
17
|
+
|
18
|
+
def run
|
19
|
+
sh "rake test"
|
20
|
+
sh "rsync -rlP --rsh=\"ssh -p#@port\" --delete --exclude '.*' ./ #@server:#{REMOTE_CHEF_PATH}"
|
21
|
+
sh "ssh -t -p #@port -A #@server \"cd #{REMOTE_CHEF_PATH}; sudo /var/lib/gems/1.8/bin/chef-solo -c config/solo.rb -j config/#@node.json \""
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
def sh(command)
|
26
|
+
stdout = `#{command}`
|
27
|
+
puts stdout
|
28
|
+
stdout
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Prepare :server: for chef solo to run on it
|
2
|
+
module Spatula
|
3
|
+
class Prepare
|
4
|
+
Spatula.register("prepare", self)
|
5
|
+
|
6
|
+
def self.run(*args)
|
7
|
+
new(*args).run
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(server, port=22)
|
11
|
+
@server = server
|
12
|
+
@port = port
|
13
|
+
end
|
14
|
+
|
15
|
+
def run
|
16
|
+
sh %Q|ssh -t -p #@port #@server sudo aptitude -y install ruby rubygems rubygems1.8 irb ri libopenssl-ruby1.8 libshadow-ruby1.8 ruby1.8-dev gcc g++ rsync |
|
17
|
+
sh %Q|ssh -t -p #@port #@server sudo gem install rdoc chef ohai --no-ri --no-rdoc --source http://gems.opscode.com --source http://gems.rubyforge.org|
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def sh(command)
|
22
|
+
stdout = `#{command}`
|
23
|
+
puts stdout
|
24
|
+
stdout
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
# Search for cookbooks matching :query:
|
2
|
+
module Spatula
|
3
|
+
class Search
|
4
|
+
Spatula.register("search", self)
|
5
|
+
|
6
|
+
def self.run(*args)
|
7
|
+
new(*args).run
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(query, start=0, count=10)
|
11
|
+
@query = query
|
12
|
+
@start = start
|
13
|
+
@count = count
|
14
|
+
end
|
15
|
+
|
16
|
+
def run
|
17
|
+
url = URI.parse("%s/search?q=%s&start=%s&items=%s" % [BASE_URL, @query, @start, @count])
|
18
|
+
response = Net::HTTP.get(url)
|
19
|
+
items = JSON.parse(response)["items"]
|
20
|
+
items.each do |item|
|
21
|
+
puts [item["cookbook_name"], item["cookbook_description"], item["cookbook_maintainer"]].join("\t")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
data/lib/spatula.rb
CHANGED
@@ -3,63 +3,134 @@ require 'net/http'
|
|
3
3
|
require 'uri'
|
4
4
|
require 'json'
|
5
5
|
|
6
|
-
|
6
|
+
module Spatula
|
7
7
|
BASE_URL = "http://cookbooks.opscode.com/api/v1"
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
Spatula.new.send(command, *ARGV)
|
12
|
-
end
|
9
|
+
class Spatula
|
10
|
+
@commands = {}
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
url = URI.parse("%s/search?q=%s&start=%s&items=%s" % [BASE_URL, query, start, items])
|
17
|
-
response = Net::HTTP.get(url)
|
18
|
-
items = JSON.parse(response)["items"]
|
19
|
-
items.each do |item|
|
20
|
-
puts [item["cookbook_name"], item["cookbook_description"], item["cookbook_maintainer"]].join("\t")
|
12
|
+
def self.register(command, klass)
|
13
|
+
@commands[command] = klass
|
21
14
|
end
|
22
|
-
end
|
23
|
-
|
24
|
-
# Show the cookbook named :name:
|
25
|
-
def show(name)
|
26
|
-
print_response(get_cookbook_info(name))
|
27
|
-
end
|
28
15
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
16
|
+
def self.run
|
17
|
+
command = ARGV.shift
|
18
|
+
if klass = @commands[command]
|
19
|
+
klass.run(*ARGV)
|
20
|
+
else
|
21
|
+
Spatula.new.send(command, *ARGV)
|
22
|
+
end
|
23
|
+
end
|
33
24
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
filename = File.basename(file)
|
39
|
-
FileUtils.mkdir_p("cookbook_tarballs")
|
40
|
-
`curl #{file} -o cookbook_tarballs/#{filename}`
|
41
|
-
`tar xzvf cookbook_tarballs/#{filename} -C cookbooks`
|
42
|
-
end
|
25
|
+
# Show the cookbook named :name:
|
26
|
+
def show(name)
|
27
|
+
print_response(get_cookbook_info(name))
|
28
|
+
end
|
43
29
|
|
44
|
-
|
45
|
-
def
|
46
|
-
|
47
|
-
Net::HTTP.get(url)
|
30
|
+
# Show the latest version of the cookbook named :name:
|
31
|
+
def show_latest_version(name)
|
32
|
+
print_response(get_version_info(name))
|
48
33
|
end
|
49
34
|
|
50
|
-
|
51
|
-
|
52
|
-
|
35
|
+
# Install the cookbook :name: into cwd/cookbooks
|
36
|
+
# Will create a cookbook_tarballs dir for storing downloaded tarballs
|
37
|
+
def install(name)
|
38
|
+
file = JSON.parse(get_version_info(name))["file"]
|
39
|
+
filename = File.basename(file)
|
40
|
+
FileUtils.mkdir_p("cookbook_tarballs")
|
41
|
+
`curl #{file} -o cookbook_tarballs/#{filename}`
|
42
|
+
`tar xzvf cookbook_tarballs/#{filename} -C cookbooks`
|
53
43
|
end
|
54
44
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
45
|
+
private
|
46
|
+
def strict_system *cmd
|
47
|
+
cmd.map! &:to_s
|
48
|
+
result = []
|
49
|
+
|
50
|
+
trace = cmd.join(' ')
|
51
|
+
warn trace if $TRACE
|
52
|
+
|
53
|
+
pid, inn, out, err = popen4(*cmd)
|
54
|
+
|
55
|
+
inn.sync = true
|
56
|
+
streams = [out, err]
|
57
|
+
out_stream = {
|
58
|
+
out => $stdout,
|
59
|
+
err => $stderr,
|
60
|
+
}
|
61
|
+
|
62
|
+
out_stream_buffers = {
|
63
|
+
out => "",
|
64
|
+
err => ""
|
65
|
+
}
|
66
|
+
|
67
|
+
# Handle process termination ourselves
|
68
|
+
status = nil
|
69
|
+
Thread.start do
|
70
|
+
status = Process.waitpid2(pid).last
|
71
|
+
end
|
72
|
+
|
73
|
+
until streams.empty? do
|
74
|
+
# don't busy loop
|
75
|
+
selected, = select streams, nil, nil, 0.1
|
76
|
+
|
77
|
+
next if selected.nil? or selected.empty?
|
78
|
+
|
79
|
+
selected.each do |stream|
|
80
|
+
if stream.eof? then
|
81
|
+
streams.delete stream if status # we've quit, so no more writing
|
82
|
+
next
|
83
|
+
end
|
84
|
+
|
85
|
+
data = stream.readpartial(1024)
|
86
|
+
out_stream[stream].write data
|
87
|
+
out_stream_buffers[stream] << data
|
88
|
+
|
89
|
+
if stream == err and out_stream_buffers[stream] =~ /password(?:for)?.*:/i then
|
90
|
+
out_stream_buffers[stream] = ""
|
91
|
+
inn.puts @password
|
92
|
+
data << "\n"
|
93
|
+
$stderr.write "\n"
|
94
|
+
end
|
95
|
+
|
96
|
+
result << data
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
unless status.success? then
|
101
|
+
raise "execution failed with status #{status.exitstatus}: #{cmd.join ' '}"
|
102
|
+
end
|
103
|
+
|
104
|
+
result.join
|
105
|
+
ensure
|
106
|
+
inn.close rescue nil
|
107
|
+
out.close rescue nil
|
108
|
+
err.close rescue nil
|
59
109
|
end
|
60
|
-
|
110
|
+
|
111
|
+
def get_cookbook_info(name)
|
112
|
+
url = URI.parse("%s/cookbooks/%s" % [BASE_URL, name])
|
113
|
+
Net::HTTP.get(url)
|
114
|
+
end
|
115
|
+
|
116
|
+
def get_version_info(name)
|
117
|
+
latest = JSON.parse(get_cookbook_info(name))["latest_version"]
|
118
|
+
response = Net::HTTP.get(URI.parse(latest))
|
119
|
+
end
|
120
|
+
|
121
|
+
def print_response(response)
|
122
|
+
item = JSON.parse(response)
|
123
|
+
item.each_pair do |k, v|
|
124
|
+
puts "#{k}:\t#{v}"
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
61
128
|
end
|
62
129
|
|
130
|
+
require 'spatula/search'
|
131
|
+
require 'spatula/prepare'
|
132
|
+
require 'spatula/cook'
|
133
|
+
|
63
134
|
if __FILE__ == $0
|
64
|
-
Spatula.run
|
135
|
+
Spatula::Spatula.run
|
65
136
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spatula
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 0
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Trotter Cashion
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date:
|
17
|
+
date: 2010-02-21 00:00:00 -05:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -24,6 +29,9 @@ extra_rdoc_files: []
|
|
24
29
|
files:
|
25
30
|
- README.textile
|
26
31
|
- bin/spatula
|
32
|
+
- lib/spatula/cook.rb
|
33
|
+
- lib/spatula/prepare.rb
|
34
|
+
- lib/spatula/search.rb
|
27
35
|
- lib/spatula.rb
|
28
36
|
has_rdoc: true
|
29
37
|
homepage: http://trottercashion.com
|
@@ -38,18 +46,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
38
46
|
requirements:
|
39
47
|
- - ">="
|
40
48
|
- !ruby/object:Gem::Version
|
49
|
+
segments:
|
50
|
+
- 0
|
41
51
|
version: "0"
|
42
|
-
version:
|
43
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
44
53
|
requirements:
|
45
54
|
- - ">="
|
46
55
|
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
47
58
|
version: "0"
|
48
|
-
version:
|
49
59
|
requirements: []
|
50
60
|
|
51
61
|
rubyforge_project:
|
52
|
-
rubygems_version: 1.3.
|
62
|
+
rubygems_version: 1.3.6
|
53
63
|
signing_key:
|
54
64
|
specification_version: 3
|
55
65
|
summary: Command line helper app for use with Chef
|