capitate 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +5 -0
- data/Manifest.txt +2 -0
- data/lib/capitate/plugins/base.rb +7 -0
- data/lib/capitate/plugins/upload.rb +58 -0
- data/lib/capitate/task_node.rb +62 -4
- data/lib/capitate/version.rb +1 -1
- data/lib/capitate.rb +2 -0
- data/lib/recipes/docs.rb +0 -2
- data/lib/recipes/mongrel_cluster.rb +22 -1
- data/lib/templates/mongrel/mongrel_cluster.yml.erb +1 -0
- data/lib/templates/nginx/nginx.conf.erb +8 -0
- data/script/txt2html +31 -25
- data/tasks/website.rake +3 -6
- data/test/test_plugin_upload.rb +32 -0
- data/website/index.html +5 -6
- data/website/index.txt +3 -4
- metadata +5 -2
data/History.txt
CHANGED
data/Manifest.txt
CHANGED
@@ -17,6 +17,7 @@ lib/capitate/plugins/package.rb
|
|
17
17
|
lib/capitate/plugins/profiles.rb
|
18
18
|
lib/capitate/plugins/script.rb
|
19
19
|
lib/capitate/plugins/templates.rb
|
20
|
+
lib/capitate/plugins/upload.rb
|
20
21
|
lib/capitate/plugins/wget.rb
|
21
22
|
lib/capitate/plugins/yum.rb
|
22
23
|
lib/capitate/recipes.rb
|
@@ -77,6 +78,7 @@ tasks/deployment.rake
|
|
77
78
|
tasks/environment.rake
|
78
79
|
tasks/website.rake
|
79
80
|
test/test_helper.rb
|
81
|
+
test/test_plugin_upload.rb
|
80
82
|
test/test_recipes.rb
|
81
83
|
test/test_templates.rb
|
82
84
|
website/index.html
|
@@ -1,3 +1,10 @@
|
|
1
|
+
#--
|
2
|
+
# =============================================================================
|
3
|
+
# Copyright (c) 2007, Gabriel Handford (gabrielh@gmail.com)
|
4
|
+
# All rights reserved.
|
5
|
+
# =============================================================================
|
6
|
+
#++
|
7
|
+
|
1
8
|
require 'erb'
|
2
9
|
require 'yaml'
|
3
10
|
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Capitate::Plugins::Upload
|
2
|
+
|
3
|
+
# Upload file with source path.
|
4
|
+
# Data is streamed.
|
5
|
+
#
|
6
|
+
# ==== Options
|
7
|
+
# +src_path+:: Source path
|
8
|
+
# +dest_path:: Remote destination path
|
9
|
+
# +options+:: Options (see capistrano 'put')
|
10
|
+
#
|
11
|
+
def file(src_path, dest_path, options = {})
|
12
|
+
data = FileData.new(src_path)
|
13
|
+
put(data, dest_path, options)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Stream data with Net::SFTP by looking like an Array
|
17
|
+
class FileData
|
18
|
+
|
19
|
+
def initialize(path)
|
20
|
+
@path = path
|
21
|
+
@next_start = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
def [](start, length)
|
25
|
+
|
26
|
+
if start != @next_start
|
27
|
+
raise <<-EOS
|
28
|
+
|
29
|
+
Can only access data sequentially; so we can stream it (The next start position should have been: #{@next_start})
|
30
|
+
|
31
|
+
EOS
|
32
|
+
end
|
33
|
+
|
34
|
+
data = file.read(length)
|
35
|
+
|
36
|
+
@next_start = start + length
|
37
|
+
close if @next_start >= self.length
|
38
|
+
|
39
|
+
data
|
40
|
+
end
|
41
|
+
|
42
|
+
def length
|
43
|
+
@file_size ||= File.size(@path)
|
44
|
+
end
|
45
|
+
|
46
|
+
def file
|
47
|
+
@file ||= File.open(@path, "r")
|
48
|
+
end
|
49
|
+
|
50
|
+
def close
|
51
|
+
@file.close if @file
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
Capistrano.plugin :upload, Capitate::Plugins::Upload
|
data/lib/capitate/task_node.rb
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
#
|
1
|
+
# Task node in the capistrano namespace, task hierarchy.
|
2
|
+
#
|
2
3
|
class Capitate::TaskNode
|
3
4
|
|
4
5
|
include Capitate::Plugins::Base
|
5
6
|
|
6
7
|
attr_reader :name, :nodes, :tasks, :parent
|
7
|
-
|
8
|
+
|
9
|
+
# Create task node with name and parent
|
10
|
+
# For root not use name = "top"
|
11
|
+
#
|
12
|
+
# ==== Options
|
13
|
+
# +name+:: Node name (namespace name)
|
14
|
+
# +parent+:: Parent node
|
15
|
+
#
|
8
16
|
def initialize(name, parent = nil)
|
9
17
|
@name = name
|
10
18
|
@parent = parent
|
@@ -12,10 +20,20 @@ class Capitate::TaskNode
|
|
12
20
|
@tasks = []
|
13
21
|
end
|
14
22
|
|
23
|
+
# Add "child" node.
|
24
|
+
#
|
25
|
+
# ==== Options
|
26
|
+
# +task_node+:: Node
|
27
|
+
#
|
15
28
|
def add_node(task_node)
|
16
29
|
@nodes << task_node
|
17
30
|
end
|
18
31
|
|
32
|
+
# Find node with name (namespace).
|
33
|
+
#
|
34
|
+
# ==== Options
|
35
|
+
# +name+:: Name to look for
|
36
|
+
#
|
19
37
|
def find(name)
|
20
38
|
@nodes.each do |node|
|
21
39
|
return node if node.name == name
|
@@ -23,15 +41,27 @@ class Capitate::TaskNode
|
|
23
41
|
nil
|
24
42
|
end
|
25
43
|
|
44
|
+
# Add task to this node.
|
45
|
+
#
|
46
|
+
# ==== Options
|
47
|
+
# +task+:: Add task associated with this node (namespace).
|
48
|
+
#
|
26
49
|
def add_task(task)
|
27
50
|
@tasks << task
|
28
51
|
end
|
29
52
|
|
53
|
+
# Get "child" nodes (sorted).
|
54
|
+
#
|
30
55
|
def sorted_nodes
|
31
56
|
nodes.sort_by(&:name)
|
32
57
|
end
|
33
58
|
|
34
|
-
#
|
59
|
+
# Iterate over ALL "child" nodes, depth first.
|
60
|
+
# Yields |node, level|.
|
61
|
+
#
|
62
|
+
# ==== Options
|
63
|
+
# +level+:: Current level
|
64
|
+
#
|
35
65
|
def each_node(level = 0, &block)
|
36
66
|
sorted_nodes.each do |node|
|
37
67
|
yield(node, level)
|
@@ -39,6 +69,14 @@ class Capitate::TaskNode
|
|
39
69
|
end
|
40
70
|
end
|
41
71
|
|
72
|
+
# Get the full name, using delimeter
|
73
|
+
#
|
74
|
+
# ==== Options
|
75
|
+
# +delimeter+:: Delimeter
|
76
|
+
#
|
77
|
+
# ==== Examples
|
78
|
+
# node.full_name(":") => "mysql:centos" # On node mysql centos node (top -> mysql -> centos)
|
79
|
+
#
|
42
80
|
def full_name(delimeter = "-")
|
43
81
|
if parent
|
44
82
|
parent_name = parent.full_name
|
@@ -50,6 +88,13 @@ class Capitate::TaskNode
|
|
50
88
|
end
|
51
89
|
|
52
90
|
# Write doc for node (recursively)
|
91
|
+
#
|
92
|
+
# ==== Options
|
93
|
+
# +dir+:: Dir to write to
|
94
|
+
# +file_name+:: File name to write to, defaults to full name
|
95
|
+
# +title+:: Title and h1 for page, defaults to name
|
96
|
+
# +options+:: Options
|
97
|
+
#
|
53
98
|
def write_doc(dir, file_name = nil, title = nil, options = {}, &block)
|
54
99
|
|
55
100
|
file_name ||= full_name
|
@@ -115,6 +160,8 @@ class Capitate::TaskNode
|
|
115
160
|
end
|
116
161
|
end
|
117
162
|
|
163
|
+
# Node to string.
|
164
|
+
#
|
118
165
|
def to_s(level = 0)
|
119
166
|
spaces = " "
|
120
167
|
indent = (0...level).collect { spaces }.join("")
|
@@ -133,9 +180,20 @@ class Capitate::TaskNode
|
|
133
180
|
end
|
134
181
|
s
|
135
182
|
end
|
136
|
-
|
183
|
+
|
184
|
+
# Class methods
|
137
185
|
class << self
|
138
186
|
|
187
|
+
# Create nodes and and task to node.
|
188
|
+
#
|
189
|
+
# If task is "mysql:centos:install", the nodes will look like:
|
190
|
+
#
|
191
|
+
# (top node) -> (mysql node) -> (centos node; w/ tasks: install)
|
192
|
+
#
|
193
|
+
# ==== Options
|
194
|
+
# +top_node+:: Node to start at
|
195
|
+
# +task+:: Task to add
|
196
|
+
#
|
139
197
|
def populate_with_task(top_node, task)
|
140
198
|
node_names = task.namespace.fully_qualified_name.split(":")
|
141
199
|
|
data/lib/capitate/version.rb
CHANGED
data/lib/capitate.rb
CHANGED
@@ -22,6 +22,8 @@ require 'capitate/plugins/templates'
|
|
22
22
|
require 'capitate/plugins/wget'
|
23
23
|
require 'capitate/plugins/yum'
|
24
24
|
|
25
|
+
require 'capitate/plugins/upload'
|
26
|
+
|
25
27
|
require "capitate/cap_ext/connections"
|
26
28
|
require "capitate/cap_ext/extension_proxy"
|
27
29
|
require "capitate/cap_ext/variables"
|
data/lib/recipes/docs.rb
CHANGED
@@ -13,6 +13,10 @@ namespace :mongrel_cluster do
|
|
13
13
|
|
14
14
|
set :mongrel_port, 9000
|
15
15
|
|
16
|
+
mongrel_config_script: Config script to load with mongrel.
|
17
|
+
|
18
|
+
set :mongrel_config_script, "config/mongrel_handler.rb"
|
19
|
+
|
16
20
|
DESC
|
17
21
|
task :setup_monit do
|
18
22
|
|
@@ -24,13 +28,30 @@ namespace :mongrel_cluster do
|
|
24
28
|
# Settings
|
25
29
|
fetch(:mongrel_size)
|
26
30
|
fetch(:mongrel_port)
|
31
|
+
fetch_or_default(:mongrel_config_script, nil)
|
27
32
|
|
28
33
|
processes = []
|
29
34
|
ports = (0...mongrel_size).collect { |i| mongrel_port + i }
|
30
35
|
ports.each do |port|
|
31
36
|
|
32
37
|
pid_path = "#{shared_path}/pids/mongrel.#{port}.pid"
|
33
|
-
|
38
|
+
|
39
|
+
default_options = [
|
40
|
+
[ "-d" ],
|
41
|
+
[ "-e", "production" ],
|
42
|
+
[ "-a", "127.0.0.1" ],
|
43
|
+
[ "-c", current_path ],
|
44
|
+
[ "--user", user ],
|
45
|
+
[ "--group", user ],
|
46
|
+
[ "-p", port ],
|
47
|
+
[ "-P", pid_path ],
|
48
|
+
[ "-l", "log/mongrel.#{port}.log" ]
|
49
|
+
]
|
50
|
+
|
51
|
+
default_options << [ "-S", mongrel_config_script ] if mongrel_config_script
|
52
|
+
|
53
|
+
start_options = default_options.collect { |a| a.join(" ") }.join(" ")
|
54
|
+
#start_options = "-d -e production -a 127.0.0.1 -c #{current_path} --user #{user} --group #{user} -p #{port} -P #{pid_path} -l log/mongrel.#{port}.log"
|
34
55
|
stop_options = "-p #{port} -P #{pid_path}"
|
35
56
|
|
36
57
|
processes << { :port => port, :start_options => start_options, :stop_options => stop_options, :name => "/usr/bin/mongrel_rails", :pid_path => pid_path }
|
@@ -4,10 +4,18 @@
|
|
4
4
|
# See vhost conf for site specific stuff.
|
5
5
|
#
|
6
6
|
# ==== References:
|
7
|
+
# http://brainspl.at/articles/2006/08/23/nginx-my-new-favorite-front-end-for-mongrel-cluster
|
7
8
|
# http://brainspl.at/articles/2007/01/03/new-nginx-conf-with-optimizations
|
8
9
|
# http://topfunky.net/svn/shovel/nginx
|
9
10
|
# http://robsanheim.com/2008/02/07/beware-the-default-nginx-config-old-ie6-hates-gzip/
|
10
11
|
#
|
12
|
+
# Nginx + memcached:
|
13
|
+
# http://www.igvita.com/2008/02/11/nginx-and-memcached-a-400-boost/
|
14
|
+
# http://blog.kovyrin.net/2007/08/05/using-nginx-ssi-and-memcache-to-make-your-web-applications-faster/
|
15
|
+
#
|
16
|
+
# Fair balancing:
|
17
|
+
# http://brainspl.at/articles/2007/11/09/a-fair-proxy-balancer-for-nginx-and-mongrel
|
18
|
+
|
11
19
|
|
12
20
|
# user and group to run as
|
13
21
|
user nginx nginx;
|
data/script/txt2html
CHANGED
@@ -40,35 +40,41 @@ def convert_syntax(syntax, source)
|
|
40
40
|
return Syntax::Convertors::HTML.for_syntax(syntax).convert(source).gsub(%r!^<pre>|</pre>$!,'')
|
41
41
|
end
|
42
42
|
|
43
|
-
if ARGV.length >=
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
if ARGV.length >= 3
|
44
|
+
src_glob, template, output_dir = ARGV
|
45
|
+
src_files = Dir[src_glob]
|
47
46
|
else
|
48
|
-
puts("Usage: #{File.split($0).last} source
|
47
|
+
puts("Usage: #{File.split($0).last} path/to/source*.txt template.rhtml output_dir")
|
49
48
|
exit!
|
50
49
|
end
|
51
50
|
|
52
51
|
template = ERB.new(File.open(template).read)
|
53
52
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
53
|
+
src_files.each do |src|
|
54
|
+
title = nil
|
55
|
+
body = nil
|
56
|
+
File.open(src) do |fsrc|
|
57
|
+
title_text = fsrc.readline
|
58
|
+
body_text = fsrc.read
|
59
|
+
syntax_items = []
|
60
|
+
body_text.gsub!(%r!<(pre|code)[^>]*?syntax=['"]([^'"]+)[^>]*>(.*?)</\1>!m){
|
61
|
+
ident = syntax_items.length
|
62
|
+
element, syntax, source = $1, $2, $3
|
63
|
+
syntax_items << "<#{element} class='syntax'>#{convert_syntax(syntax, source)}</#{element}>"
|
64
|
+
"syntax-temp-#{ident}"
|
65
|
+
}
|
66
|
+
title = RedCloth.new(title_text).to_html.gsub(%r!<.*?>!,'').strip
|
67
|
+
body = RedCloth.new(body_text).to_html
|
68
|
+
body.gsub!(%r!(?:<pre><code>)?syntax-temp-(\d+)(?:</code></pre>)?!){ syntax_items[$1.to_i] }
|
69
|
+
end
|
70
|
+
stat = File.stat(src)
|
71
|
+
created = stat.ctime
|
72
|
+
modified = stat.mtime
|
73
73
|
|
74
|
-
|
74
|
+
#$stdout << template.result(binding)
|
75
|
+
output_file_path = src.split("/").last.gsub(/txt$/, "html")
|
76
|
+
output_path = output_dir + "/" + output_file_path
|
77
|
+
puts " create #{output_path}"
|
78
|
+
File.open(output_path, "w") { |file| file.puts template.result(binding) }
|
79
|
+
|
80
|
+
end
|
data/tasks/website.rake
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
desc 'Generate website files'
|
2
2
|
task :website_generate => :ruby_env do
|
3
|
-
(
|
4
|
-
|
5
|
-
end
|
3
|
+
template = File.join(File.dirname(__FILE__), '/../website/template.rhtml')
|
4
|
+
sh %{ #{RUBY_APP} script/txt2html "website/**/*.txt" #{template} website }
|
6
5
|
|
7
6
|
# Clean and re-create
|
8
7
|
FileUtils.rm_rf("website/recipes")
|
9
8
|
FileUtils.mkdir_p("website/recipes")
|
10
9
|
sh "cap docs:recipes"
|
11
10
|
template = File.join(File.dirname(__FILE__), '/../website/template_recipe.rhtml')
|
12
|
-
|
13
|
-
sh %{ #{RUBY_APP} script/txt2html #{txt} #{template} > website/recipes/#{txt.split("/").last.gsub(/txt$/,'html')} }
|
14
|
-
end
|
11
|
+
sh %{ #{RUBY_APP} script/txt2html "docs/recipes/**/*.txt" #{template} website/recipes }
|
15
12
|
end
|
16
13
|
|
17
14
|
desc 'Upload website files to rubyforge'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper.rb'
|
2
|
+
|
3
|
+
class TestPluginUpload < Test::Unit::TestCase
|
4
|
+
|
5
|
+
include Capitate::Plugins::Upload
|
6
|
+
|
7
|
+
# Mocked put
|
8
|
+
def put(data, dest_path, options)
|
9
|
+
start = 0
|
10
|
+
length = 4096
|
11
|
+
|
12
|
+
@mock_put << data[start, length]
|
13
|
+
end
|
14
|
+
|
15
|
+
# Test upload streamed
|
16
|
+
def test_upload
|
17
|
+
@mock_put = ""
|
18
|
+
|
19
|
+
# Use this file for data
|
20
|
+
path = __FILE__
|
21
|
+
|
22
|
+
file(path, "mocked")
|
23
|
+
|
24
|
+
data = nil
|
25
|
+
File.open(__FILE__) { |f| data = f.readlines }
|
26
|
+
data = data.join
|
27
|
+
|
28
|
+
assert_equal data, @mock_put
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
data/website/index.html
CHANGED
@@ -38,7 +38,7 @@
|
|
38
38
|
|
39
39
|
<div id="version" class="clickable box" onclick='document.location = "http://rubyforge.org/projects/capitate"; return false'>
|
40
40
|
<p>Get Version</p>
|
41
|
-
<a href="http://rubyforge.org/projects/capitate" class="numbers">0.1.
|
41
|
+
<a href="http://rubyforge.org/projects/capitate" class="numbers">0.1.9</a>
|
42
42
|
</div>
|
43
43
|
|
44
44
|
<div id="recipes" class="box">
|
@@ -65,10 +65,9 @@
|
|
65
65
|
<p>Add capitate to your Capfile. Copy this somewhere near the top:</p>
|
66
66
|
|
67
67
|
|
68
|
-
<p><pre class='syntax'>
|
69
|
-
|
70
|
-
|
71
|
-
<span class="ident">require</span> <span class="punct">'</span><span class="string">capitate/recipes</span><span class="punct">'</span>
|
68
|
+
<p><pre class='syntax'><span class="ident">require</span> <span class="punct">'</span><span class="string">capitate</span><span class="punct">'</span>
|
69
|
+
<span class="ident">require</span> <span class="punct">'</span><span class="string">capitate/recipes</span><span class="punct">'</span>
|
70
|
+
<span class="ident">set</span> <span class="symbol">:project_root</span><span class="punct">,</span> <span class="constant">File</span><span class="punct">.</span><span class="ident">dirname</span><span class="punct">(</span><span class="constant">__FILE__</span><span class="punct">)</span>
|
72
71
|
</pre></p>
|
73
72
|
|
74
73
|
|
@@ -152,7 +151,7 @@
|
|
152
151
|
<p>Comments are welcome. Send an email to <a href="mailto:gabrielh@gmail.com">Gabriel Handford</a> via the <a href="http://groups.google.com/group/capitate">forum</a></p>
|
153
152
|
</div>
|
154
153
|
<p class="coda">
|
155
|
-
<a href="FIXME email">Gabriel Handford</a>,
|
154
|
+
<a href="FIXME email">Gabriel Handford</a>, 22nd February 2008<br>
|
156
155
|
Theme extended from <a href="http://rb2js.rubyforge.org/">Paul Battley</a>
|
157
156
|
</p>
|
158
157
|
</div>
|
data/website/index.txt
CHANGED
@@ -13,10 +13,9 @@ h2. Running
|
|
13
13
|
|
14
14
|
Add capitate to your Capfile. Copy this somewhere near the top:
|
15
15
|
|
16
|
-
<pre syntax="ruby">
|
17
|
-
|
18
|
-
|
19
|
-
require 'capitate/recipes'
|
16
|
+
<pre syntax="ruby">require 'capitate'
|
17
|
+
require 'capitate/recipes'
|
18
|
+
set :project_root, File.dirname(__FILE__)
|
20
19
|
</pre>
|
21
20
|
|
22
21
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: capitate
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ""
|
6
6
|
authors:
|
7
7
|
- Gabriel Handford
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-02-
|
12
|
+
date: 2008-02-22 00:00:00 -05:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/capitate/plugins/profiles.rb
|
55
55
|
- lib/capitate/plugins/script.rb
|
56
56
|
- lib/capitate/plugins/templates.rb
|
57
|
+
- lib/capitate/plugins/upload.rb
|
57
58
|
- lib/capitate/plugins/wget.rb
|
58
59
|
- lib/capitate/plugins/yum.rb
|
59
60
|
- lib/capitate/recipes.rb
|
@@ -114,6 +115,7 @@ files:
|
|
114
115
|
- tasks/environment.rake
|
115
116
|
- tasks/website.rake
|
116
117
|
- test/test_helper.rb
|
118
|
+
- test/test_plugin_upload.rb
|
117
119
|
- test/test_recipes.rb
|
118
120
|
- test/test_templates.rb
|
119
121
|
- website/index.html
|
@@ -151,5 +153,6 @@ specification_version: 2
|
|
151
153
|
summary: Capistrano recipes, plugins and templates.
|
152
154
|
test_files:
|
153
155
|
- test/test_helper.rb
|
156
|
+
- test/test_plugin_upload.rb
|
154
157
|
- test/test_recipes.rb
|
155
158
|
- test/test_templates.rb
|