tb-cli 0.1.0
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/.gitignore +7 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/README.md +89 -0
- data/Rakefile +18 -0
- data/bin/tb +4 -0
- data/lib/tb-cli.rb +47 -0
- data/lib/tb-cli/camel_case.rb +18 -0
- data/lib/tb-cli/cli/add.rb +256 -0
- data/lib/tb-cli/cli/rack.rb +51 -0
- data/lib/tb-cli/config_file.rb +76 -0
- data/lib/tb-cli/descriptions.rb +55 -0
- data/lib/tb-cli/templates/Gemfile.tt +6 -0
- data/lib/tb-cli/templates/README.tt +21 -0
- data/lib/tb-cli/templates/Rakefile.tt +1 -0
- data/lib/tb-cli/templates/app.rb.tt +9 -0
- data/lib/tb-cli/templates/config.ru.tt +2 -0
- data/lib/tb-cli/templates/fully-exploded-torquebox.yml.tt +106 -0
- data/lib/tb-cli/templates/template.rb +74 -0
- data/lib/tb-cli/templates/torquebox.yml.tt +3 -0
- data/lib/tb-cli/version.rb +6 -0
- data/spec/spec_helper.rb +3 -0
- data/tb-cli.gemspec +31 -0
- metadata +116 -0
data/.gitignore
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
-m markdown
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
Torquebox CLI
|
2
|
+
=============
|
3
|
+
The command-line app for making [Torquebox][1] even louder.
|
4
|
+
|
5
|
+
Usage
|
6
|
+
-----
|
7
|
+
|
8
|
+
tb [action] [options]
|
9
|
+
|
10
|
+
Actions that you can perform are `rack` and `add`, which can be described
|
11
|
+
below.
|
12
|
+
|
13
|
+
### Add component with `tb add`
|
14
|
+
Add a component to your torquebox.yml. Torquebox provides a number of features
|
15
|
+
that make writing Rack and Rails-based applications a breeze, such as messaging
|
16
|
+
features, background services, cron-like tasks, and service pooling.
|
17
|
+
|
18
|
+
Types of components can be:
|
19
|
+
|
20
|
+
* `application` - Application types
|
21
|
+
* `web` - WEb configuration settings
|
22
|
+
* `ruby` - version of ruby you want to set, including compilation options
|
23
|
+
* `environment` - add and remove environment variables for the runtime of
|
24
|
+
your JRuby App
|
25
|
+
* `queue` - manipulate queues (create, rename, remove)
|
26
|
+
* `topic` - create a topic
|
27
|
+
* `messaing` - set up handlers for your queues/topics
|
28
|
+
* `task` - create a task with a concurrency setting
|
29
|
+
* `job` - create an external job, including various settings around it
|
30
|
+
(job class, description, crontab)
|
31
|
+
* `service` - Create a long-running service that runs in the background
|
32
|
+
* `auth` - configure your authorization settings
|
33
|
+
* `pooling` - Runtime pooling options
|
34
|
+
|
35
|
+
For help with any component you want to add, you can get help by typing `tb add
|
36
|
+
help [component]`, and you'll get some help.
|
37
|
+
|
38
|
+
### Create baseline Torquebox-Rack app with `tb rack`
|
39
|
+
Generate a Rack-based application. A normal Rack-based Torquebox application
|
40
|
+
only needs a few files, which this generator helps fill out for you:
|
41
|
+
|
42
|
+
* `project_name` folder
|
43
|
+
* `project_name/config.ru` - Your Rackup file
|
44
|
+
* `project_name/lib` directory
|
45
|
+
* `project_name/app.rb` base application file that starts Rack
|
46
|
+
* `project_name/Rakefile` with [Torquebox specific rake tasks][3]
|
47
|
+
* `project_name/torquebox.yml` - Your Torquebox config file
|
48
|
+
* `project_name/Gemfile` if you decide to use it as a Gem
|
49
|
+
|
50
|
+
|
51
|
+
More Help
|
52
|
+
=========
|
53
|
+
|
54
|
+
If you are unfamiliar with the layout of the `torquebox.yml` file or don't know
|
55
|
+
what all this gobbledygook means, you can always reference the torquebox documentation, from
|
56
|
+
which much of this application is based off of.
|
57
|
+
|
58
|
+
http://torquebox.org/documentation/
|
59
|
+
|
60
|
+
Why
|
61
|
+
---
|
62
|
+
Torquebox is a really awesome project and I was interested in doing something
|
63
|
+
with it. Since there didn't appear to be any project-generator-type
|
64
|
+
thing in place, I decided to make one. This is as much an experiment with
|
65
|
+
[Thor][2] as it is an interest in providing Torquebox a command-line application
|
66
|
+
to spin up TB apps quickly.
|
67
|
+
|
68
|
+
Obviously, if you find bugs, report them, throw a pull request my way, and
|
69
|
+
feel free to critique the hell out of this. This is my first project in the
|
70
|
+
Ruby space, and I'm more interested in making this a good app, even if it's not
|
71
|
+
entirely useful to anybody.
|
72
|
+
|
73
|
+
### Note:
|
74
|
+
I have no tests at all for this. I'm interested in trying to test it, but I'm
|
75
|
+
not entirely sure how I would test a command-line app when much of it's
|
76
|
+
functionality is wrapped in Thor (which I trust to do its job) tasks and such.
|
77
|
+
|
78
|
+
To Do
|
79
|
+
=====
|
80
|
+
I don't have an interest in adding too many more features, but I have a small list of things
|
81
|
+
I'd like to include to fill it out a bit:
|
82
|
+
|
83
|
+
* wrap [rake tasks][3]
|
84
|
+
* include the [rails template generator][4] provided by the Torquebox team
|
85
|
+
|
86
|
+
[1]: http://www.torquebox.org/
|
87
|
+
[2]: http://www.github.com/wycats/thor
|
88
|
+
[3]: http://torquebox.org/documentation/1.0.1/deployment.html#deploy-using-rake
|
89
|
+
[4]: http://torquebox.org/documentation/1.0.1/web.html#using-the-rails-application-template
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
gem 'rdoc'
|
2
|
+
require 'rdoc/task'
|
3
|
+
require 'rake/clean'
|
4
|
+
require 'bundler'
|
5
|
+
|
6
|
+
Bundler::GemHelper.install_tasks
|
7
|
+
|
8
|
+
CLEAN.include('*.tmp')
|
9
|
+
CLOBBER.include('*.tmp', 'pkg/', 'html/')
|
10
|
+
|
11
|
+
# Default is to build and generate docs. No tests yet, so can't do that
|
12
|
+
task :default => ["build", "rdoc"]
|
13
|
+
|
14
|
+
# Document gem and place in html/
|
15
|
+
Rake::RDocTask.new do |rd|
|
16
|
+
rd.main = "README.md"
|
17
|
+
rd.rdoc_files.include("lib/**/*.rb", "README.md")
|
18
|
+
end
|
data/bin/tb
ADDED
data/lib/tb-cli.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$: << File.expand_path(File.dirname(__FILE__) + "/../lib")
|
2
|
+
require 'rubygems'
|
3
|
+
require 'thor'
|
4
|
+
require 'thor/group'
|
5
|
+
|
6
|
+
module Tbox
|
7
|
+
# Base Command Line interface. Registers the two major Thor tasks (Rack and
|
8
|
+
# Add).
|
9
|
+
class Cli < Thor
|
10
|
+
require 'tb-cli/camel_case'
|
11
|
+
require 'tb-cli/descriptions'
|
12
|
+
require 'tb-cli/cli/add'
|
13
|
+
require 'tb-cli/cli/rack'
|
14
|
+
require 'tb-cli/config_file'
|
15
|
+
|
16
|
+
register Tbox::Add, "add", "add [component]", ADD
|
17
|
+
register Tbox::Rack, "rack", "rack [project_name]", RACK
|
18
|
+
|
19
|
+
# Default help message when nothing is passed in
|
20
|
+
def help(meth=nil)
|
21
|
+
puts BANNER
|
22
|
+
super
|
23
|
+
end
|
24
|
+
|
25
|
+
# override the Basic shell with the colorized one in Thor
|
26
|
+
def self.start(*)
|
27
|
+
Thor::Base.shell = Thor::Shell::Color
|
28
|
+
super
|
29
|
+
end
|
30
|
+
|
31
|
+
# Default Help Message banner.
|
32
|
+
BANNER = <<-BAN
|
33
|
+
Torquebox CLI
|
34
|
+
|
35
|
+
tb [action] [options] # See below for more details on actions
|
36
|
+
|
37
|
+
Use this template generator to make quick Rack applications. If you want a
|
38
|
+
rails app, please use the application template provided by Torquebox
|
39
|
+
(http://torquebox.org/documentation/DEV/rails.html#using-the-rails-application-template):
|
40
|
+
|
41
|
+
rails new my_app -m $TORQUEBOX_HOME/share/rails/template.rb
|
42
|
+
|
43
|
+
BAN
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
47
|
+
Tbox::Cli.start
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# See the 'tb-cli/cli/rack' module for initializing Rack-based projects to see
|
2
|
+
# where this modification is being used.
|
3
|
+
class String
|
4
|
+
|
5
|
+
# Stolen from StackOverflow: http://stackoverflow.com/questions/1509915/converting-camel-case-to-underscore-case-in-ruby
|
6
|
+
#
|
7
|
+
# This converts a string from CamelCase to snake_case. This allows all String
|
8
|
+
# classes to call #underscore to get a proper conversion.
|
9
|
+
#
|
10
|
+
def underscore
|
11
|
+
self.gsub(/::/, '/').
|
12
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
13
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
14
|
+
tr("-", "_").
|
15
|
+
downcase
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
@@ -0,0 +1,256 @@
|
|
1
|
+
module Tbox
|
2
|
+
# Class for adding components to your `torquebox.yml`, `queues.yml` or
|
3
|
+
# `topics.yml` file.
|
4
|
+
class Add < Thor
|
5
|
+
include Thor::Actions
|
6
|
+
|
7
|
+
desc "add application", "Application"
|
8
|
+
long_desc <<-DESC
|
9
|
+
Add an application component descriptor to your project. See
|
10
|
+
|
11
|
+
http://torquebox.org/documentation/1.0.1/deployment-descriptors.html#general-application-config-in-descriptor
|
12
|
+
|
13
|
+
for more details. The two options you have at your disposal are:
|
14
|
+
|
15
|
+
root_loc: location for your project (/path/to/my/app)
|
16
|
+
env: your environment (development, test, production)
|
17
|
+
DESC
|
18
|
+
method_option :root_loc, :type => :string, :desc => "root for your application"
|
19
|
+
method_option :env, :type => :string, :desc => "Environment to run under (development, test, production)"
|
20
|
+
def application
|
21
|
+
y = ConfigFile.new destination_root
|
22
|
+
if options.root_loc || options.env
|
23
|
+
y.add_config('application', 'root', options.root_loc) if options.root_loc
|
24
|
+
y.add_config('application', 'env', options.env) if options.env
|
25
|
+
replace_yaml(y.yaml)
|
26
|
+
else
|
27
|
+
puts "You need to specify either --root-loc or --env"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "add web", "Web"
|
32
|
+
long_desc <<-DESC
|
33
|
+
Add web-specific configuration to your application. Since Torquebox can deploy multiple applications
|
34
|
+
under one hostname, extra configuration options are allowed to make deployment easier. If you want to
|
35
|
+
specify the specific 'rackup.ru' script for your app, configure with --rackup=location. You can specify
|
36
|
+
a specific context that this application will be avaialble for (such as /application) by using --context.
|
37
|
+
|
38
|
+
Virtual hosts can also be configured with the --host option. Finally, you can also specify a location for
|
39
|
+
your static web content can be pointed to by using the --static=location option.
|
40
|
+
|
41
|
+
See http://torquebox.org/documentation/1.0.1/deployment-descriptors.html#web-specific-config-in-descriptor
|
42
|
+
for more details.
|
43
|
+
DESC
|
44
|
+
method_option :rackup, :type => :string, :default => "config.ru", :desc => "Rackup file (default config.ru)"
|
45
|
+
method_option :host, :type => :string, :default => "localhost", :desc => "virtual host to run as (default localhost)"
|
46
|
+
method_option :context, :type => :string, :default => "/", :desc => "path under http://host/ to deploy to (default: '/')"
|
47
|
+
method_option :static, :type => :string, :desc => "Any static web content provided should be put here (default: none)"
|
48
|
+
def web
|
49
|
+
y = ConfigFile.new destination_root
|
50
|
+
y.add_config('web', 'rackup', options.rackup) if options.rackup
|
51
|
+
y.add_config('web', 'host', options.host) if options.host
|
52
|
+
y.add_config('web', 'context', options.context) if options.context
|
53
|
+
y.add_config('web', 'static', options.static) if options.static
|
54
|
+
replace_yaml(y.yaml)
|
55
|
+
end
|
56
|
+
|
57
|
+
desc "add ruby", "Ruby"
|
58
|
+
long_desc <<-DESC
|
59
|
+
Add Ruby runtime configurations for your web application. JRuby allows for a couple different runtime options:
|
60
|
+
Ruby interpreter version (1.8 or 1.9 through --version), and compile mode (jit, force, off) through --compile_mode.
|
61
|
+
|
62
|
+
See http://torquebox.org/documentation/1.0.1/deployment-descriptors.html#ruby-runtime-config-in-descriptor
|
63
|
+
for more details.
|
64
|
+
DESC
|
65
|
+
method_option :version, :type => :numeric, :desc => "Ruby interpreter version, either 1.8 or 1.9"
|
66
|
+
method_option :compile_mode, :type => :string, :desc => "Compile mode (jit, force, or off)"
|
67
|
+
def ruby
|
68
|
+
y = ConfigFile.new destination_root
|
69
|
+
if [ 1.8, 1.9 ].include? options.version
|
70
|
+
y.add_config('ruby', 'version', options.version)
|
71
|
+
end
|
72
|
+
if [ 'jit', 'force', 'off' ].include? options.compile_mode
|
73
|
+
y.add_config('ruby', 'compile_mode', options.compile_mode)
|
74
|
+
end
|
75
|
+
replace_yaml(y.yaml)
|
76
|
+
end
|
77
|
+
|
78
|
+
desc "add environment", "Add an environment variable, such as MAIL_HOST or REPLY_TO"
|
79
|
+
method_option :options, :type => :hash, :desc => "Add options as you need them: --options=MAIL_HOST:server REPLY_TO:emailaddress, etc., etc."
|
80
|
+
def environment
|
81
|
+
y = ConfigFile.new destination_root
|
82
|
+
options.options.each_pair { |k,v|
|
83
|
+
y.add_config('environment', k, v)
|
84
|
+
}
|
85
|
+
replace_yaml(y.yaml)
|
86
|
+
end
|
87
|
+
|
88
|
+
desc "add queue", "Add a Queue to your application"
|
89
|
+
long_desc <<-DESC
|
90
|
+
Queues are a messaging component that can be often used in load balancing situations. For sending and receiving
|
91
|
+
messages, you define a topic to queue up all of the work to be done, and subscribe a number of queue handlers
|
92
|
+
to retrieve messages off of the queue as the work arrives. Adding a queue to your application is pretty easy.
|
93
|
+
Just add the --name=queue_name. An additional option --not_durable, can be appended to prevent any messages from
|
94
|
+
being written to disk in case of server failure. By default, all queues are durable, but if you want to disable this
|
95
|
+
functionality, you can do so.
|
96
|
+
|
97
|
+
Much more detailed documentation on queues and topics can be found on the Torquebox site, including documentation
|
98
|
+
on how to interact with a queue, sending and receiving messages and the like:
|
99
|
+
|
100
|
+
http://torquebox.org/documentation/1.0.1/messaging.html
|
101
|
+
DESC
|
102
|
+
method_option :name, :type => :string, :required => true
|
103
|
+
method_option :not_durable, :type => :boolean, :default => false, :desc => "Disable Durable subscriber (at your own risk)"
|
104
|
+
def queue
|
105
|
+
# TODO: Add external queues and hosts (see section 7.2.3.3 for details)
|
106
|
+
file = 'queues.yml'
|
107
|
+
y = ConfigFile.new destination_root, file
|
108
|
+
if (options.not_durable && options.name)
|
109
|
+
y.add_config("/queues/#{options.name}", "durable: #{!options.not_durable}")
|
110
|
+
elsif (options.name)
|
111
|
+
y.add_config("/queues/#{options.name}")
|
112
|
+
end
|
113
|
+
replace_yaml(y.yaml, file)
|
114
|
+
end
|
115
|
+
|
116
|
+
desc "add topic", "Add a Topic to your application"
|
117
|
+
long_desc <<-DESC
|
118
|
+
Topics are similar to Queues, except that they follow the pub-sub model for messaging. Currently, the only
|
119
|
+
option allowed is --name=name_of_topic. Much more documentation can be found on how to use Topics and Queues,
|
120
|
+
and how they fit into Torquebox on their website:
|
121
|
+
|
122
|
+
http://torquebox.org/documentation/1.0.1/messaging.html
|
123
|
+
DESC
|
124
|
+
method_option :name, :type => :string, :required => true
|
125
|
+
def topic
|
126
|
+
# TODO: Add external queues and hosts (see section 7.2.3.3 for details)
|
127
|
+
file = 'topics.yml'
|
128
|
+
y = ConfigFile.new destination_root, file
|
129
|
+
y.add_config("/topics/#{options.name}")
|
130
|
+
replace_yaml(y.yaml, file)
|
131
|
+
end
|
132
|
+
|
133
|
+
desc "add messaging", "Add Messaging handlers for your queues and topics"
|
134
|
+
long_desc <<-DESC
|
135
|
+
Handlers are classes that consume messages on either topics or queues. Defining which classes are going to handle
|
136
|
+
these messages can be done by specifying the --queue=name_of_queue, as well as the --handler_class=ClassName to
|
137
|
+
provide a handler for.
|
138
|
+
|
139
|
+
As always, documentation for Message Processors can be found on the Torquebox site:
|
140
|
+
http://torquebox.org/documentation/LATEST/messaging.html#messaging-consumers
|
141
|
+
DESC
|
142
|
+
method_option :queue, :type => :string, :desc => "Name of the queue (/queues/my_queue_name:)"
|
143
|
+
method_option :topic, :type => :string, :desc => "Name of the topic (/topics/my_topic_name:)"
|
144
|
+
method_option :handler_class, :type => :string
|
145
|
+
def messaging
|
146
|
+
if options.queue == nil && options.topic == nil
|
147
|
+
puts "You must specify either a topic or a queue you're configuring a handler for"
|
148
|
+
else
|
149
|
+
if options.handler_class
|
150
|
+
y = ConfigFile.new destination_root
|
151
|
+
messaging = y.add_config["messaging"] || {}
|
152
|
+
if options.queue
|
153
|
+
messaging[options.queue] = options.handler_class
|
154
|
+
elsif options.topic
|
155
|
+
messaging[options.topic] = options.handler_class
|
156
|
+
end
|
157
|
+
y.add_config["messaging"] = messaging
|
158
|
+
puts y.yaml
|
159
|
+
replace_yaml(y.yaml)
|
160
|
+
else
|
161
|
+
puts "You must specify a --handler-class"
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
desc "add task", "Add a Task"
|
167
|
+
method_option :name, :type => :string, :desc => "Class Name of Task (MyTaskName)", :required => true
|
168
|
+
method_option :concurrency, :type => :numeric, :desc => "Number of concurrent messages you want to handle"
|
169
|
+
def task
|
170
|
+
y = ConfigFile.new destination_root
|
171
|
+
if options.concurrency
|
172
|
+
y.add_config('tasks', options.name, { "concurrency" => options.concurrency })
|
173
|
+
else
|
174
|
+
y.add_config('tasks', options.name)
|
175
|
+
end
|
176
|
+
replace_yaml(y.yaml)
|
177
|
+
end
|
178
|
+
|
179
|
+
desc "add job", "Add a scheduled job"
|
180
|
+
method_option :job_name, :type => :string, :required => true
|
181
|
+
method_option :job_class, :type => :string, :required => true, :desc => "Class for the Job (Mail::Notifier)"
|
182
|
+
method_option :cron, :type => :string, :required => true,
|
183
|
+
:desc => "crontab-like entry, Similar to the following: '0 */5 * * * ?'"
|
184
|
+
method_option :description, :type => :string, :desc => "Optional Description"
|
185
|
+
def job
|
186
|
+
y = ConfigFile.new destination_root
|
187
|
+
opts = {}
|
188
|
+
opts['job'] = options.job_class
|
189
|
+
opts['cron'] = options.cron
|
190
|
+
opts['description'] = options.description if options.description
|
191
|
+
y.add_config('jobs', options.job_name, opts)
|
192
|
+
replace_yaml(y.yaml)
|
193
|
+
end
|
194
|
+
|
195
|
+
desc "add service", "Add a background service"
|
196
|
+
method_option :name, :type => :string, :desc => "Service Name", :required => true
|
197
|
+
method_option :params, :type => :hash, :desc => "key:value pairs to supply for this service"
|
198
|
+
method_option :singleton, :type => :boolean, :desc => "Will this be a singleton operation?", :default => false
|
199
|
+
def service
|
200
|
+
y = ConfigFile.new destination_root
|
201
|
+
opts = options.params
|
202
|
+
opts["singleton"] = true if options.singleton
|
203
|
+
y.add_config('services', options.name, opts)
|
204
|
+
replace_yaml(y.yaml)
|
205
|
+
end
|
206
|
+
|
207
|
+
desc "add auth", "Auth"
|
208
|
+
method_option :auth_type, :type => :string, :desc => "Authentication type", :required => true
|
209
|
+
method_option :domain, :type => :string, :desc => "domain to authenticate against", :required => true
|
210
|
+
def auth
|
211
|
+
y = ConfigFile.new destination_root
|
212
|
+
y.add_config('auth', options.auth_type, { "domain" => options.domain })
|
213
|
+
replace_yaml(y.yaml)
|
214
|
+
end
|
215
|
+
|
216
|
+
desc "add pooling", "Pooling"
|
217
|
+
method_option :subsystem, :type => :string, :desc => "Subsystem type (web, jobs, messaging, services)",
|
218
|
+
:required => true
|
219
|
+
method_option :bounded, :type => :hash, :desc => "min:1, max:3, etc"
|
220
|
+
method_option :shared, :type => :boolean, :desc => "use this if not using bounded pooling"
|
221
|
+
method_option :global, :type => :boolean, :desc => "if not using bounded or shared"
|
222
|
+
def pooling
|
223
|
+
y = ConfigFile.new destination_root
|
224
|
+
thing = {}
|
225
|
+
thing["pooling"] = {}
|
226
|
+
if [ 'web', 'jobs', 'messaging', 'services' ].include? options.subsystem
|
227
|
+
if options.bounded
|
228
|
+
y.add_config('pooling', options.subsystem, options.bounded)
|
229
|
+
elsif options.shared
|
230
|
+
y.add_config('pooling', options.subsystem, 'shared')
|
231
|
+
elsif options.global
|
232
|
+
y.add_config('pooling', options.subsystem, 'global')
|
233
|
+
end
|
234
|
+
replace_yaml(y.yaml)
|
235
|
+
else
|
236
|
+
puts "subsystem must be one of: web, job, messaging, or services"
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
def help(meth=nil)
|
241
|
+
puts INIT
|
242
|
+
super
|
243
|
+
end
|
244
|
+
|
245
|
+
no_tasks do
|
246
|
+
|
247
|
+
def replace_yaml(yaml_f, file='torquebox.yml')
|
248
|
+
puts "Saving:\n"
|
249
|
+
remove_file(file)
|
250
|
+
create_file(file, yaml_f)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
end
|
255
|
+
|
256
|
+
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Tbox
|
2
|
+
## Rack tasks for your application.
|
3
|
+
class Rack < Thor
|
4
|
+
|
5
|
+
# For use with generating Rack-based projects
|
6
|
+
include Thor::Actions
|
7
|
+
|
8
|
+
default_task :init
|
9
|
+
|
10
|
+
desc "init", "Initialize a new Rack-based Application"
|
11
|
+
# Initialize a new Rack-based Application
|
12
|
+
def init
|
13
|
+
setup = yes? "Would you like to set up a new Rack-based Application?"
|
14
|
+
if setup
|
15
|
+
say "awesome!", Thor::Color::BOLD + Thor::Color::RED, false
|
16
|
+
say " let's get to work"
|
17
|
+
@project = ask "Name of project: "
|
18
|
+
if @project
|
19
|
+
gen_project @project
|
20
|
+
else
|
21
|
+
say "You need to supply a project name"
|
22
|
+
end
|
23
|
+
else
|
24
|
+
say "Shucks"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
no_tasks do
|
29
|
+
|
30
|
+
# Generates a new project with the provided name:
|
31
|
+
# [project_name] Name of the project and subsequent folder to create
|
32
|
+
# the project for
|
33
|
+
def gen_project(project_name)
|
34
|
+
say_status "new_project", project_name
|
35
|
+
Tbox::Rack.source_root(File.expand_path(File.join(__FILE__, "..", "..")))
|
36
|
+
empty_directory(project_name)
|
37
|
+
empty_directory(project_name + "/lib")
|
38
|
+
%w{ app.rb config.ru Rakefile torquebox.yml README Gemfile }.each { |f|
|
39
|
+
template("templates/#{f}.tt", "#{project_name}/#{f}")
|
40
|
+
}
|
41
|
+
end
|
42
|
+
|
43
|
+
def method_missing(name, *args) # :nodoc:
|
44
|
+
@project = name.to_s.underscore
|
45
|
+
gen_project name.to_s.underscore
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Tbox
|
2
|
+
# ConfigFile class provides some simple YAML configuration file helpers.
|
3
|
+
# While normal YAML methods within Ruby are fine (and used heavily), these
|
4
|
+
# helpers assist in adding, removing, and replacing configurations for the
|
5
|
+
# Torquebox.yml default specification file. These methods make adding
|
6
|
+
# a config to the torquebox.yml much easier, as it abstracts out the details
|
7
|
+
# of having to know the underlying data structure (Hashes, Arrays, boolean,
|
8
|
+
# string) and just pass in to this ConfigFile the pieces you want to add
|
9
|
+
class ConfigFile
|
10
|
+
require 'yaml'
|
11
|
+
|
12
|
+
attr_accessor :config, :torquebox_yml
|
13
|
+
|
14
|
+
# Create and/or open a YAML configuration file
|
15
|
+
# [destination_root] Directory that you will find the YAML file
|
16
|
+
# [file] Filename of the YAML file to load
|
17
|
+
def initialize(destination_root=nil, file='torquebox.yml')
|
18
|
+
@filename = file
|
19
|
+
@torquebox_yml = File.join(destination_root, @filename)
|
20
|
+
if config_present?
|
21
|
+
@config = YAML.load_file @torquebox_yml
|
22
|
+
else
|
23
|
+
@config = {}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Is the configuration file there or does a new config there to laod?
|
28
|
+
def config_present?
|
29
|
+
File.exist? @torquebox_yml
|
30
|
+
end
|
31
|
+
|
32
|
+
# Convert config to YAML
|
33
|
+
def yaml
|
34
|
+
@config.to_yaml
|
35
|
+
end
|
36
|
+
|
37
|
+
# Dynamically adds to the config object based on what was passed in through
|
38
|
+
# Thor
|
39
|
+
#
|
40
|
+
# @param [Thor::CoreExt::HashWithIndifferentAccess] options options hash given to you by Thor
|
41
|
+
# @param [String] meth string of the method passed in
|
42
|
+
# @param [String] config what the config for that method sets
|
43
|
+
# @param [String] value value assocated with it
|
44
|
+
#
|
45
|
+
# @return [String] the YAML output for this config, e.g.:
|
46
|
+
# options = HashWithIndifferentAccess.new 'topic' => 'some_topic_name'
|
47
|
+
# add_config(options, "topics", "topic"
|
48
|
+
#
|
49
|
+
# ---
|
50
|
+
# topics:
|
51
|
+
# some_topic_name:
|
52
|
+
def add_config(root, config=nil, value=nil)
|
53
|
+
conf = @config[root.to_s] || {}
|
54
|
+
conf[config.to_s] = value if config
|
55
|
+
@config[root.to_s] = nil # Some attributes need no settings and just exist, like queues.yml
|
56
|
+
@config[root.to_s] = conf unless conf.empty?
|
57
|
+
puts "Current #{@filename} configuration file:\n\n#{yaml}\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
# Not tested or documented
|
61
|
+
def remove_config(meth, config)
|
62
|
+
conf = @config[meth.to_s]
|
63
|
+
unless conf
|
64
|
+
puts "No such config available for #{meth}"
|
65
|
+
else
|
66
|
+
puts "removing config \n\t#{config}"
|
67
|
+
begin
|
68
|
+
@config.delete(config)
|
69
|
+
rescue e
|
70
|
+
puts "No such config #{config} to remove, skipping..."
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# Description for when you pass in the 'add' method execution.
|
2
|
+
ADD = <<-COMPONENT
|
3
|
+
Add a new component to the torquebox.yml file. The type of component can be:
|
4
|
+
|
5
|
+
- application
|
6
|
+
- web
|
7
|
+
- ruby
|
8
|
+
- environment
|
9
|
+
- queue
|
10
|
+
- topic
|
11
|
+
- messaging
|
12
|
+
- task
|
13
|
+
- job
|
14
|
+
- service
|
15
|
+
- auth
|
16
|
+
- pooling
|
17
|
+
|
18
|
+
For more help on a particular subcommand, enter
|
19
|
+
|
20
|
+
tb add help [component]
|
21
|
+
|
22
|
+
COMPONENT
|
23
|
+
|
24
|
+
MESSAGING_LONG = <<-MSG
|
25
|
+
Messaging
|
26
|
+
=========
|
27
|
+
For more information, go to (http://torquebox.org/documentation/1.0.0/messaging.html#messaging-consumers) for information (figure 8.15, specifically):
|
28
|
+
|
29
|
+
messaging:
|
30
|
+
/queues/foo:
|
31
|
+
MyFooHandler:
|
32
|
+
filter: "cost > 30"
|
33
|
+
config:
|
34
|
+
type: "premium"
|
35
|
+
season: "fall"
|
36
|
+
concurrency: 2
|
37
|
+
/topics/bar:
|
38
|
+
MyBarHandler:
|
39
|
+
durable: true
|
40
|
+
|
41
|
+
MSG
|
42
|
+
|
43
|
+
RACK = <<-RCK
|
44
|
+
Create a new Rack Application template. By default, will generate the following:
|
45
|
+
|
46
|
+
project_folder
|
47
|
+
|- app.rb (Application stub)
|
48
|
+
|- config.ru (Rackup file)
|
49
|
+
|- Rakefile (Rake with Torquebox configs)
|
50
|
+
|- torquebox.yml (Torquebox config)
|
51
|
+
|
52
|
+
Much of this would be much similar to a rails app, but if you
|
53
|
+
have an interest in doing something more lightweight, you might
|
54
|
+
find this template more appealing and minimal.
|
55
|
+
RCK
|
@@ -0,0 +1,21 @@
|
|
1
|
+
Here's a new application
|
2
|
+
========================
|
3
|
+
|
4
|
+
Nothing fancy, so if you're looking for more details on how to
|
5
|
+
actually generate a nice Torquebox project, there is a wealth
|
6
|
+
of good information to be found in the Torquebox documentation:
|
7
|
+
|
8
|
+
http://torquebox.org/documentation/1.0.0
|
9
|
+
|
10
|
+
What's in this project?
|
11
|
+
-----------------------
|
12
|
+
|
13
|
+
Here are currently a handful of base files to make your first
|
14
|
+
Torquebox app:
|
15
|
+
|
16
|
+
- app.rb Your Application
|
17
|
+
- config.ru Your Rackup file (see http://m.onkey.org/ruby-on-rack-1-hello-rack)
|
18
|
+
- Gemfile include the torquebox and torquebox-rake-support gems
|
19
|
+
- Rakefile See http://torquebox.org/documentation/1.0.0/deployment.html#deploy-using-rake
|
20
|
+
- torquebox.yml Your Torquebox YAML file for configuring all the fancy Torquebox-y things
|
21
|
+
- README This file
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'torquebox/rake/tasks'
|
@@ -0,0 +1,106 @@
|
|
1
|
+
application:
|
2
|
+
root: /path/to/myapp
|
3
|
+
env: development
|
4
|
+
|
5
|
+
web:
|
6
|
+
rackup: alternative/path/to/my_config.ru
|
7
|
+
context: /app-one
|
8
|
+
static: public
|
9
|
+
host: www.host-one.com
|
10
|
+
|
11
|
+
ruby:
|
12
|
+
version: 1.9
|
13
|
+
compile_mode: off
|
14
|
+
|
15
|
+
environment:
|
16
|
+
MAIL_HOST: mail.yourhost.com
|
17
|
+
REPLY_TO: you@yourhost.com
|
18
|
+
|
19
|
+
queues:
|
20
|
+
/queues/my_app_queue:
|
21
|
+
|
22
|
+
topics:
|
23
|
+
/queues/my_app_topic:
|
24
|
+
|
25
|
+
messaging:
|
26
|
+
# Simple messaging:
|
27
|
+
/queues/my_app_queue: MyFooHandler
|
28
|
+
/topics/long_lived_topic: MyBazHandler
|
29
|
+
# Set options in messaging:
|
30
|
+
/queues/foo:
|
31
|
+
MyFooHandler:
|
32
|
+
filter: "cost > 30"
|
33
|
+
config:
|
34
|
+
type: "premium"
|
35
|
+
season: "fall"
|
36
|
+
concurrency: 2
|
37
|
+
/topics/bar:
|
38
|
+
MyBarHandler:
|
39
|
+
durable: true
|
40
|
+
# Advanced Setup
|
41
|
+
/topics/simple: SimpleHandler
|
42
|
+
|
43
|
+
/topics/popular:
|
44
|
+
- Handler
|
45
|
+
concurrency: 5
|
46
|
+
- Observer: &defaults
|
47
|
+
filter: "x > 18"
|
48
|
+
config:
|
49
|
+
x: ex
|
50
|
+
y: why
|
51
|
+
- Processor
|
52
|
+
|
53
|
+
/queues/students:
|
54
|
+
VerySimpleAnalyzer:
|
55
|
+
YouthMonitor:
|
56
|
+
filter: "y < 18"
|
57
|
+
config:
|
58
|
+
h: ache
|
59
|
+
i: eye
|
60
|
+
LookAndFeel:
|
61
|
+
<<: *defaults
|
62
|
+
|
63
|
+
|
64
|
+
tasks:
|
65
|
+
SomeTask:
|
66
|
+
concurrency: 2
|
67
|
+
SomeOtherTask:
|
68
|
+
concurrency: 5
|
69
|
+
|
70
|
+
jobs:
|
71
|
+
mail.notifier:
|
72
|
+
job: Mail::Notifier
|
73
|
+
cron: '0 */5 * * * ?'
|
74
|
+
description: Deliver queued mail notifications
|
75
|
+
|
76
|
+
services:
|
77
|
+
MyService:
|
78
|
+
name: TorqueBox User
|
79
|
+
|
80
|
+
AnotherService:
|
81
|
+
singleton: true # Enable High Availability
|
82
|
+
|
83
|
+
auth:
|
84
|
+
default:
|
85
|
+
domain: hornetq
|
86
|
+
jmx:
|
87
|
+
domain: jmx-console
|
88
|
+
|
89
|
+
pooling:
|
90
|
+
web: # Bounded pool with upper and lower limit
|
91
|
+
min: 3
|
92
|
+
max: 10
|
93
|
+
web: shared # A shared pool is also an option
|
94
|
+
web: global # A global pool
|
95
|
+
# Default pooling config for an app in development mode
|
96
|
+
jobs:
|
97
|
+
min: 1
|
98
|
+
max: 2
|
99
|
+
messaging:
|
100
|
+
min: 1
|
101
|
+
max: 2
|
102
|
+
web: shared
|
103
|
+
# Default pooling config for a non-development deployment
|
104
|
+
jobs: shared
|
105
|
+
messaging: shared
|
106
|
+
web: shared
|
@@ -0,0 +1,74 @@
|
|
1
|
+
if ( Rails::VERSION::MAJOR == 2 )
|
2
|
+
gem "activerecord-jdbc-adapter", :lib => "arjdbc"
|
3
|
+
else
|
4
|
+
text = File.read 'Gemfile'
|
5
|
+
File.open('Gemfile', 'w') {|f| f << text.gsub(/^(gem 'sqlite3)/, '# \1') }
|
6
|
+
gem "activerecord-jdbc-adapter", :require => "arjdbc"
|
7
|
+
gem "jdbc-sqlite3"
|
8
|
+
gem "jruby-openssl"
|
9
|
+
end
|
10
|
+
|
11
|
+
# gems defs common to v2 and v3
|
12
|
+
gem "torquebox-rake-support"
|
13
|
+
gem 'torquebox'
|
14
|
+
|
15
|
+
|
16
|
+
if ( Rails::VERSION::MAJOR == 2 )
|
17
|
+
initializer("session_store.rb") do
|
18
|
+
<<-INIT
|
19
|
+
# Configure the TorqueBox Servlet-based session store.
|
20
|
+
# Provides for server-based, in-memory, cluster-compatible sessions.
|
21
|
+
( ActionController::Base.session_store = TorqueBox::Session::ServletStore ) if defined?(TorqueBox::Session::ServletStore)
|
22
|
+
INIT
|
23
|
+
end
|
24
|
+
else
|
25
|
+
remove_file( 'config/initializers/session_store.rb' )
|
26
|
+
initializer("session_store.rb") do
|
27
|
+
<<-INIT
|
28
|
+
# Configure the TorqueBox Servlet-based session store.
|
29
|
+
# Provides for server-based, in-memory, cluster-compatible sessions
|
30
|
+
#{app_const}.config.session_store TorqueBox::Session::ServletStore if defined?(TorqueBox::Session::ServletStore)
|
31
|
+
INIT
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
initializer("active_record_backgroundable.rb") do
|
36
|
+
<<-INIT
|
37
|
+
# Enable backgroundable methods for ActiveRecord classes. Provides:
|
38
|
+
# class AModel < ActiveRecord::Base
|
39
|
+
# always_background :a_method
|
40
|
+
# end
|
41
|
+
#
|
42
|
+
# a_model_instance.background.another_method
|
43
|
+
if defined?(TorqueBox::Messaging::Backgroundable) && defined?(ActiveRecord::Base)
|
44
|
+
ActiveRecord::Base.send(:include, TorqueBox::Messaging::Backgroundable)
|
45
|
+
end
|
46
|
+
INIT
|
47
|
+
end
|
48
|
+
|
49
|
+
# Create app/tasks and app/jobs, just for fun
|
50
|
+
inside('app') {
|
51
|
+
FileUtils.mkdir %w( tasks jobs )
|
52
|
+
}
|
53
|
+
|
54
|
+
# We need the app to find the rake tasks
|
55
|
+
rakefile( 'torquebox.rake' ) do
|
56
|
+
<<-TASK
|
57
|
+
|
58
|
+
begin
|
59
|
+
require 'torquebox-rake-support'
|
60
|
+
rescue LoadError => ex
|
61
|
+
puts "Failed to load the TorqueBox rake gem (torquebox-rake-support). Make sure it is available in your environment."
|
62
|
+
end
|
63
|
+
|
64
|
+
# Patch db:load_config to make sure activerecord-jdbc-adapter gets loaded
|
65
|
+
namespace :db do
|
66
|
+
task :load_config => :rails_env do
|
67
|
+
require 'active_record'
|
68
|
+
require 'activerecord-jdbc-adapter'
|
69
|
+
ActiveRecord::Base.configurations = Rails::Application.config.database_configuration
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
TASK
|
74
|
+
end
|
data/spec/spec_helper.rb
ADDED
data/tb-cli.gemspec
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "tb-cli/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "tb-cli"
|
7
|
+
s.version = Tbox::Cli::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Nick Klauer"]
|
10
|
+
s.email = ["klauer@gmail.com"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Create simple Torquebox.yml templates for your Torquebox, Rack-based applications.}
|
13
|
+
s.description = %q{Torquebox (http://www.torquebox.org) is a JBoss Application Server that will run your
|
14
|
+
Rack and Rails apps in JRuby. Torquebox provides a number of additional functionality that you might find useful, such
|
15
|
+
as messaging, background services, and scheduled tasks. Configuring those is incredibly easy, since they all rely on
|
16
|
+
simple YAML file configs. This CLI application simplifies that further by lettnig you generate your applications and
|
17
|
+
application templates with simple command line executions.}
|
18
|
+
|
19
|
+
s.add_development_dependency "rspec"
|
20
|
+
s.add_development_dependency "sinatra"
|
21
|
+
s.add_dependency "thor"
|
22
|
+
|
23
|
+
s.executables << "tb"
|
24
|
+
|
25
|
+
s.rubyforge_project = "tb-cli"
|
26
|
+
|
27
|
+
s.files = `git ls-files`.split("\n")
|
28
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
29
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
30
|
+
s.require_paths = ["lib"]
|
31
|
+
end
|
metadata
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tb-cli
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease:
|
5
|
+
version: 0.1.0
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Nick Klauer
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2011-05-29 00:00:00 -05:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rspec
|
18
|
+
prerelease: false
|
19
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0"
|
25
|
+
type: :development
|
26
|
+
version_requirements: *id001
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sinatra
|
29
|
+
prerelease: false
|
30
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
31
|
+
none: false
|
32
|
+
requirements:
|
33
|
+
- - ">="
|
34
|
+
- !ruby/object:Gem::Version
|
35
|
+
version: "0"
|
36
|
+
type: :development
|
37
|
+
version_requirements: *id002
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: thor
|
40
|
+
prerelease: false
|
41
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: "0"
|
47
|
+
type: :runtime
|
48
|
+
version_requirements: *id003
|
49
|
+
description: |-
|
50
|
+
Torquebox (http://www.torquebox.org) is a JBoss Application Server that will run your
|
51
|
+
Rack and Rails apps in JRuby. Torquebox provides a number of additional functionality that you might find useful, such
|
52
|
+
as messaging, background services, and scheduled tasks. Configuring those is incredibly easy, since they all rely on
|
53
|
+
simple YAML file configs. This CLI application simplifies that further by lettnig you generate your applications and
|
54
|
+
application templates with simple command line executions.
|
55
|
+
email:
|
56
|
+
- klauer@gmail.com
|
57
|
+
executables:
|
58
|
+
- tb
|
59
|
+
extensions: []
|
60
|
+
|
61
|
+
extra_rdoc_files: []
|
62
|
+
|
63
|
+
files:
|
64
|
+
- .gitignore
|
65
|
+
- .yardopts
|
66
|
+
- Gemfile
|
67
|
+
- README.md
|
68
|
+
- Rakefile
|
69
|
+
- bin/tb
|
70
|
+
- lib/tb-cli.rb
|
71
|
+
- lib/tb-cli/camel_case.rb
|
72
|
+
- lib/tb-cli/cli/add.rb
|
73
|
+
- lib/tb-cli/cli/rack.rb
|
74
|
+
- lib/tb-cli/config_file.rb
|
75
|
+
- lib/tb-cli/descriptions.rb
|
76
|
+
- lib/tb-cli/templates/Gemfile.tt
|
77
|
+
- lib/tb-cli/templates/README.tt
|
78
|
+
- lib/tb-cli/templates/Rakefile.tt
|
79
|
+
- lib/tb-cli/templates/app.rb.tt
|
80
|
+
- lib/tb-cli/templates/config.ru.tt
|
81
|
+
- lib/tb-cli/templates/fully-exploded-torquebox.yml.tt
|
82
|
+
- lib/tb-cli/templates/template.rb
|
83
|
+
- lib/tb-cli/templates/torquebox.yml.tt
|
84
|
+
- lib/tb-cli/version.rb
|
85
|
+
- spec/spec_helper.rb
|
86
|
+
- tb-cli.gemspec
|
87
|
+
has_rdoc: true
|
88
|
+
homepage: ""
|
89
|
+
licenses: []
|
90
|
+
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
|
94
|
+
require_paths:
|
95
|
+
- lib
|
96
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
97
|
+
none: false
|
98
|
+
requirements:
|
99
|
+
- - ">="
|
100
|
+
- !ruby/object:Gem::Version
|
101
|
+
version: "0"
|
102
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
|
+
none: false
|
104
|
+
requirements:
|
105
|
+
- - ">="
|
106
|
+
- !ruby/object:Gem::Version
|
107
|
+
version: "0"
|
108
|
+
requirements: []
|
109
|
+
|
110
|
+
rubyforge_project: tb-cli
|
111
|
+
rubygems_version: 1.6.1
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: Create simple Torquebox.yml templates for your Torquebox, Rack-based applications.
|
115
|
+
test_files:
|
116
|
+
- spec/spec_helper.rb
|