simonmenke-shuttle 0.1.07

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.
Files changed (48) hide show
  1. data/app_generators/engine/engine_generator.rb +39 -0
  2. data/app_generators/engine/templates/config/routes.rb +2 -0
  3. data/app_generators/engine/templates/init.rb +1 -0
  4. data/app_generators/engine/templates/lib/engine.rb +1 -0
  5. data/app_generators/engine/templates/rails/init.rb +1 -0
  6. data/bin/shuttle +20 -0
  7. data/lib/rubygems_plugin.rb +1 -0
  8. data/lib/shuttle/actor/actions.rb +76 -0
  9. data/lib/shuttle/actor.rb +23 -0
  10. data/lib/shuttle/actors/apache_actor.rb +56 -0
  11. data/lib/shuttle/actors/base_actor.rb +276 -0
  12. data/lib/shuttle/actors/mysql_actor.rb +20 -0
  13. data/lib/shuttle/actors/passenger_actor.rb +19 -0
  14. data/lib/shuttle/actors/plesk_actor.rb +210 -0
  15. data/lib/shuttle/actors/sqlite3_actor.rb +44 -0
  16. data/lib/shuttle/app_runner.rb +118 -0
  17. data/lib/shuttle/apps/dev.rb +27 -0
  18. data/lib/shuttle/apps/engines.rb +33 -0
  19. data/lib/shuttle/apps/jobs.rb +35 -0
  20. data/lib/shuttle/apps/satellite.rb +32 -0
  21. data/lib/shuttle/apps/server.rb +70 -0
  22. data/lib/shuttle/client/auth_token.rb +98 -0
  23. data/lib/shuttle/client.rb +48 -0
  24. data/lib/shuttle/exception_handler.rb +53 -0
  25. data/lib/shuttle/extentions/rubygems_plugin.rb +27 -0
  26. data/lib/shuttle/extentions/thor_extentions.rb +32 -0
  27. data/lib/shuttle/job_queue.rb +199 -0
  28. data/lib/shuttle/satellite/actions.rb +35 -0
  29. data/lib/shuttle/satellite/dependency_loader.rb +79 -0
  30. data/lib/shuttle/satellite/persistence.rb +50 -0
  31. data/lib/shuttle/satellite.rb +49 -0
  32. data/lib/shuttle/server/daemon.rb +85 -0
  33. data/lib/shuttle/server/proxy.rb +25 -0
  34. data/lib/shuttle/server/security.rb +113 -0
  35. data/lib/shuttle/server.rb +113 -0
  36. data/lib/shuttle/system/config.rb +36 -0
  37. data/lib/shuttle/system/helper.rb +21 -0
  38. data/lib/shuttle/system/options.rb +79 -0
  39. data/lib/shuttle/system/process_user.rb +75 -0
  40. data/lib/shuttle/system/satellites.rb +44 -0
  41. data/lib/shuttle/system/shell.rb +80 -0
  42. data/lib/shuttle/system.rb +159 -0
  43. data/lib/shuttle/systems/centos_plesk_system.rb +28 -0
  44. data/lib/shuttle/systems/macports_system.rb +14 -0
  45. data/lib/shuttle.rb +82 -0
  46. data/spec/actor/actions_spec.rb +13 -0
  47. data/spec/spec_helper.rb +1 -0
  48. metadata +129 -0
