spiderfw 0.6.6 → 0.6.7
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/CHANGELOG +4 -0
- data/VERSION +1 -1
- data/apps/master/_init.rb +2 -0
- data/apps/master/controllers/master_controller.rb +81 -24
- data/apps/master/models/command.rb +12 -5
- data/apps/master/models/event.rb +9 -0
- data/apps/master/views/installation.shtml +22 -0
- data/apps/servant/lib/client.rb +21 -7
- data/apps/servant/lib/commands_processor.rb +109 -0
- data/apps/servant/servant.rb +10 -0
- data/lib/spiderfw/cmd/commands/app.rb +25 -82
- data/lib/spiderfw/config/options/spider.rb +1 -1
- data/lib/spiderfw/controller/controller_exceptions.rb +3 -0
- data/lib/spiderfw/controller/first_responder.rb +5 -0
- data/lib/spiderfw/controller/home_controller.rb +1 -1
- data/lib/spiderfw/controller/mixins/http_mixin.rb +5 -2
- data/lib/spiderfw/controller/mixins/visual.rb +27 -12
- data/lib/spiderfw/http/server.rb +0 -1
- data/lib/spiderfw/setup/app_manager.rb +125 -2
- data/lib/spiderfw/spider.rb +23 -4
- data/views/errors/404.shtml +3 -0
- data/views/errors/simple.layout.shtml +16 -0
- data/views/generic.layout.shtml +16 -0
- data/views/maintenance.shtml +6 -0
- metadata +9 -4
data/CHANGELOG
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.6.
|
1
|
+
0.6.7
|
data/apps/master/_init.rb
CHANGED
@@ -14,6 +14,8 @@ require 'apps/master/master'
|
|
14
14
|
require 'apps/master/models/admin'
|
15
15
|
require 'apps/master/models/customer'
|
16
16
|
require 'apps/master/models/installation'
|
17
|
+
require 'apps/master/models/command'
|
18
|
+
require 'apps/master/models/event'
|
17
19
|
require 'apps/master/models/remote_log'
|
18
20
|
require 'apps/master/models/server'
|
19
21
|
require 'apps/master/models/scout_plugin_info'
|
@@ -18,7 +18,7 @@ module Spider; module Master
|
|
18
18
|
#route /servers\/([^\/]+)/, ServerController, :do => lambda{ |id| @request.misc[:server] = Server.new(id) }
|
19
19
|
route 'login', LoginController
|
20
20
|
|
21
|
-
require_user Master::Admin, :unless => [:login, :admin, :ping], :redirect => 'login'
|
21
|
+
require_user Master::Admin, :unless => [:login, :admin, :ping, :servant_event], :redirect => 'login'
|
22
22
|
require_user Spider::Auth::SuperUser, :only => [:admin]
|
23
23
|
|
24
24
|
|
@@ -118,28 +118,34 @@ module Spider; module Master
|
|
118
118
|
@installation = Installation.new(id) unless id == 'new'
|
119
119
|
@scene.edit = (@request.params['_w'] && @request.params['_w'].key?('installation_form')) || @request.params.key?('edit') || id == 'new'
|
120
120
|
@scene.pk = id
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
121
|
+
|
122
|
+
if @request.params['add_command']
|
123
|
+
command = @request.params['command']
|
124
|
+
args = @request.params['arguments']
|
125
|
+
arguments = args
|
126
|
+
# FIXME: move somewhere else
|
127
|
+
case command
|
128
|
+
when 'gems', 'apps'
|
129
|
+
arguments = args.split(/\s*,\s*/).to_json
|
130
|
+
end
|
131
|
+
Master::Command.create(
|
132
|
+
:installation => @installation,
|
133
|
+
:name => @request.params['command'],
|
134
|
+
:arguments => arguments,
|
135
|
+
:status => 'pending'
|
136
|
+
)
|
137
|
+
redirect(@request.path)
|
138
|
+
|
139
|
+
end
|
139
140
|
@scene.install_apps = JSON.parse(@installation.apps) unless @installation.apps.blank?
|
140
141
|
@scene.install_apps ||= []
|
141
142
|
@scene.apps = Spider::AppServer.apps_by_id
|
142
143
|
@scene.logs = RemoteLog.where(:installation => @installation)
|
144
|
+
@scene.commands = Master::Command.where{ |c| (c.installation == @installation) }.order_by(:obj_created)
|
145
|
+
@scene.available_commands = {
|
146
|
+
'gems' => _('Install or update gems'),
|
147
|
+
'apps' => _('Install or update apps')
|
148
|
+
}
|
143
149
|
@scene << {
|
144
150
|
:customer => @customer,
|
145
151
|
:installation => @installation
|
@@ -345,15 +351,66 @@ module Spider; module Master
|
|
345
351
|
RemoteLog.create(:text => desc, :level => level, :time => time, :installation => install)
|
346
352
|
end
|
347
353
|
response = {
|
348
|
-
:pong => DateTime.
|
354
|
+
:pong => DateTime.now
|
349
355
|
}
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
356
|
+
commands = []
|
357
|
+
Master::Command.where{ |c| (c.installation == install) & (c.status == 'pending') }.each do |c|
|
358
|
+
commands << {
|
359
|
+
:id => c.uuid,
|
360
|
+
:name => c.name,
|
361
|
+
:arguments => c.arguments ? JSON.parse(c.arguments) : nil
|
362
|
+
}
|
363
|
+
end
|
364
|
+
response[:commands] = commands unless commands.empty?
|
354
365
|
$out << response.to_json
|
366
|
+
Master::Command.where{ |c| (c.installation == install) & (c.status == 'pending') }.each do |c|
|
367
|
+
c.sent = DateTime.now
|
368
|
+
c.status = 'sent'
|
369
|
+
c.save
|
370
|
+
end
|
355
371
|
end
|
356
372
|
|
373
|
+
__.json
|
374
|
+
def servant_event
|
375
|
+
params = @request.params.clone
|
376
|
+
name = params.delete('event')
|
377
|
+
install_id = params.delete('install_id')
|
378
|
+
unless install_id
|
379
|
+
Spider.logger.error("No install_id passed in ping")
|
380
|
+
done
|
381
|
+
end
|
382
|
+
install = Spider::Master::Installation.load_or_create(:uuid => install_id)
|
383
|
+
details = @request.params['details']
|
384
|
+
params = JSON.parse(details)
|
385
|
+
Event.create(
|
386
|
+
:installation => install,
|
387
|
+
:name => name,
|
388
|
+
:details => details
|
389
|
+
)
|
390
|
+
case name.to_sym
|
391
|
+
when :command_done
|
392
|
+
cmd = Master::Command.load(:uuid => params['id'])
|
393
|
+
cmd.done = DateTime.now
|
394
|
+
cmd.result = params['res'].to_json
|
395
|
+
cmd.status = 'success'
|
396
|
+
cmd.save
|
397
|
+
when :plan_done
|
398
|
+
results = params['results']
|
399
|
+
results.each do |res|
|
400
|
+
cmd = Master::Command.load(:uuid => res['command_id'])
|
401
|
+
if res['previous_error']
|
402
|
+
cmd.status = 'not_done'
|
403
|
+
cmd.save
|
404
|
+
elsif res['error']
|
405
|
+
cmd.status = 'error'
|
406
|
+
cmd.save
|
407
|
+
end
|
408
|
+
end
|
409
|
+
end
|
410
|
+
end
|
411
|
+
|
412
|
+
|
413
|
+
|
357
414
|
private
|
358
415
|
|
359
416
|
def decompress_string(str)
|
@@ -1,17 +1,24 @@
|
|
1
1
|
module Spider; module Master
|
2
2
|
|
3
|
-
class Command < Spider::Model::
|
4
|
-
|
5
|
-
element :
|
3
|
+
class Command < Spider::Model::Managed
|
4
|
+
element :installation, Installation, :add_multiple_reverse => :commands
|
5
|
+
element :uuid, UUID
|
6
6
|
element :name, String
|
7
7
|
element :arguments, Text
|
8
8
|
element :status, {
|
9
9
|
'pending' => 'Pending',
|
10
|
+
'sent' => 'Sent',
|
10
11
|
'success' => 'Success',
|
11
|
-
'failure' => 'Failure'
|
12
|
+
'failure' => 'Failure',
|
13
|
+
'not_done' => 'Not done'
|
12
14
|
}, :default => 'pending'
|
13
|
-
element :
|
15
|
+
element :sent, DateTime
|
16
|
+
element :done, DateTime
|
14
17
|
element :result, Text
|
18
|
+
|
19
|
+
def to_s
|
20
|
+
"#{self.name} '#{self.arguments}' - #{self.status}"
|
21
|
+
end
|
15
22
|
end
|
16
23
|
|
17
24
|
end; end
|
@@ -20,6 +20,12 @@
|
|
20
20
|
<h2>_(Installation "%s") % [@installation]</h2>
|
21
21
|
<a href="?edit" class="manage edit">_(Edit)</a>
|
22
22
|
</div>
|
23
|
+
<div class="details">
|
24
|
+
_(Last check-in): { @installation.last_check.lformat(:short) }
|
25
|
+
<tpl:pass sp:if="@installation.interval">
|
26
|
+
_(Next check-in): { (@installation.last_check + @installation.interval).lformat(:short) }
|
27
|
+
</tpl:pass>
|
28
|
+
</div>
|
23
29
|
<core:tabs id="tabs">
|
24
30
|
<tab label="_(Apps)" id="apps">
|
25
31
|
<div class="apps">
|
@@ -43,6 +49,22 @@
|
|
43
49
|
<core:table id="logs_table" queryset="@logs" sort="time,desc" />
|
44
50
|
</div>
|
45
51
|
</tab>
|
52
|
+
<tab label="_(Commands)" id="commands">
|
53
|
+
<div class="commands">
|
54
|
+
<h4>_(Commands)</h4><a href="#" class="manage add">_(Add command)</a>
|
55
|
+
<div id="add_command">
|
56
|
+
<form>
|
57
|
+
<select name="command">
|
58
|
+
<option></option>
|
59
|
+
<option sp:each="@available_commands |k, v|" value="{ k }">{ v }</option>
|
60
|
+
</select>
|
61
|
+
<input type="text" name="arguments">
|
62
|
+
<input type="submit" name="add_command" value="_(Ok)">
|
63
|
+
</form>
|
64
|
+
</div>
|
65
|
+
<core:list id="commands_list" queryset="@commands" delete="true" />
|
66
|
+
</div>
|
67
|
+
</tab>
|
46
68
|
</core:tabs>
|
47
69
|
</div>
|
48
70
|
</div>
|
data/apps/servant/lib/client.rb
CHANGED
@@ -10,9 +10,14 @@ module Spider
|
|
10
10
|
def initialize(url)
|
11
11
|
@url = url
|
12
12
|
end
|
13
|
+
|
14
|
+
def http_client
|
15
|
+
HTTPClient.new
|
16
|
+
end
|
13
17
|
|
14
|
-
def ping_server(url
|
15
|
-
|
18
|
+
def ping_server(url=nil)
|
19
|
+
url ||= @url
|
20
|
+
clnt = self.http_client
|
16
21
|
status = Servant.status
|
17
22
|
status[:apps] = status[:apps].to_json
|
18
23
|
last_check_file = File.join(Spider.paths[:var], 'memory', 'servant_last_check')
|
@@ -29,15 +34,24 @@ module Spider
|
|
29
34
|
end
|
30
35
|
File.open(last_check_file, 'w'){ |f| f << Time.now.to_s }
|
31
36
|
res = JSON.parse(res.content)
|
32
|
-
if res[
|
33
|
-
|
34
|
-
|
35
|
-
clnt.post()
|
36
|
-
end
|
37
|
+
if res['commands']
|
38
|
+
processor = Servant.command_processor.new(url)
|
39
|
+
processor.run_commands(res['commands'])
|
37
40
|
end
|
38
41
|
end
|
39
42
|
|
43
|
+
def process_commands(commands)
|
44
|
+
end
|
45
|
+
|
46
|
+
def send_event(name, details)
|
47
|
+
self.http_client.post("#{@url}/servant_event", {
|
48
|
+
:event => name, :install_id => Servant.install_id, :details => details.to_json
|
49
|
+
})
|
50
|
+
end
|
51
|
+
|
52
|
+
|
40
53
|
private
|
54
|
+
|
41
55
|
|
42
56
|
def compress_string(str)
|
43
57
|
compr = ""
|
@@ -0,0 +1,109 @@
|
|
1
|
+
module Spider; module Servant
|
2
|
+
|
3
|
+
class CommandsProcessor
|
4
|
+
attr_reader :client
|
5
|
+
|
6
|
+
def self.plan_file
|
7
|
+
File.join(Spider.paths[:var], 'servant_command_plan')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.progress_file
|
11
|
+
File.join(Spider.paths[:var], 'servant_command_progress')
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.save_plan(commands)
|
15
|
+
File.open(self.plan_file, 'w'){ |f| f << commands.to_json }
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.read_plan
|
19
|
+
return nil unless File.exists?(self.plan_file)
|
20
|
+
JSON.parse(File.readfile(self.plan_file))
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.unfinished_plan?
|
24
|
+
File.exists?(self.plan_file)
|
25
|
+
end
|
26
|
+
|
27
|
+
def initialize(master_url)
|
28
|
+
@url = master_url
|
29
|
+
@client = Servant::Client.new(@url)
|
30
|
+
@progress = {}
|
31
|
+
end
|
32
|
+
|
33
|
+
def resume_plan
|
34
|
+
plan = self.class.read_plan
|
35
|
+
progress = JSON.parse(File.read(self.progress_file)) if File.exists?(self.progress_file)
|
36
|
+
progress ||= {}
|
37
|
+
plan.reject!{ |c| progress[c['id']] }
|
38
|
+
process_commands(plan)
|
39
|
+
end
|
40
|
+
|
41
|
+
def save_progress
|
42
|
+
File.open(self.class.progress_file, 'w'){ |f| f << @progress.to_json }
|
43
|
+
end
|
44
|
+
|
45
|
+
def run_commands(commands)
|
46
|
+
self.class.save_plan(commands)
|
47
|
+
process_commands(commands)
|
48
|
+
end
|
49
|
+
|
50
|
+
def process_commands(commands)
|
51
|
+
results = []
|
52
|
+
error = nil
|
53
|
+
commands.each do |command|
|
54
|
+
command_result = {:command_id => command['id']}
|
55
|
+
if error
|
56
|
+
command_result[:previous_error] = true
|
57
|
+
else
|
58
|
+
begin
|
59
|
+
command_result[:res] = execute_command(command)
|
60
|
+
rescue => exc
|
61
|
+
error = exc.message
|
62
|
+
command_result[:error] = error
|
63
|
+
end
|
64
|
+
end
|
65
|
+
results << command_result
|
66
|
+
end
|
67
|
+
self.client.send_event(:plan_done, {:results => results})
|
68
|
+
File.unlink(self.class.plan_file) if File.exists?(self.class.plan_file)
|
69
|
+
File.unlink(self.class.progress_file) if File.exists?(self.class.progress_file)
|
70
|
+
end
|
71
|
+
|
72
|
+
def execute_command(command)
|
73
|
+
args = command["arguments"]
|
74
|
+
res = case command["name"]
|
75
|
+
when "gems"
|
76
|
+
install_gems(args)
|
77
|
+
when "apps"
|
78
|
+
install_apps(args)
|
79
|
+
when "configure"
|
80
|
+
|
81
|
+
end
|
82
|
+
@progress[command['id']] = true
|
83
|
+
save_progress
|
84
|
+
self.client.send_event(:command_done, {:id => command['id'], :res => res})
|
85
|
+
res
|
86
|
+
end
|
87
|
+
|
88
|
+
def install_gems(gems)
|
89
|
+
inst = Gem::DependencyInstaller.new
|
90
|
+
installed = []
|
91
|
+
gems.each do |g|
|
92
|
+
v = g['version'] || Gem::Requirement.default
|
93
|
+
unless Gem.available?(g['name'], v)
|
94
|
+
inst.install g['name'], v
|
95
|
+
installed << g
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
return {:installed => gems}
|
100
|
+
end
|
101
|
+
|
102
|
+
def install_apps(apps)
|
103
|
+
require 'spiderfw/setup/app_manager'
|
104
|
+
Spider::AppManager.install_or_update(apps)
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
109
|
+
end; end
|
data/apps/servant/servant.rb
CHANGED
@@ -1,9 +1,19 @@
|
|
1
1
|
require 'uuidtools'
|
2
|
+
require 'apps/servant/lib/client'
|
3
|
+
require 'apps/servant/lib/commands_processor'
|
2
4
|
|
3
5
|
module Spider
|
4
6
|
|
5
7
|
module Servant
|
8
|
+
|
9
|
+
def self.command_processor
|
10
|
+
@command_processor ||= Spider::Servant::CommandsProcessor
|
11
|
+
end
|
6
12
|
|
13
|
+
def self.command_processor=(klass)
|
14
|
+
@command_processor = klass
|
15
|
+
end
|
16
|
+
|
7
17
|
def self.install_id
|
8
18
|
uuid_file = File.join(Spider.paths[:var], 'install_id')
|
9
19
|
return File.read(uuid_file) if File.exists?(uuid_file)
|
@@ -5,7 +5,6 @@ class AppCommand < CmdParse::Command
|
|
5
5
|
super('app', true, true )
|
6
6
|
@short_desc = _("Manage apps")
|
7
7
|
|
8
|
-
@server_url = 'http://www.soluzionipa.it/euroservizi/spider/app_server'
|
9
8
|
|
10
9
|
self.options = CmdParse::OptionParserWrapper.new do |opt|
|
11
10
|
opt.on("--proxy [SERVER]", _("Proxy server to use (http://user:pass@host:port)"), "-p"){ |p|
|
@@ -57,6 +56,11 @@ class AppCommand < CmdParse::Command
|
|
57
56
|
end
|
58
57
|
if @remote
|
59
58
|
require 'spiderfw/setup/app_server_client'
|
59
|
+
unless @server_url
|
60
|
+
require 'spiderfw/spider'
|
61
|
+
Spider.init_base
|
62
|
+
@server_url = Spider.config.get('app_server.url')
|
63
|
+
end
|
60
64
|
client = Spider::AppServerClient.new(@server_url)
|
61
65
|
remote = {}
|
62
66
|
client.specs.each do |app|
|
@@ -119,56 +123,26 @@ class AppCommand < CmdParse::Command
|
|
119
123
|
puts _("Please execute this command from the home folder")
|
120
124
|
exit
|
121
125
|
end
|
122
|
-
require 'spiderfw/setup/app_server_client'
|
123
|
-
use_git = false
|
124
|
-
unless @no_git
|
125
|
-
begin
|
126
|
-
require 'grit'
|
127
|
-
use_git = true
|
128
|
-
rescue => exc
|
129
|
-
puts exc.message
|
130
|
-
puts "Grit not available; install Grit for Git support"
|
131
|
-
end
|
132
|
-
end
|
133
|
-
|
134
|
-
apps = args
|
135
|
-
existent = []
|
136
|
-
apps.each do |app|
|
137
|
-
if File.exist?("apps/#{app}")
|
138
|
-
puts _("%s already exists, skipping") % app
|
139
|
-
existent << app
|
140
|
-
end
|
141
|
-
end
|
142
126
|
require 'spiderfw/setup/app_manager'
|
143
|
-
specs = []
|
144
|
-
client = Spider::AppServerClient.new(@server_url)
|
145
|
-
if @no_deps
|
146
|
-
specs = client.get_specs(apps)
|
147
|
-
else
|
148
|
-
specs = client.get_deps(apps, :no_optional => @no_optional)
|
149
|
-
end
|
150
|
-
deps = specs.map{ |s| s.app_id }
|
151
|
-
unless (deps - apps).empty?
|
152
|
-
puts _("The following apps will be installed as a dependency:")
|
153
|
-
puts (deps - apps).inspect
|
154
|
-
end
|
155
127
|
options = {
|
156
|
-
:
|
157
|
-
:no_gems => @no_gems,
|
158
|
-
:no_optional_gems => @no_optional_gems
|
128
|
+
:no_git => @no_git, :all => @all, :no_deps => @no_deps, :no_optional => @no_optional,
|
129
|
+
:no_gems => @no_gems, :no_optional_gems => @no_optional_gems, :no_activate => @no_activate
|
159
130
|
}
|
160
|
-
options[:
|
161
|
-
|
162
|
-
Spider::AppManager.install(inst_specs, Dir.pwd, options)
|
163
|
-
unless @no_activate
|
164
|
-
require 'spiderfw/spider'
|
165
|
-
specs_hash = {}
|
166
|
-
specs.each{ |s| specs_hash[s.app_id] = s }
|
167
|
-
Spider.activate_apps(deps, specs_hash)
|
168
|
-
end
|
131
|
+
options[:url] = @server_url if @server_url
|
132
|
+
Spider::AppManager.install_apps(args, options)
|
169
133
|
end
|
170
134
|
self.add_command(install)
|
171
135
|
|
136
|
+
activate = CmdParse::Command.new('activate', false )
|
137
|
+
activate.short_desc = _("Activate an app")
|
138
|
+
activate.set_execution_block do |args|
|
139
|
+
apps = args
|
140
|
+
require 'spiderfw/spider'
|
141
|
+
apps = Spider.get_app_deps(apps)
|
142
|
+
Spider.activate_apps(apps)
|
143
|
+
end
|
144
|
+
self.add_command(activate)
|
145
|
+
|
172
146
|
update = CmdParse::Command.new( 'update', false )
|
173
147
|
update.short_desc = _("Update an app")
|
174
148
|
update.options = CmdParse::OptionParserWrapper.new do |opt|
|
@@ -188,44 +162,13 @@ class AppCommand < CmdParse::Command
|
|
188
162
|
puts _("Please execute this command from the home folder")
|
189
163
|
exit
|
190
164
|
end
|
191
|
-
require 'spiderfw/setup/app_server_client'
|
192
|
-
use_git = false
|
193
|
-
unless @no_git
|
194
|
-
begin
|
195
|
-
require 'grit'
|
196
|
-
use_git = true
|
197
|
-
rescue
|
198
|
-
puts "Grit not available; install Grit for Git support"
|
199
|
-
end
|
200
|
-
end
|
201
|
-
apps = args
|
202
|
-
if @all
|
203
|
-
require 'spiderfw/home'
|
204
|
-
home = Spider::Home.new(Dir.pwd)
|
205
|
-
apps = home.list_apps
|
206
|
-
end
|
207
|
-
if apps.empty?
|
208
|
-
puts _("No app to update")
|
209
|
-
exit
|
210
|
-
end
|
211
165
|
require 'spiderfw/setup/app_manager'
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
end
|
219
|
-
deps = specs.map{ |s| s.app_id }
|
220
|
-
unless (deps - apps).empty?
|
221
|
-
puts _("The following apps will be updated as a dependency:")
|
222
|
-
puts (deps - apps).inspect
|
223
|
-
end
|
224
|
-
Spider::AppManager.update(specs, Dir.pwd, {
|
225
|
-
:use_git => use_git,
|
226
|
-
:no_gems => @no_gems,
|
227
|
-
:no_optional_gems => @no_optional_gems
|
228
|
-
})
|
166
|
+
options = {
|
167
|
+
:no_git => @no_git, :all => @all, :no_deps => @no_deps, :no_optional => @no_optional,
|
168
|
+
:no_gems => @no_gems, :no_optional_gems => @no_optional_gems
|
169
|
+
}
|
170
|
+
options[:url] = @server_url if @server_url
|
171
|
+
Spider::AppManager.update_apps(args, options)
|
229
172
|
end
|
230
173
|
self.add_command(update)
|
231
174
|
|
@@ -33,7 +33,7 @@ module Spider
|
|
33
33
|
:default => Proc.new{ RUBY_VERSION_PARTS[1] == '8' && !Object.const_defined?(:PhusionPassenger) ? true : false }
|
34
34
|
config_option 'webserver.timeout', _("Time allowed for each request (in seconds)"), :type=> Fixnum, :default => nil
|
35
35
|
config_option 'webserver.respawn_on_change', _("Restart the webserver when application code changes"), :type => Spider::Bool,
|
36
|
-
:default => Proc.new{ Spider.config.get('runmode') == 'devel' ? true : false }
|
36
|
+
:default => Proc.new{ RUBY_PLATFORM !~ /win32|mingw32/ && Spider.config.get('runmode') == 'devel' ? true : false }
|
37
37
|
config_option 'static_content.mode', _("Mode to use for serving static files"), :type => String,
|
38
38
|
:choices => [nil, 'x-sendfile', 'x-accel-redirect', 'published'], :default => nil
|
39
39
|
config_option 'static_content.auto_publish', _("Automatically publish content to the home's public folder"),
|
@@ -89,9 +89,13 @@ module Spider; module ControllerMixins
|
|
89
89
|
super
|
90
90
|
end
|
91
91
|
|
92
|
-
def base_url
|
92
|
+
def self.base_url
|
93
93
|
HTTPMixin.reverse_proxy_mapping("")
|
94
94
|
end
|
95
|
+
|
96
|
+
def base_url
|
97
|
+
self.class.base_url
|
98
|
+
end
|
95
99
|
|
96
100
|
def prepare_scene(scene)
|
97
101
|
scene = super
|
@@ -101,7 +105,6 @@ module Spider; module ControllerMixins
|
|
101
105
|
end
|
102
106
|
|
103
107
|
def try_rescue(exc)
|
104
|
-
self.done = true
|
105
108
|
if (exc.is_a?(Spider::Controller::NotFound))
|
106
109
|
@response.status = Spider::HTTP::NOT_FOUND
|
107
110
|
elsif (exc.is_a?(Spider::Controller::BadRequest))
|
@@ -40,6 +40,9 @@ module Spider; module ControllerMixins
|
|
40
40
|
output_format_headers(format)
|
41
41
|
@executed_format = format
|
42
42
|
@executed_format_params = format_params
|
43
|
+
if Spider.runmode != 'devel' && File.exists?(File.join(Spider.paths[:tmp], 'maintenance.txt'))
|
44
|
+
raise Spider::Controller::Maintenance
|
45
|
+
end
|
43
46
|
super
|
44
47
|
end
|
45
48
|
|
@@ -182,7 +185,7 @@ module Spider; module ControllerMixins
|
|
182
185
|
def render(path=nil, options={})
|
183
186
|
scene = options[:scene] || @scene
|
184
187
|
scene ||= get_scene
|
185
|
-
scene = prepare_scene(scene)
|
188
|
+
scene = prepare_scene(scene) unless options[:no_prepare_scene]
|
186
189
|
request = options[:request] || @request
|
187
190
|
response = options[:response] || @response
|
188
191
|
if (path.is_a?(Spider::Template))
|
@@ -215,6 +218,11 @@ module Spider; module ControllerMixins
|
|
215
218
|
return template
|
216
219
|
end
|
217
220
|
|
221
|
+
def render_error(path, options)
|
222
|
+
options[:no_prepare_scene] = true
|
223
|
+
render(path, options)
|
224
|
+
end
|
225
|
+
|
218
226
|
def find_widget(name)
|
219
227
|
@template.find_widget(name)
|
220
228
|
end
|
@@ -239,19 +247,26 @@ module Spider; module ControllerMixins
|
|
239
247
|
return obj
|
240
248
|
end
|
241
249
|
|
242
|
-
def try_rescue(exc)
|
250
|
+
def try_rescue(exc)
|
243
251
|
exc.uuid = UUIDTools::UUID.random_create.to_s if exc.respond_to?(:uuid=)
|
244
252
|
format = self.class.output_format(:error) || :html
|
245
|
-
|
246
|
-
|
247
|
-
|
253
|
+
unless exc.is_a?(Spider::Controller::Maintenance) || exc.is_a?(Spider::Controller::NotFound)
|
254
|
+
return super unless @executed_format == :html
|
255
|
+
return super unless action_target?
|
256
|
+
return super if target_mode?
|
257
|
+
end
|
248
258
|
output_format_headers(format)
|
249
|
-
|
250
|
-
|
259
|
+
layout = 'errors/error'
|
260
|
+
if exc.is_a?(Spider::Controller::Maintenance)
|
261
|
+
error_page = 'maintenance'
|
262
|
+
layout = 'generic'
|
263
|
+
elsif exc.is_a?(Spider::Controller::NotFound)
|
264
|
+
error_page = 'errors/404'
|
265
|
+
layout = 'errors/simple'
|
251
266
|
@scene.error_msg = _("Page not found")
|
252
267
|
@scene.email_subject = @scene.error_msg
|
253
268
|
else
|
254
|
-
error_page = 'error_generic'
|
269
|
+
error_page = 'errors/error_generic'
|
255
270
|
if (exc.is_a?(HTTPMixin::HTTPStatus))
|
256
271
|
@scene.error_msg = exc.status_message
|
257
272
|
end
|
@@ -259,13 +274,13 @@ module Spider; module ControllerMixins
|
|
259
274
|
@scene.email_subject = @scene.error_msg
|
260
275
|
end
|
261
276
|
|
262
|
-
if
|
277
|
+
if exc.respond_to?(:uuid)
|
263
278
|
exc.extend(UUIDExceptionMessage)
|
264
279
|
@scene.exception_uuid = exc.uuid
|
265
|
-
@scene.email_subject += " (#{exc.uuid})"
|
280
|
+
@scene.email_subject += " (#{exc.uuid})" if @scene.email_subject
|
266
281
|
end
|
267
282
|
@scene.admin_email = Spider.conf.get('site.tech_admin.email')
|
268
|
-
if
|
283
|
+
if Spider.runmode == 'devel'
|
269
284
|
begin
|
270
285
|
@scene.devel = true
|
271
286
|
@scene.backtrace = build_backtrace(exc)
|
@@ -294,7 +309,7 @@ module Spider; module ControllerMixins
|
|
294
309
|
rescue => exc2
|
295
310
|
end
|
296
311
|
end
|
297
|
-
|
312
|
+
render_error "#{error_page}", :layout => layout
|
298
313
|
super
|
299
314
|
end
|
300
315
|
|
data/lib/spiderfw/http/server.rb
CHANGED
@@ -4,6 +4,129 @@ require 'fileutils'
|
|
4
4
|
module Spider
|
5
5
|
|
6
6
|
module AppManager
|
7
|
+
|
8
|
+
def self.install_or_update(apps, options={})
|
9
|
+
require 'spiderfw/home'
|
10
|
+
home = Spider::Home.new(Dir.pwd)
|
11
|
+
installed = {}
|
12
|
+
Spider.init_base
|
13
|
+
active = Spider.config.get('apps')
|
14
|
+
Spider.home.apps.each do |app, info|
|
15
|
+
installed[app] = {
|
16
|
+
:active => active.include?(app)
|
17
|
+
}
|
18
|
+
if spec = info[:spec]
|
19
|
+
installed[app].merge!({
|
20
|
+
:version => spec.version
|
21
|
+
})
|
22
|
+
end
|
23
|
+
end
|
24
|
+
to_inst = apps.select{ |a| !installed[a] }
|
25
|
+
to_upd = apps.select{ |a| installed[a] }
|
26
|
+
install_apps(to_inst, options)
|
27
|
+
update_apps(to_upd, options)
|
28
|
+
return {:installed => to_inst, :updated => to_upd}
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.install_apps(apps, options={})
|
32
|
+
return if apps.empty?
|
33
|
+
require 'spiderfw/setup/app_server_client'
|
34
|
+
use_git = false
|
35
|
+
unless options[:no_git]
|
36
|
+
begin
|
37
|
+
require 'grit'
|
38
|
+
use_git = true
|
39
|
+
rescue => exc
|
40
|
+
puts exc.message
|
41
|
+
puts "Grit not available; install Grit for Git support"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
existent = []
|
46
|
+
apps.each do |app|
|
47
|
+
if File.exist?("apps/#{app}")
|
48
|
+
puts _("%s already exists, skipping") % app
|
49
|
+
existent << app
|
50
|
+
end
|
51
|
+
end
|
52
|
+
require 'spiderfw/setup/app_manager'
|
53
|
+
specs = []
|
54
|
+
url = options[:url]
|
55
|
+
unless url
|
56
|
+
require 'spiderfw/spider'
|
57
|
+
Spider.init_base
|
58
|
+
url = Spider.config.get('app_server.url')
|
59
|
+
end
|
60
|
+
client = Spider::AppServerClient.new(url)
|
61
|
+
if options[:no_deps]
|
62
|
+
specs = client.get_specs(apps)
|
63
|
+
else
|
64
|
+
specs = client.get_deps(apps, :no_optional => options[:no_optional])
|
65
|
+
end
|
66
|
+
deps = specs.map{ |s| s.app_id }
|
67
|
+
unless (deps - apps).empty?
|
68
|
+
puts _("The following apps will be installed as a dependency:")
|
69
|
+
puts (deps - apps).inspect
|
70
|
+
end
|
71
|
+
i_options = {
|
72
|
+
:use_git => use_git,
|
73
|
+
:no_gems => options[:no_gems],
|
74
|
+
:no_optional_gems => options[:no_optional_gems]
|
75
|
+
}
|
76
|
+
i_options[:ssh_user] = options[:ssh_user] if options[:ssh_user]
|
77
|
+
inst_specs = specs.reject!{ |s| existent.include? s.app_id }
|
78
|
+
Spider::AppManager.install(inst_specs, Dir.pwd, i_options)
|
79
|
+
unless options[:no_activate]
|
80
|
+
require 'spiderfw/spider'
|
81
|
+
specs_hash = {}
|
82
|
+
specs.each{ |s| specs_hash[s.app_id] = s }
|
83
|
+
Spider.activate_apps(deps, specs_hash)
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.update_apps(apps, options={})
|
89
|
+
require 'spiderfw/spider'
|
90
|
+
require 'spiderfw/setup/app_server_client'
|
91
|
+
Spider.init_base
|
92
|
+
url = options[:url] || Spider.conf.get('app_server.url')
|
93
|
+
use_git = false
|
94
|
+
unless options[:no_git]
|
95
|
+
begin
|
96
|
+
require 'grit'
|
97
|
+
use_git = true
|
98
|
+
rescue
|
99
|
+
puts "Grit not available; install Grit for Git support"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
if options[:all]
|
103
|
+
require 'spiderfw/home'
|
104
|
+
home = Spider::Home.new(Dir.pwd)
|
105
|
+
apps = home.list_apps
|
106
|
+
end
|
107
|
+
if apps.empty?
|
108
|
+
puts _("No app to update")
|
109
|
+
exit
|
110
|
+
end
|
111
|
+
require 'spiderfw/setup/app_manager'
|
112
|
+
specs = []
|
113
|
+
client = Spider::AppServerClient.new(url)
|
114
|
+
if options[:no_deps]
|
115
|
+
specs = client.get_specs(apps)
|
116
|
+
else
|
117
|
+
specs = client.get_deps(apps, :no_optional => options[:no_optional])
|
118
|
+
end
|
119
|
+
deps = specs.map{ |s| s.app_id }
|
120
|
+
unless (deps - apps).empty?
|
121
|
+
puts _("The following apps will be updated as a dependency:")
|
122
|
+
puts (deps - apps).inspect
|
123
|
+
end
|
124
|
+
Spider::AppManager.update(specs, Dir.pwd, {
|
125
|
+
:use_git => use_git,
|
126
|
+
:no_gems => options[:no_gems],
|
127
|
+
:no_optional_gems => options[:no_optional_gems]
|
128
|
+
})
|
129
|
+
end
|
7
130
|
|
8
131
|
def self.install(specs, home_path, options)
|
9
132
|
options[:use_git] = true unless options[:use_git] == false
|
@@ -77,7 +200,7 @@ module Spider
|
|
77
200
|
end
|
78
201
|
end
|
79
202
|
|
80
|
-
def pre_update
|
203
|
+
def self.pre_update(specs, options={})
|
81
204
|
end
|
82
205
|
|
83
206
|
def self.post_setup(specs, options={})
|
@@ -89,7 +212,7 @@ module Spider
|
|
89
212
|
options[:use_git] = true unless options[:use_git] == false
|
90
213
|
specs = [specs] unless specs.is_a?(Array)
|
91
214
|
pre_setup(specs, options)
|
92
|
-
pre_update(specs,
|
215
|
+
pre_update(specs, options)
|
93
216
|
specs.each do |spec|
|
94
217
|
if spec.git_repo && options[:use_git]
|
95
218
|
git_update(spec, home_path, options)
|
data/lib/spiderfw/spider.rb
CHANGED
@@ -78,6 +78,11 @@ module Spider
|
|
78
78
|
@home.instance_eval(File.read(init_file), init_file)
|
79
79
|
end
|
80
80
|
|
81
|
+
init_apps
|
82
|
+
@init_done=true
|
83
|
+
end
|
84
|
+
|
85
|
+
def init_apps
|
81
86
|
@apps.each do |name, mod|
|
82
87
|
mod.app_init if mod.respond_to?(:app_init)
|
83
88
|
end
|
@@ -87,7 +92,6 @@ module Spider
|
|
87
92
|
GetText.bindtextdomain(mod.short_name)
|
88
93
|
end
|
89
94
|
end
|
90
|
-
@init_done=true
|
91
95
|
end
|
92
96
|
|
93
97
|
def init_done?
|
@@ -175,9 +179,9 @@ module Spider
|
|
175
179
|
@fssm_thread = Thread.new do
|
176
180
|
monitor.run
|
177
181
|
end
|
178
|
-
Spider.logger.debug("Monitoring restart.txt")
|
182
|
+
Spider.logger.debug("Monitoring restart.txt") if Spider.logger
|
179
183
|
else
|
180
|
-
Spider.logger.debug("FSSM not installed, unable to monitor restart.txt")
|
184
|
+
Spider.logger.debug("FSSM not installed, unable to monitor restart.txt") if Spider.logger
|
181
185
|
end
|
182
186
|
trap('TERM'){ Spider.main_process_shutdown; exit }
|
183
187
|
trap('INT'){ Spider.main_process_shutdown; exit }
|
@@ -314,6 +318,7 @@ module Spider
|
|
314
318
|
@paths[:tmp] = File.join(root, 'tmp')
|
315
319
|
@paths[:data] = File.join(root, 'data')
|
316
320
|
@paths[:log] = File.join(@paths[:var], 'log')
|
321
|
+
@paths[:restart_file] = File.join(@paths[:tmp], 'restart.txt')
|
317
322
|
@paths.each do |k, path|
|
318
323
|
@paths[k] = File.expand_path(File.readlink(path)) if File.symlink?(path)
|
319
324
|
end
|
@@ -422,6 +427,20 @@ module Spider
|
|
422
427
|
return false
|
423
428
|
end
|
424
429
|
|
430
|
+
def get_app_deps(apps, options={})
|
431
|
+
new_apps = apps.clone
|
432
|
+
specs = {}
|
433
|
+
init_base
|
434
|
+
while !new_apps.empty? && curr = new_apps.pop
|
435
|
+
raise "Could not find app #{curr}" unless Spider.home.apps[curr]
|
436
|
+
spec = Spider.home.apps[curr][:spec]
|
437
|
+
specs[curr] = spec
|
438
|
+
new_apps += spec.depends.reject{ |app| specs[app] }
|
439
|
+
new_apps += spec.depends_optional.reject{ |app| specs[app] } if options[:optional]
|
440
|
+
end
|
441
|
+
specs.keys
|
442
|
+
end
|
443
|
+
|
425
444
|
def activate_apps(apps, specs=nil)
|
426
445
|
require 'spiderfw/config/configuration_editor'
|
427
446
|
init_base
|
@@ -448,7 +467,7 @@ module Spider
|
|
448
467
|
apps.each do |a|
|
449
468
|
sort.add(specs[a] ? specs[a] : a)
|
450
469
|
end
|
451
|
-
sort.tsort
|
470
|
+
sort.tsort.reject{ |a| a.nil? }
|
452
471
|
end
|
453
472
|
|
454
473
|
def load_configuration(path)
|
data/views/errors/404.shtml
CHANGED
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<tpl:asset type="css" src="css/error_page.css" />
|
4
|
+
<head>
|
5
|
+
<title>{ @error_msg }</title>
|
6
|
+
<script sp:each='@assets[:js] |script|' type="text/javascript" src="{ script }"></script>
|
7
|
+
<link sp:each='@assets[:css] |css_file|' rel='stylesheet' href='{ css_file }' />
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div id="header">
|
11
|
+
</div>
|
12
|
+
<div id="content">
|
13
|
+
<sp:yield />
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<!DOCTYPE HTML>
|
2
|
+
<html>
|
3
|
+
<tpl:asset type="css" src="css/error_page.css" />
|
4
|
+
<head>
|
5
|
+
<title>{ @error_msg }</title>
|
6
|
+
<script sp:each='@assets[:js] |script|' type="text/javascript" src="{ script }"></script>
|
7
|
+
<link sp:each='@assets[:css] |css_file|' rel='stylesheet' href='{ css_file }' />
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
<div id="header">
|
11
|
+
</div>
|
12
|
+
<div id="content">
|
13
|
+
<sp:yield />
|
14
|
+
</div>
|
15
|
+
</div>
|
16
|
+
</div>
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spiderfw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 9
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 6
|
9
|
-
-
|
10
|
-
version: 0.6.
|
9
|
+
- 7
|
10
|
+
version: 0.6.7
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Ivan Pirlik
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-07-
|
18
|
+
date: 2011-07-26 00:00:00 +02:00
|
19
19
|
default_executable: spider
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -850,6 +850,7 @@ files:
|
|
850
850
|
- apps/master/models/admin.rb
|
851
851
|
- apps/master/models/command.rb
|
852
852
|
- apps/master/models/customer.rb
|
853
|
+
- apps/master/models/event.rb
|
853
854
|
- apps/master/models/installation.rb
|
854
855
|
- apps/master/models/remote_log.rb
|
855
856
|
- apps/master/models/resource.rb
|
@@ -935,6 +936,7 @@ files:
|
|
935
936
|
- apps/servant/controllers/servant_controller.rb
|
936
937
|
- apps/servant/Gemfile
|
937
938
|
- apps/servant/lib/client.rb
|
939
|
+
- apps/servant/lib/commands_processor.rb
|
938
940
|
- apps/servant/servant.appspec
|
939
941
|
- apps/servant/servant.rb
|
940
942
|
- apps/soap/_init.rb
|
@@ -1211,6 +1213,9 @@ files:
|
|
1211
1213
|
- views/errors/404.shtml
|
1212
1214
|
- views/errors/error.layout.shtml
|
1213
1215
|
- views/errors/error_generic.shtml
|
1216
|
+
- views/errors/simple.layout.shtml
|
1217
|
+
- views/generic.layout.shtml
|
1218
|
+
- views/maintenance.shtml
|
1214
1219
|
has_rdoc: true
|
1215
1220
|
homepage: http://github.com/me/spider
|
1216
1221
|
licenses: []
|