perus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.rspec +2 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +16 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/exe/perus-pinger +23 -0
- data/exe/perus-server +23 -0
- data/lib/perus/options.rb +30 -0
- data/lib/perus/pinger/chrome_command.rb +54 -0
- data/lib/perus/pinger/command.rb +123 -0
- data/lib/perus/pinger/commands/chrome_execute.rb +26 -0
- data/lib/perus/pinger/commands/chrome_navigate.rb +25 -0
- data/lib/perus/pinger/commands/chrome_reload.rb +29 -0
- data/lib/perus/pinger/commands/kill_process.rb +13 -0
- data/lib/perus/pinger/commands/remove_path.rb +15 -0
- data/lib/perus/pinger/commands/replace.rb +18 -0
- data/lib/perus/pinger/commands/restart.rb +9 -0
- data/lib/perus/pinger/commands/script.rb +59 -0
- data/lib/perus/pinger/commands/upgrade.rb +16 -0
- data/lib/perus/pinger/commands/upload.rb +15 -0
- data/lib/perus/pinger/metrics/chrome.rb +33 -0
- data/lib/perus/pinger/metrics/cpu.rb +17 -0
- data/lib/perus/pinger/metrics/hd.rb +14 -0
- data/lib/perus/pinger/metrics/mem.rb +11 -0
- data/lib/perus/pinger/metrics/process.rb +27 -0
- data/lib/perus/pinger/metrics/screenshot.rb +36 -0
- data/lib/perus/pinger/metrics/temp.rb +18 -0
- data/lib/perus/pinger/metrics/uptime.rb +10 -0
- data/lib/perus/pinger/metrics/value.rb +18 -0
- data/lib/perus/pinger/pinger.rb +218 -0
- data/lib/perus/pinger.rb +38 -0
- data/lib/perus/server/admin.rb +83 -0
- data/lib/perus/server/app.rb +304 -0
- data/lib/perus/server/db.rb +29 -0
- data/lib/perus/server/form.rb +73 -0
- data/lib/perus/server/helpers.rb +36 -0
- data/lib/perus/server/migrations/001_create_systems.rb +20 -0
- data/lib/perus/server/migrations/002_create_configs.rb +12 -0
- data/lib/perus/server/migrations/003_create_values.rb +23 -0
- data/lib/perus/server/migrations/004_create_groups.rb +12 -0
- data/lib/perus/server/migrations/005_create_errors.rb +15 -0
- data/lib/perus/server/migrations/006_create_alerts.rb +14 -0
- data/lib/perus/server/migrations/007_create_actions.rb +18 -0
- data/lib/perus/server/migrations/008_create_metrics.rb +16 -0
- data/lib/perus/server/migrations/009_create_command_config.rb +13 -0
- data/lib/perus/server/migrations/010_create_scripts.rb +13 -0
- data/lib/perus/server/migrations/011_create_script_commands.rb +14 -0
- data/lib/perus/server/migrations/012_create_config_metrics.rb +14 -0
- data/lib/perus/server/models/action.rb +71 -0
- data/lib/perus/server/models/alert.rb +9 -0
- data/lib/perus/server/models/command_config.rb +58 -0
- data/lib/perus/server/models/config.rb +30 -0
- data/lib/perus/server/models/config_metric.rb +15 -0
- data/lib/perus/server/models/error.rb +5 -0
- data/lib/perus/server/models/group.rb +12 -0
- data/lib/perus/server/models/metric.rb +53 -0
- data/lib/perus/server/models/script.rb +39 -0
- data/lib/perus/server/models/script_command.rb +15 -0
- data/lib/perus/server/models/system.rb +160 -0
- data/lib/perus/server/models/value.rb +11 -0
- data/lib/perus/server/public/css/reset.css +102 -0
- data/lib/perus/server/public/css/style.css +461 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-Italic.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-Light.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-LightItalic.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-Regular.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-Semibold.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/OpenSans-SemiboldItalic.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-light-webfont.eot +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-light-webfont.svg +1824 -0
- data/lib/perus/server/public/fonts/opensans/opensans-light-webfont.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-light-webfont.woff +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-light-webfont.woff2 +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-regular-webfont.eot +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-regular-webfont.svg +1824 -0
- data/lib/perus/server/public/fonts/opensans/opensans-regular-webfont.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-regular-webfont.woff +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-regular-webfont.woff2 +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-semibold-webfont.eot +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-semibold-webfont.svg +1824 -0
- data/lib/perus/server/public/fonts/opensans/opensans-semibold-webfont.ttf +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-semibold-webfont.woff +0 -0
- data/lib/perus/server/public/fonts/opensans/opensans-semibold-webfont.woff2 +0 -0
- data/lib/perus/server/public/fonts/opensans/stylesheet.css +35 -0
- data/lib/perus/server/public/js/dygraph-combined.js +6 -0
- data/lib/perus/server/public/js/jquery.js +4 -0
- data/lib/perus/server/server.rb +32 -0
- data/lib/perus/server/views/admin/edit.erb +9 -0
- data/lib/perus/server/views/admin/index.erb +18 -0
- data/lib/perus/server/views/admin/new.erb +5 -0
- data/lib/perus/server/views/alerts/form.erb +3 -0
- data/lib/perus/server/views/command_config.erb +37 -0
- data/lib/perus/server/views/configs/edit.erb +36 -0
- data/lib/perus/server/views/configs/form.erb +1 -0
- data/lib/perus/server/views/errors.erb +6 -0
- data/lib/perus/server/views/groups/form.erb +1 -0
- data/lib/perus/server/views/index.erb +21 -0
- data/lib/perus/server/views/layout.erb +44 -0
- data/lib/perus/server/views/scripts/edit.erb +36 -0
- data/lib/perus/server/views/scripts/form.erb +2 -0
- data/lib/perus/server/views/system.erb +202 -0
- data/lib/perus/server/views/systems/form.erb +6 -0
- data/lib/perus/server/views/systems.erb +17 -0
- data/lib/perus/server.rb +24 -0
- data/lib/perus/version.rb +3 -0
- data/lib/perus.rb +10 -0
- data/perus.gemspec +36 -0
- metadata +354 -0
@@ -0,0 +1,11 @@
|
|
1
|
+
module Perus::Pinger
|
2
|
+
class Mem < Command
|
3
|
+
description 'Measures overall RAM usage as a percentage on the client.'
|
4
|
+
metric!
|
5
|
+
|
6
|
+
def run
|
7
|
+
percent = `cat /proc/meminfo | awk '{if ($1=="MemTotal:") total = $2; if ($1 == "MemFree:") free = $2;} END {print (1 - (free / total))*100}'`
|
8
|
+
{mem_all: percent.to_f}
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Perus::Pinger
|
2
|
+
class Process < Command
|
3
|
+
description 'Measures percentage of RAM and CPU used by the process
|
4
|
+
specified by "process_path". The results are returned to
|
5
|
+
the server under 2 metrics called "cpu_{name}" and
|
6
|
+
"mem_{name}". Valid values for "process_path" are
|
7
|
+
contained in the pinger config file.'
|
8
|
+
option :process_path, restricted: true
|
9
|
+
option :name
|
10
|
+
metric!
|
11
|
+
|
12
|
+
def run
|
13
|
+
path = options.process_path.gsub("/", "\\\\\\/")
|
14
|
+
cpu, mem = `ps aux | awk '/#{path}/ {cpu += $3; mem += $4} END {print cpu, mem;}'`.split
|
15
|
+
if `uname -s`.strip == 'Darwin'
|
16
|
+
core_count = `sysctl -n hw.ncpu`
|
17
|
+
else
|
18
|
+
core_count = `cat /proc/cpuinfo | grep processor | awk '{count += 1} END {print count}'`
|
19
|
+
end
|
20
|
+
|
21
|
+
{
|
22
|
+
"cpu_#{options.name}" => cpu.to_f / core_count.to_i,
|
23
|
+
"mem_#{options.name}" => mem.to_f
|
24
|
+
}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Perus::Pinger
|
2
|
+
class Screenshot < Command
|
3
|
+
description 'Takes a screenshot of the primary screen on the client and
|
4
|
+
uploads it. The screenshot is saved to "path" before being
|
5
|
+
uploaded. Valid values for "path" are contained in the
|
6
|
+
pinger config file.'
|
7
|
+
option :path, default: '/tmp/screenshot.jpg', restricted: true
|
8
|
+
option :resize, default: '20%'
|
9
|
+
metric!
|
10
|
+
|
11
|
+
def run
|
12
|
+
if `uname -s`.strip == 'Darwin'
|
13
|
+
if options.resize[-1] != '%'
|
14
|
+
raise 'Non percent resize option unsupported by OS X currently'
|
15
|
+
else
|
16
|
+
percent = options.resize.to_f / 100
|
17
|
+
end
|
18
|
+
|
19
|
+
`screencapture -m -t jpg -x #{options.path}`
|
20
|
+
width = `sips -g pixelWidth #{options.path}`.match(/pixelWidth: (\d+)/)[1]
|
21
|
+
height = `sips -g pixelHeight #{options.path}`.match(/pixelHeight: (\d+)/)[1]
|
22
|
+
`sips -z #{height.to_i * percent} #{width.to_i * percent} #{options.path}`
|
23
|
+
else
|
24
|
+
`export DISPLAY=:0; import -window root -resize #{options.resize} #{options.path}`
|
25
|
+
end
|
26
|
+
|
27
|
+
@screenshot_file = File.new(options.path)
|
28
|
+
{screenshot: @screenshot_file}
|
29
|
+
end
|
30
|
+
|
31
|
+
def cleanup
|
32
|
+
@screenshot_file.close unless @screenshot_file.closed?
|
33
|
+
File.delete(options.path)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Perus::Pinger
|
2
|
+
class Temp < Command
|
3
|
+
description 'Measures the temperature of "device" on the client. By
|
4
|
+
default, this will be a CPU.'
|
5
|
+
option :device, default: 'Physical id 0'
|
6
|
+
metric!
|
7
|
+
|
8
|
+
def run
|
9
|
+
if `uname -s`.strip == 'Darwin'
|
10
|
+
degrees = `istats cpu temp`.split[2].match(/([0-9\.]+)/)[0]
|
11
|
+
else
|
12
|
+
degrees = `sensors | grep "#{options.device}:"`.match(/#{options.device}:\s+(\S+)/)[1]
|
13
|
+
end
|
14
|
+
|
15
|
+
{temp: degrees.to_f}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Perus::Pinger
|
2
|
+
class Value < Command
|
3
|
+
description 'Searches the file specified by "path" with the regular
|
4
|
+
expression specified by "grep". Returns the resulting
|
5
|
+
string to the server under the metric called "name". Valid
|
6
|
+
values for "path" are contained in the pinger config file.'
|
7
|
+
option :path, restricted: true
|
8
|
+
option :grep
|
9
|
+
option :name
|
10
|
+
metric!
|
11
|
+
|
12
|
+
def run
|
13
|
+
line = `cat #{options.path} | grep #{options.grep}`
|
14
|
+
value = line.match(Regexp.compile(options.match))[1]
|
15
|
+
{options.name => value}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,218 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
require 'rest-client'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'json'
|
5
|
+
require 'uri'
|
6
|
+
|
7
|
+
DEFAULT_PINGER_OPTIONS = {
|
8
|
+
'__anonymous__' => {
|
9
|
+
'system_id' => 1,
|
10
|
+
'server' => 'http://127.0.0.1:3000/'
|
11
|
+
},
|
12
|
+
|
13
|
+
# restricted values
|
14
|
+
'Value' => {
|
15
|
+
'path' => []
|
16
|
+
},
|
17
|
+
|
18
|
+
'Screenshot' => {
|
19
|
+
'path' => []
|
20
|
+
},
|
21
|
+
|
22
|
+
'Process' => {
|
23
|
+
'process_path' => []
|
24
|
+
},
|
25
|
+
|
26
|
+
'Upload' => {
|
27
|
+
'path' => []
|
28
|
+
},
|
29
|
+
|
30
|
+
'Replace' => {
|
31
|
+
'path' => []
|
32
|
+
},
|
33
|
+
|
34
|
+
'RemovePath' => {
|
35
|
+
'path' => []
|
36
|
+
},
|
37
|
+
|
38
|
+
'KillProcess' => {
|
39
|
+
'process_name' => []
|
40
|
+
}
|
41
|
+
}
|
42
|
+
|
43
|
+
module Perus::Pinger
|
44
|
+
class Pinger
|
45
|
+
def self.options
|
46
|
+
@options ||= Perus::Options.new
|
47
|
+
end
|
48
|
+
|
49
|
+
def initialize(options_path = DEFAULT_PINGER_OPTIONS_PATH)
|
50
|
+
Pinger.options.load(options_path, DEFAULT_PINGER_OPTIONS)
|
51
|
+
|
52
|
+
# cache urls on initialisation since the urls depend on values known
|
53
|
+
# at startup and that won't change over the object lifetime
|
54
|
+
config_path = URI("/systems/#{Pinger.options.system_id}/config")
|
55
|
+
pinger_path = URI("/systems/#{Pinger.options.system_id}/ping")
|
56
|
+
server_uri = URI(Pinger.options.server)
|
57
|
+
|
58
|
+
@config_url = (server_uri + config_path).to_s
|
59
|
+
@pinger_url = (server_uri + pinger_path).to_s
|
60
|
+
|
61
|
+
@metrics = []
|
62
|
+
@metric_results = {}
|
63
|
+
@metric_errors = {}
|
64
|
+
|
65
|
+
@actions = []
|
66
|
+
@action_results = {}
|
67
|
+
@late_actions = []
|
68
|
+
end
|
69
|
+
|
70
|
+
def run
|
71
|
+
load_config
|
72
|
+
run_metrics
|
73
|
+
run_actions
|
74
|
+
send_response
|
75
|
+
cleanup
|
76
|
+
end
|
77
|
+
|
78
|
+
#----------------------
|
79
|
+
# configuration
|
80
|
+
#----------------------
|
81
|
+
def load_config
|
82
|
+
# load the system config by requesting it from the perus server
|
83
|
+
json = JSON.parse(RestClient.get(@config_url))
|
84
|
+
json['metrics'] ||= []
|
85
|
+
json['actions'] ||= []
|
86
|
+
|
87
|
+
# load metric and command modules based on the config
|
88
|
+
json['metrics'].each do |config|
|
89
|
+
begin
|
90
|
+
if ::Perus::Pinger.const_defined?(config['type'])
|
91
|
+
metric = ::Perus::Pinger.const_get(config['type'])
|
92
|
+
@metric_errors[metric.name] ||= []
|
93
|
+
@metrics << metric.new(config['options'])
|
94
|
+
else
|
95
|
+
@metric_errors[config['type']] = e.inspect
|
96
|
+
end
|
97
|
+
rescue => e
|
98
|
+
@metric_errors[metric.name] << e.inspect
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
json['actions'].each do |config|
|
103
|
+
begin
|
104
|
+
command = ::Perus::Pinger.const_get(config['type'])
|
105
|
+
@actions << command.new(config['options'], config['id'])
|
106
|
+
rescue => e
|
107
|
+
if config['id']
|
108
|
+
@action_results[config['id']] = e.inspect
|
109
|
+
else
|
110
|
+
puts 'Error - action does not have an associated id'
|
111
|
+
p config
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
#----------------------
|
118
|
+
# run
|
119
|
+
#----------------------
|
120
|
+
def run_metrics
|
121
|
+
@metrics.each do |metric|
|
122
|
+
begin
|
123
|
+
result = metric.run
|
124
|
+
@metric_results.merge!(result)
|
125
|
+
rescue => e
|
126
|
+
@metric_errors[metric.class.name] << e.inspect
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def run_actions
|
132
|
+
@actions.each do |action|
|
133
|
+
begin
|
134
|
+
result = action.run
|
135
|
+
|
136
|
+
if result.instance_of?(Proc)
|
137
|
+
@late_actions << result
|
138
|
+
result = true
|
139
|
+
end
|
140
|
+
|
141
|
+
@action_results[action.id] = result
|
142
|
+
|
143
|
+
rescue => e
|
144
|
+
@action_results[action.id] = e.inspect
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
#----------------------
|
150
|
+
# response
|
151
|
+
#----------------------
|
152
|
+
def add_to_payload(payload, field, results)
|
153
|
+
results.each do |name, val|
|
154
|
+
next unless val.instance_of?(File)
|
155
|
+
uuid = SecureRandom.uuid
|
156
|
+
results[name] = {file: uuid}
|
157
|
+
payload[uuid] = val
|
158
|
+
end
|
159
|
+
|
160
|
+
payload[field] = JSON.dump(results)
|
161
|
+
end
|
162
|
+
|
163
|
+
def send_response
|
164
|
+
# prepare the response and replace file results with a reference
|
165
|
+
# to the uploaded file. files are sent as top level parameters in
|
166
|
+
# the payload, while metric and action results are sent as a json
|
167
|
+
# object with a reference to these files.
|
168
|
+
payload = {}
|
169
|
+
add_to_payload(payload, 'metrics', @metric_results)
|
170
|
+
add_to_payload(payload, 'actions', @action_results)
|
171
|
+
|
172
|
+
# metric_errors is created with a key for each metric type. most
|
173
|
+
# metrics should run without any errors, so remove these entries
|
174
|
+
# before adding errors to the payload.
|
175
|
+
@metric_errors.reject! {|metric, errors| errors.empty?}
|
176
|
+
add_to_payload(payload, 'metric_errors', @metric_errors)
|
177
|
+
|
178
|
+
begin
|
179
|
+
RestClient.post(@pinger_url, payload)
|
180
|
+
rescue => e
|
181
|
+
puts 'Ping failed with exception'
|
182
|
+
puts e.inspect
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
#----------------------
|
187
|
+
# cleanup
|
188
|
+
#----------------------
|
189
|
+
def cleanup
|
190
|
+
@metrics.each do |metric|
|
191
|
+
begin
|
192
|
+
metric.cleanup
|
193
|
+
rescue => e
|
194
|
+
puts 'Error running metric cleanup'
|
195
|
+
puts e.inspect
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
199
|
+
@actions.each do |action|
|
200
|
+
begin
|
201
|
+
action.cleanup
|
202
|
+
rescue => e
|
203
|
+
puts 'Error running action cleanup'
|
204
|
+
puts e.inspect
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
@late_actions.each do |code|
|
209
|
+
begin
|
210
|
+
code.call
|
211
|
+
rescue => e
|
212
|
+
puts 'Error running late action'
|
213
|
+
puts e.inspect
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
218
|
+
end
|
data/lib/perus/pinger.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
module Perus
|
2
|
+
module Pinger
|
3
|
+
Dir.chdir(__dir__) do
|
4
|
+
# commands
|
5
|
+
require './pinger/command'
|
6
|
+
require './pinger/chrome_command'
|
7
|
+
require './pinger/commands/chrome_execute'
|
8
|
+
require './pinger/commands/chrome_navigate'
|
9
|
+
require './pinger/commands/chrome_reload'
|
10
|
+
require './pinger/commands/kill_process'
|
11
|
+
require './pinger/commands/remove_path'
|
12
|
+
require './pinger/commands/replace'
|
13
|
+
require './pinger/commands/restart'
|
14
|
+
require './pinger/commands/upload'
|
15
|
+
require './pinger/commands/upgrade'
|
16
|
+
require './pinger/commands/script'
|
17
|
+
|
18
|
+
# metrics
|
19
|
+
require './pinger/metrics/chrome'
|
20
|
+
require './pinger/metrics/cpu'
|
21
|
+
require './pinger/metrics/hd'
|
22
|
+
require './pinger/metrics/mem'
|
23
|
+
require './pinger/metrics/process'
|
24
|
+
require './pinger/metrics/screenshot'
|
25
|
+
require './pinger/metrics/temp'
|
26
|
+
require './pinger/metrics/value'
|
27
|
+
require './pinger/metrics/uptime'
|
28
|
+
|
29
|
+
# pinger
|
30
|
+
require './pinger/pinger'
|
31
|
+
end
|
32
|
+
|
33
|
+
# options file
|
34
|
+
DEFAULT_PINGER_OPTIONS_PATH = '/etc/perus-pinger'
|
35
|
+
end
|
36
|
+
|
37
|
+
Pinger::Pinger.new.run if __FILE__ == $0
|
38
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module Perus::Server
|
2
|
+
module Admin
|
3
|
+
def admin(type, redirect_to_record = false)
|
4
|
+
plural = type.to_s.pluralize
|
5
|
+
singular = plural.singularize
|
6
|
+
title = singular.titleize
|
7
|
+
klass = title
|
8
|
+
|
9
|
+
class_eval "
|
10
|
+
use Sinatra.new {
|
11
|
+
helpers Helpers
|
12
|
+
|
13
|
+
before do
|
14
|
+
@plural = '#{plural}'
|
15
|
+
@title = '#{title}'
|
16
|
+
load_site_information
|
17
|
+
end
|
18
|
+
|
19
|
+
# list
|
20
|
+
get '/admin/#{plural}' do
|
21
|
+
@records = #{klass}.all
|
22
|
+
erb :'admin/index'
|
23
|
+
end
|
24
|
+
|
25
|
+
# new form
|
26
|
+
get '/admin/#{plural}/new' do
|
27
|
+
@record = #{klass}.new
|
28
|
+
@form = Form.new(@record)
|
29
|
+
erb :'admin/new'
|
30
|
+
end
|
31
|
+
|
32
|
+
# create
|
33
|
+
post '/admin/#{plural}' do
|
34
|
+
@record = #{klass}.new(params[:record])
|
35
|
+
if @record.valid?
|
36
|
+
begin
|
37
|
+
@record.save
|
38
|
+
if #{redirect_to_record}
|
39
|
+
redirect url_prefix + 'admin/#{plural}/' + @record.id.to_s
|
40
|
+
else
|
41
|
+
redirect url_prefix + 'admin/#{plural}'
|
42
|
+
end
|
43
|
+
rescue
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
@form = Form.new(@record)
|
48
|
+
erb :'admin/new'
|
49
|
+
end
|
50
|
+
|
51
|
+
# edit
|
52
|
+
get '/admin/#{plural}/:id' do
|
53
|
+
@record = #{klass}.with_pk!(params['id'])
|
54
|
+
@form = Form.new(@record)
|
55
|
+
erb :'admin/edit'
|
56
|
+
end
|
57
|
+
|
58
|
+
# update
|
59
|
+
put '/admin/#{plural}/:id' do
|
60
|
+
@record = #{klass}.with_pk!(params['id'])
|
61
|
+
if @record.valid?
|
62
|
+
begin
|
63
|
+
@record.update(params[:record])
|
64
|
+
redirect url_prefix + 'admin/#{plural}'
|
65
|
+
rescue
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
@form = Form.new(@record)
|
70
|
+
erb :'admin/edit'
|
71
|
+
end
|
72
|
+
|
73
|
+
# delete
|
74
|
+
delete '/admin/#{plural}/:id' do
|
75
|
+
@record = #{klass}.with_pk!(params['id'])
|
76
|
+
@record.destroy
|
77
|
+
redirect url_prefix + 'admin/#{plural}'
|
78
|
+
end
|
79
|
+
}
|
80
|
+
"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|