@@ -0,0 +1,210 @@
1
+
2
+ module Shuttle
3
+ module Actors # :nodoc:
4
+ class PleskActor < Shuttle::Actor
5
+
6
+ before_install_satellite :create_client
7
+ before_install_satellite :create_domain
8
+ after_install_satellite :link_htdocs
9
+ after_install_satellite :reload_subdomains
10
+ after_install_satellite :restart_apache
11
+ on_install_satellite :create_database
12
+ on_uninstall_satellite :drop_databases
13
+
14
+ def create_client
15
+ # only do this if this is needed
16
+ if false
17
+ unless system.client?(system.plesk_client)
18
+ system.create_client(system.plesk_client, system.plesk_client, 'mypwd')
19
+ end
20
+ end
21
+ end
22
+
23
+ def create_domain
24
+ unless system.domain?(satellite.basedomain)
25
+ system.create_domain(system.plesk_client, satellite.basedomain,
26
+ system.web_user[0,20], (rand(1_000_000_000) + 10_000).to_s)
27
+ else
28
+ httpdocs_path = "/var/www/vhosts/#{satellite.basedomain}/httpdocs"
29
+ system.set_satellite_option(:web_user,
30
+ system.get_user_name(File.stat(httpdocs_path).uid))
31
+ end
32
+
33
+ if satellite.subdomain? and !system.subdomain?(satellite.basedomain, satellite.subdomain)
34
+ system.create_subdomain(satellite.basedomain, satellite.subdomain)
35
+ end
36
+
37
+ FileUtils.mkdir_p(system.satellite_root)
38
+ FileUtils.mkdir_p(system.shared_root)
39
+ FileUtils.chown_R(system.web_user, system.web_group, system.satellite_root)
40
+ FileUtils.chown_R(system.web_user, system.web_group, system.shared_root)
41
+ end
42
+
43
+ def link_htdocs
44
+ httpdocs_path = File.join(File.dirname(system.satellite_root), 'httpdocs')
45
+ FileUtils.rm_rf(httpdocs_path)
46
+ FileUtils.ln_s(system.satellite_root, httpdocs_path)
47
+ FileUtils.chown_R(system.web_user, system.web_group, httpdocs_path)
48
+
49
+ File.open(File.join(system.satellite_root, '../conf/vhost.conf'), 'w+') do |f|
50
+ f.puts "DocumentRoot #{httpdocs_path}/public"
51
+ end
52
+ end
53
+
54
+ def reload_subdomains
55
+ system.run("#{system.plesk_websrvmng_bin} --reconfigure-vhost --vhost-name=#{satellite.basedomain}")
56
+ end
57
+
58
+ def restart_apache
59
+ system.run("#{system.plesk_httpd_bin} restart")
60
+ end
61
+
62
+ def create_database
63
+ db_name = satellite.domain.downcase.gsub(/[^a-z]+/, '_')[0,63]
64
+ db_user = db_name[0,13]
65
+ db_pswd = (rand(1_000_000_000) + 10_000).to_s
66
+
67
+ system.create_database(satellite.basedomain, "#{db_name}_d", "#{db_user}_ud", db_pswd)
68
+ system.create_database(satellite.basedomain, "#{db_name}_t", "#{db_user}_ut", db_pswd)
69
+ system.create_database(satellite.basedomain, "#{db_name}_p", "#{db_user}_up", db_pswd)
70
+
71
+
72
+ system.as_user(system.web_user, system.web_group) do
73
+ config = %{
74
+ development:
75
+ adapter: mysql
76
+ database: #{db_name}_d
77
+ username: #{db_user}_ud
78
+ password: #{db_pswd}
79
+ host: localhost
80
+ encoding: utf8
81
+ socket: /var/lib/mysql/mysql.sock
82
+
83
+ test:
84
+ adapter: mysql
85
+ database: #{db_name}_t
86
+ username: #{db_user}_ut
87
+ password: #{db_pswd}
88
+ host: localhost
89
+ encoding: utf8
90
+ socket: /var/lib/mysql/mysql.sock
91
+
92
+ production:
93
+ adapter: mysql
94
+ database: #{db_name}_p
95
+ username: #{db_user}_up
96
+ password: #{db_pswd}
97
+ host: localhost
98
+ encoding: utf8
99
+ socket: /var/lib/mysql/mysql.sock
100
+ }
101
+
102
+ db_file = File.join(system.satellite_root, 'config', 'database.yml')
103
+ File.open(db_file, 'w+') { |f| f.write config }
104
+ end
105
+ end
106
+
107
+ def drop_databases
108
+ db_name = satellite.domain.downcase.gsub(/[^a-z]+/, '_')[0,63]
109
+
110
+ system.drop_database("#{db_name}_d")
111
+ system.drop_database("#{db_name}_t")
112
+ system.drop_database("#{db_name}_p")
113
+ end
114
+
115
+ module Helper
116
+
117
+ def create_client(name, login, pwd)
118
+
119
+ end
120
+
121
+ # check is the client exists
122
+ def client?(login)
123
+ !(run("#{plesk_client_bin} -i #{login}") =~ /Object not found: Client/)
124
+ end
125
+
126
+ # create a domain through plesk
127
+ def create_domain(client, domain, user, passwd)
128
+ run("#{plesk_domain_bin} -c #{domain} -clogin #{client} -status enabled -hosting true -hst_type phys -dns true -www true -login #{user} -passwd #{passwd} -shell /bin/bash")
129
+ end
130
+
131
+ # check if a domain exists with plesk
132
+ def domain?(domain)
133
+ !(run("#{plesk_domain_bin} -i #{domain}") =~ /Object not found: Domain/)
134
+ end
135
+
136
+ # create a subdomain through plesk
137
+ def create_subdomain(basedomain, subdomain)
138
+ run("#{plesk_subdomain_bin} -c #{subdomain} -d #{basedomain}")
139
+ end
140
+
141
+ # check if a subdomain exists with plesk
142
+ def subdomain?(basedomain, subdomain)
143
+ run("#{plesk_subdomain_bin} -i -s #{subdomain} -d #{basedomain}") =~ /SUCCESS: Gathering/
144
+ end
145
+
146
+ # create a database through plesk
147
+ def create_database(basedomain, db_name, db_user, pwd)
148
+ o = run("#{plesk_database_bin} -c #{db_name} -domain #{basedomain} -server #{plesk_database_server} -add_user #{db_user} -passwd #{pwd}")
149
+ if o =~ /Database with requested name already exists/
150
+ o = run("#{plesk_database_bin} -u #{db_name} -add_user #{db_user} -passwd #{pwd}")
151
+ if o =~ /Unable to create database user: User/
152
+ o = run("#{plesk_database_bin} -u #{db_name} -update_user #{db_user} -passwd #{pwd}")
153
+ end
154
+ end
155
+ end
156
+
157
+ # drop a database through plesk
158
+ def drop_database(db_name)
159
+ run("#{plesk_database_bin} -r #{db_name}")
160
+ end
161
+
162
+ end
163
+
164
+ module Config
165
+
166
+ # set the plesk client to be used for this satellite.
167
+ def plesk_client(&block)
168
+ satellite_option(:plesk_client, block)
169
+ end
170
+
171
+ # path to the client tool.
172
+ def plesk_client_bin(&block)
173
+ option(:plesk_client_bin, block) { |v| v or '/usr/local/psa/bin/client' }
174
+ end
175
+
176
+ # path to the domain tool.
177
+ def plesk_domain_bin(&block)
178
+ option(:plesk_domain_bin, block) { |v| v or '/usr/local/psa/bin/domain' }
179
+ end
180
+
181
+ # path to the subdomain tool.
182
+ def plesk_subdomain_bin(&block)
183
+ option(:plesk_subdomain_bin, block) { |v| v or '/usr/local/psa/bin/subdomain' }
184
+ end
185
+
186
+ # path to the database tool.
187
+ def plesk_database_bin(&block)
188
+ option(:plesk_database_bin, block) { |v| v or '/usr/local/psa/bin/database' }
189
+ end
190
+
191
+ # path to the websrvmng tool.
192
+ def plesk_websrvmng_bin(&block)
193
+ option(:plesk_websrvmng_bin, block) { |v| v or '/usr/local/psa/admin/sbin/websrvmng' }
194
+ end
195
+
196
+ # path to the httpd tool.
197
+ def plesk_httpd_bin(&block)
198
+ option(:plesk_httpd_bin, block) { |v| v or '/etc/init.d/httpd' }
199
+ end
200
+
201
+ # host and port of database server.
202
+ def plesk_database_server(&block)
203
+ option(:plesk_database_server, block)
204
+ end
205
+
206
+ end
207
+
208
+ end
209
+ end
210
+ end
@@ -0,0 +1,44 @@
1
+
2
+ module Shuttle
3
+ module Actors # :nodoc:
4
+ class Sqlite3Actor < Shuttle::Actor
5
+
6
+ after_install_satellite :write_config_file
7
+
8
+ # write the +database.yml+ config file.
9
+ def write_config_file
10
+ system.as_user(system.web_user, system.web_group) do
11
+
12
+ config = %{# SQLite version 3.x
13
+ # gem install sqlite3-ruby (not necessary on OS X Leopard)
14
+ development:
15
+ adapter: sqlite3
16
+ database: db/system/development.sqlite3
17
+ pool: 5
18
+ timeout: 5000
19
+
20
+ # Warning: The database defined as "test" will be erased and
21
+ # re-generated from your development database when you run "rake".
22
+ # Do not set this db to the same as development or production.
23
+ test:
24
+ adapter: sqlite3
25
+ database: db/system/test.sqlite3
26
+ pool: 5
27
+ timeout: 5000
28
+
29
+ production:
30
+ adapter: sqlite3
31
+ database: db/system/production.sqlite3
32
+ pool: 5
33
+ timeout: 5000
34
+ }
35
+
36
+ db_file = File.join(system.satellite_root, 'config', 'database.yml')
37
+ File.open(db_file, 'w+') { |f| f.write config }
38
+
39
+ end
40
+ end
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,118 @@
1
+ require 'thor'
2
+ require File.dirname(__FILE__)+'/extentions/thor_extentions'
3
+
4
+ module Shuttle
5
+
6
+ # AppRunner allows us to have multiple apps in different namespaces
7
+ class AppRunner < Thor
8
+
9
+ # register a subapplication with the app runner.
10
+ def self.use(app)
11
+ Shuttle::Apps.const_get(app)
12
+ end
13
+
14
+ # Override Thor#help so we can give info about not-yet-loaded tasks
15
+ def help(task = nil)
16
+ super
17
+
18
+ unless task
19
+ search = ".*#{search}" if options["substring"]
20
+ search = /^#{search}.*/i
21
+ group = options[:group] || "standard"
22
+
23
+ classes = Thor.subclasses.select do |k|
24
+ (options[:all] || k.group_name == group) &&
25
+ Thor::Util.constant_to_thor_path(k.name) =~ search
26
+ end
27
+ display_klasses(false, classes)
28
+ end
29
+ end
30
+
31
+ # forward actions to the sub apps
32
+ def method_missing(meth, *args)
33
+ meth = meth.to_s
34
+ super(meth.to_sym, *args) unless meth.include?(?:)
35
+
36
+ begin
37
+ task = Thor[meth]
38
+ task.parse(task.klass.new, ARGV[1..-1])
39
+ rescue => e
40
+ puts e.message
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def display_klasses(with_modules = false, klasses = Thor.subclasses)
47
+ klasses -= [Thor, Shuttle::AppRunner] unless with_modules
48
+ raise Error, "No Thor tasks available" if klasses.empty?
49
+
50
+ if with_modules && !thor_yaml.empty?
51
+ max_name = thor_yaml.max { |(xk, xv), (yk, yv)| xk.to_s.size <=> yk.to_s.size }.first.size
52
+ modules_label = "Modules"
53
+ namespaces_label = "Namespaces"
54
+ column_width = [max_name + 4, modules_label.size + 1].max
55
+
56
+ print "%-#{column_width}s" % modules_label
57
+ puts namespaces_label
58
+ print "%-#{column_width}s" % ("-" * modules_label.size)
59
+ puts "-" * namespaces_label.size
60
+
61
+ thor_yaml.each do |name, info|
62
+ print "%-#{column_width}s" % name
63
+ puts info[:constants].map { |c| Thor::Util.constant_to_thor_path(c) }.join(", ")
64
+ end
65
+
66
+ puts
67
+ end
68
+
69
+ # Calculate the largest base class name
70
+ max_base = klasses.max do |x,y|
71
+ Thor::Util.constant_to_thor_path(x.name).size <=> Thor::Util.constant_to_thor_path(y.name).size
72
+ end.name.size
73
+
74
+ # Calculate the size of the largest option description
75
+ max_left_item = klasses.max do |x,y|
76
+ (x.maxima.usage + x.maxima.opt).to_i <=> (y.maxima.usage + y.maxima.opt).to_i
77
+ end
78
+
79
+ max_left = max_left_item.maxima.usage + max_left_item.maxima.opt
80
+
81
+ unless klasses.empty?
82
+ puts # add some spacing
83
+ klasses.each { |k| display_tasks(k, max_base, max_left); }
84
+ else
85
+ puts "\033[1;34mNo Thor tasks available\033[0m"
86
+ end
87
+ end
88
+
89
+ def display_tasks(klass, max_base, max_left)
90
+ if klass.tasks.values.length > 1
91
+
92
+ base = Thor::Util.constant_to_thor_path(klass.name)
93
+
94
+ if base.to_a.empty?
95
+ base = 'default'
96
+ puts "\033[1;35m#{base}\033[0m"
97
+ else
98
+ puts "\033[1;34m#{base}\033[0m"
99
+ end
100
+
101
+ puts "-" * base.length
102
+
103
+ klass.tasks.each true do |name, task|
104
+ format_string = "%-#{max_left + max_base + 5}s"
105
+ print format_string % task.formatted_usage(true)
106
+ puts task.description
107
+ end
108
+
109
+ unless klass.opts.empty?
110
+ puts "\nglobal options: #{Options.new(klass.opts)}"
111
+ end
112
+
113
+ puts # add some spacing
114
+ end
115
+ end
116
+
117
+ end
118
+ end
@@ -0,0 +1,27 @@
1
+ require 'thor'
2
+
3
+ module Shuttle
4
+ module Apps # :nodoc:
5
+
6
+ class Dev < Thor
7
+ desc "create NAME", "create a new engine"
8
+ def create(name)
9
+ require 'rubigen'
10
+ system("rails #{name}")
11
+
12
+ FileUtils.rm_r("#{name}/doc", :verbose => true)
13
+ FileUtils.rm_r("#{name}/README", :verbose => true)
14
+ FileUtils.rm_r("#{name}/public/javascripts", :verbose => true)
15
+
16
+ require 'rubigen/scripts/generate'
17
+ RubiGen::Base.use_application_sources!
18
+ RubiGen::Scripts::Generate.new.run(["-f", name], :generator => 'engine')
19
+ end
20
+
21
+ desc "link", "link the current development app"
22
+ def link
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,33 @@
1
+ require 'thor'
2
+
3
+ module Shuttle
4
+ module Apps # :nodoc:
5
+
6
+ class Engines < Thor
7
+ desc 'install DOMAIN NAME', 'install an engine'
8
+ method_options :version => :required, :lib => :optional, :source => :optional, :token => :optional
9
+ def install(domain, name)
10
+ desc = { :version => options[:version] }
11
+ desc[:lib] = options[:lib] if options[:lib]
12
+ desc[:source] = options[:source] if options[:source]
13
+ Shuttle.client(options[:token]).install_engine(domain, name, desc)
14
+ end
15
+
16
+ desc 'update DOMAIN NAME', 'update an engine'
17
+ method_options :version => :required, :lib => :optional, :source => :optional, :token => :optional
18
+ def update(domain, name)
19
+ desc = { :version => options[:version] }
20
+ desc[:lib] = options[:lib] if options[:lib]
21
+ desc[:source] = options[:source] if options[:source]
22
+ Shuttle.client(options[:token]).update_engine(domain, name, desc)
23
+ end
24
+
25
+ desc 'uninstall DOMAIN NAME', 'uninstall an engine'
26
+ method_options :token => :optional
27
+ def uninstall(domain, name)
28
+ Shuttle.client(options[:token]).uninstall_engine(domain, name)
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,35 @@
1
+ require 'thor'
2
+
3
+ module Shuttle
4
+ module Apps
5
+ class Jobs < Thor
6
+
7
+ desc "list", 'list the jobs in the queue'
8
+ method_options :token => :optional
9
+ def list
10
+ queued_jobs = Shuttle.client(options[:token]).queued_jobs
11
+ queued_jobs.each do |id, name, canceled, immediated, running, waiting, delay|
12
+ status = []
13
+ status.push canceled ? 'c' : ' '
14
+ status.push immediated ? 'i' : ' '
15
+ status.push running ? 'r' : ' '
16
+ status.push waiting ? 'w' : ' '
17
+ puts("% 8d % 8d % 8s %s" % [id, delay.to_i, status.join, name])
18
+ end
19
+ end
20
+
21
+ desc "cancel ID", 'cancel the job with ID'
22
+ method_options :token => :optional
23
+ def cancel(id)
24
+ Shuttle.client(options[:token]).cancel_job(id.to_i)
25
+ end
26
+
27
+ desc "immediate ID", 'immediately run the job with ID'
28
+ method_options :token => :optional
29
+ def immediate(id)
30
+ Shuttle.client(options[:token]).immediate_job(id.to_i)
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,32 @@
1
+ require 'thor'
2
+
3
+ module Shuttle
4
+ module Apps # :nodoc:
5
+
6
+ class Satellite < Thor
7
+ desc 'list', 'show all managed satellites'
8
+ method_options :token => :optional
9
+ def list
10
+ Shuttle.client(options[:token]).satellites.each do |sat|
11
+ puts sat.domain
12
+ sat.engines.each do |name, options|
13
+ puts "- #{name} #{options.inspect}"
14
+ end
15
+ end
16
+ end
17
+
18
+ desc 'install DOMAIN', 'install a satellite'
19
+ method_options :token => :optional
20
+ def install(domain)
21
+ Shuttle.client(options[:token]).install_satellite(domain)
22
+ end
23
+
24
+ desc 'uninstall DOMAIN', 'uninstall a satellite'
25
+ method_options :token => :optional
26
+ def uninstall(domain)
27
+ Shuttle.client(options[:token]).uninstall_satellite(domain)
28
+ end
29
+ end
30
+
31
+ end
32
+ end
@@ -0,0 +1,70 @@
1
+ require 'thor'
2
+ require 'simple-daemon'
3
+
4
+ module Shuttle
5
+ module Apps
6
+
7
+ class Server < Thor
8
+
9
+ desc "start", 'start the server'
10
+ method_options :foreground => :boolean, :config => :optional
11
+ def start
12
+ Shuttle.server? true
13
+ Shuttle::System.load!(options[:root_path])
14
+
15
+ begin
16
+ FileUtils.mkdir_p(Shuttle.system.root)
17
+ rescue Errno::EACCES
18
+ Shuttle.logger.out.fatal "must be executed as root"
19
+ exit(1)
20
+ end
21
+
22
+ unless Shuttle.system.is_user('root')
23
+ Shuttle.logger.out.fatal "must be executed as root"
24
+ exit(1)
25
+ end
26
+
27
+ SimpleDaemon.const_set 'WORKING_DIRECTORY', Shuttle.system.root
28
+ if options[:foreground]
29
+ Shuttle::Server.start
30
+ else
31
+ ARGV.clear and ARGV.concat(%w( start ))
32
+ Shuttle::Server.daemonize
33
+ end
34
+ end
35
+
36
+ desc "stop", 'stop the server'
37
+ method_options :token => :optional
38
+ def stop
39
+ Shuttle.client(options[:token]).stop_server
40
+ end
41
+
42
+ desc "restart", 'restart the server'
43
+ method_options :token => :optional
44
+ def restart
45
+ Shuttle.client(options[:token]).restart_server
46
+ end
47
+
48
+ desc "reload", 'reload the server'
49
+ method_options :token => :optional
50
+ def reload
51
+ Shuttle.client(options[:token]).reload_server
52
+ end
53
+
54
+ desc "update", 'update the shuttle'
55
+ method_options :token => :optional
56
+ def update
57
+ Shuttle.client(options[:token]).update_server
58
+ end
59
+
60
+ desc "version", 'version of the server'
61
+ method_options :token => :optional
62
+ def version
63
+ puts "Client: #{Shuttle.version}"
64
+ puts "Server: #{Shuttle.client(options[:token]).server_version}"
65
+ end
66
+
67
+ end
68
+
69
+ end
70
+ end
@@ -0,0 +1,98 @@
1
+ require 'yaml'
2
+
3
+ module Shuttle
4
+ class Client
5
+ class AuthToken
6
+
7
+ # load a token from the passed IO.
8
+ def self.load(io)
9
+ self.new YAML.load(io)
10
+ end
11
+
12
+ # load a token from a file referenced by the given +path+.
13
+ def self.load_file(path)
14
+ self.new YAML.load_file(path)
15
+ end
16
+
17
+ # the uri at which the shuttle server can be accessed.
18
+ attr_reader :target_uri
19
+ # the SSL verification mode used by the shuttle server
20
+ attr_reader :verify_mode
21
+ # the optional CA certificate used by the shuttle server
22
+ attr_reader :ca_certificate_data
23
+ # the private key used by the client
24
+ attr_reader :private_key_data
25
+ # the certificate used by the client
26
+ attr_reader :certificate_data
27
+
28
+ # create a new token from the given options
29
+ #
30
+ # +:target_uri+, +:verify_mode+, +:ca_certificate_data+, +:private_key_data+, +:certificate_data+
31
+ def initialize(options={})
32
+ @target_uri = options[:target_uri]
33
+ @verify_mode = options[:verify_mode]
34
+ @ca_certificate_data = options[:ca_certificate_data]
35
+ @private_key_data = options[:private_key_data]
36
+ @certificate_data = options[:certificate_data]
37
+ end
38
+
39
+ # get the parsed and initialized OpenSSL::X509::Certificate
40
+ def ca_certificate
41
+ @ca_certificate ||= OpenSSL::X509::Certificate.new(@ca_certificate_data)
42
+ end
43
+
44
+ # get the parsed and initialized OpenSSL::X509::Certificate
45
+ def certificate
46
+ @certificate ||= OpenSSL::X509::Certificate.new(@certificate_data)
47
+ end
48
+
49
+ # get the parsed and initialized OpenSSL::PKey::RSA
50
+ def private_key
51
+ @private_key ||= OpenSSL::PKey::RSA.new(@private_key_data)
52
+ end
53
+
54
+ # connect to the server and return the server handle.
55
+ def connect
56
+ use_ssl, uri = Shuttle::Client.parse_uri(self.target_uri)
57
+ if use_ssl
58
+ DRb.start_service nil, nil, self.options_for_drb
59
+ else
60
+ DRb.start_service
61
+ end
62
+ DRbObject.new nil, uri
63
+ end
64
+
65
+ # return options for use with DRb
66
+ def options_for_drb
67
+ @options_for_drb ||= {
68
+ :SSLVerifyMode => self.verify_mode,
69
+ :SSLCACertificate => self.ca_certificate,
70
+ :SSLPrivateKey => self.private_key,
71
+ :SSLCertificate => self.certificate
72
+ }
73
+ end
74
+
75
+ # dump this token to the given IO or return the content as a String
76
+ def dump(io=nil)
77
+ data = {
78
+ :target_uri => self.target_uri,
79
+ :verify_mode => self.verify_mode,
80
+ :ca_certificate_data => self.ca_certificate_data,
81
+ :private_key_data => self.private_key_data,
82
+ :certificate_data => self.certificate_data
83
+ }
84
+ if io
85
+ io.write YAML.dump(data)
86
+ else
87
+ YAML.dump(data)
88
+ end
89
+ end
90
+
91
+ # dump this token to a file at the given +path+.
92
+ def dump_file(path)
93
+ File.open(path, 'w+') { |f| dump(f) }
94
+ end
95
+
96
+ end
97
+ end
98
+ end