scout-camp 0.1.13 → 0.1.14
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.
- checksums.yaml +4 -4
- data/.vimproject +52 -11
- data/Rakefile +5 -0
- data/VERSION +1 -1
- data/bin/scout-camp +46 -0
- data/doc/terraform.md +188 -0
- data/lib/scout/aws/s3.rb +6 -4
- data/lib/scout/offsite/resource.rb +110 -5
- data/lib/scout/offsite/step.rb +21 -14
- data/lib/scout/offsite/sync.rb +38 -10
- data/lib/scout/offsite.rb +1 -0
- data/lib/scout/render/engine.rb +119 -0
- data/lib/scout/render/helpers.rb +92 -0
- data/lib/scout/render/resource.rb +54 -0
- data/lib/scout/render.rb +3 -0
- data/lib/scout/sinatra/auth.rb +158 -0
- data/lib/scout/sinatra/base/assets.rb +245 -0
- data/lib/scout/sinatra/base/favicon.rb +43 -0
- data/lib/scout/sinatra/base/headers.rb +77 -0
- data/lib/scout/sinatra/base/helpers.rb +14 -0
- data/lib/scout/sinatra/base/parameters.rb +147 -0
- data/lib/scout/sinatra/base/post_processing.rb +18 -0
- data/lib/scout/sinatra/base/session.rb +72 -0
- data/lib/scout/sinatra/base.rb +253 -0
- data/lib/scout/sinatra/entity.rb +259 -0
- data/lib/scout/sinatra/finder.rb +9 -0
- data/lib/scout/sinatra/fragment.rb +275 -0
- data/lib/scout/sinatra/htmx.rb +68 -0
- data/lib/scout/sinatra/knowledge_base.rb +14 -0
- data/lib/scout/sinatra/tool.rb +11 -0
- data/lib/scout/sinatra/workflow.rb +129 -0
- data/lib/scout-camp.rb +1 -1
- data/scout-camp.gemspec +39 -3
- data/scout_commands/find +83 -0
- data/scout_commands/glob +90 -0
- data/share/aws/lambda_function.rb +53 -30
- data/share/terraform/aws/efs_host/data.tf +1 -2
- data/share/terraform/aws/efs_host/main.tf +1 -1
- data/share/terraform/aws/efs_host/variables.tf +5 -1
- data/test/scout/render/test_engine.rb +88 -0
- data/test/scout/render/test_resource.rb +29 -0
- data/test/scout/sinatra/base/test_headers.rb +125 -0
- data/test/scout/sinatra/base/test_parameters.rb +88 -0
- data/test/scout/sinatra/test_base.rb +27 -0
- data/test/scout/sinatra/test_entity.rb +44 -0
- data/test/scout/sinatra/test_render.rb +44 -0
- data/test/scout/sinatra/test_workflow.rb +157 -0
- data/test/test_helper.rb +26 -0
- metadata +103 -2
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
require_relative 'render/parameters'
|
|
2
|
+
|
|
3
|
+
module ScoutRenderHelpers
|
|
4
|
+
def fragment(link = nil, &block)
|
|
5
|
+
fragment_code, link = [link.to_s, nil] if link and not link.to_s[0] == '<'
|
|
6
|
+
text = fragment_code if fragment_code
|
|
7
|
+
|
|
8
|
+
if block_given?
|
|
9
|
+
if defined? @step and (_cache_type == :asynchronous or _cache_type == :async)
|
|
10
|
+
|
|
11
|
+
fragment_code ||= (rand * 100000).to_i.to_s
|
|
12
|
+
fragment_file = @step.file(fragment_code)
|
|
13
|
+
pid_file = fragment_file + '.pid'
|
|
14
|
+
|
|
15
|
+
pid = @step.child{
|
|
16
|
+
begin
|
|
17
|
+
class << @step
|
|
18
|
+
def status=(message)
|
|
19
|
+
nil
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
Log.low("Fragment started: #{ fragment_file } - #{Process.pid}")
|
|
23
|
+
res = block.call fragment_file
|
|
24
|
+
Log.low("Fragment writing: #{ fragment_file } - #{Process.pid}")
|
|
25
|
+
Open.write(fragment_file, res) unless res.nil?
|
|
26
|
+
Log.low("Fragment done: #{ fragment_file } - #{Process.pid}")
|
|
27
|
+
rescue Exception
|
|
28
|
+
Open.write(fragment_file + '.error', [$!.class.to_s, $!.message] * ": ")
|
|
29
|
+
Open.write(fragment_file + '.backtrace', $!.backtrace * "\n") if $!.backtrace
|
|
30
|
+
Log.error("Error in fragment: #{ fragment_file }")
|
|
31
|
+
Log.exception $!
|
|
32
|
+
Open.rm pid_file if Open.exists? pid_file
|
|
33
|
+
Kernel.exit! -1
|
|
34
|
+
ensure
|
|
35
|
+
Open.rm pid_file if Open.exists? pid_file
|
|
36
|
+
end
|
|
37
|
+
Kernel.exit! 0
|
|
38
|
+
}
|
|
39
|
+
Open.write(pid_file, pid.to_s)
|
|
40
|
+
|
|
41
|
+
url = fullpath
|
|
42
|
+
url = remove_GET_param(url, "_update")
|
|
43
|
+
url = remove_GET_param(url, "_")
|
|
44
|
+
|
|
45
|
+
fragment_url = add_GET_param(url, "_fragment", fragment_code)
|
|
46
|
+
if link.nil?
|
|
47
|
+
html_tag('a', "", :href => fragment_url, :class => 'fragment', "data-text" => text)
|
|
48
|
+
else
|
|
49
|
+
if FalseClass === link
|
|
50
|
+
return fragment_code
|
|
51
|
+
elsif TrueClass === link
|
|
52
|
+
return fragment_url
|
|
53
|
+
elsif link =~ / href=/
|
|
54
|
+
link = link.sub(/ href=('|")/," href='#{fragment_url}'")
|
|
55
|
+
else
|
|
56
|
+
link = link.sub(/<a /,"<a href='#{fragment_url}' ")
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
if text
|
|
60
|
+
link.sub(/<a /,"<a data-text='#{text}' ")
|
|
61
|
+
else
|
|
62
|
+
link
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
else
|
|
66
|
+
block.call
|
|
67
|
+
end
|
|
68
|
+
else
|
|
69
|
+
if link =~ / class=/
|
|
70
|
+
link = link.sub(/ class=('|")/,' class=\1fragment ')
|
|
71
|
+
else
|
|
72
|
+
link = link.sub(/<a /,'<a class="fragment" ')
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
if text
|
|
76
|
+
link.sub(/<a /,"<a data-text='#{text}' ")
|
|
77
|
+
else
|
|
78
|
+
link
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
module SinatraScoutFragment
|
|
85
|
+
def self.registered(app)
|
|
86
|
+
app.helpers do
|
|
87
|
+
# keep a small param consumer (safe)
|
|
88
|
+
def process_fragment(fragment_code)
|
|
89
|
+
fragment_file = @step.file(fragment_code)
|
|
90
|
+
if Open.exists?(fragment_file)
|
|
91
|
+
case _format.to_s
|
|
92
|
+
when "query-entity"
|
|
93
|
+
tsv, table_options = load_tsv(fragment_file, true)
|
|
94
|
+
begin
|
|
95
|
+
res = tsv[@entity].to_json
|
|
96
|
+
content_type "application/json"
|
|
97
|
+
rescue
|
|
98
|
+
res = nil.to_json
|
|
99
|
+
end
|
|
100
|
+
halt 200, res
|
|
101
|
+
when "query-entity-field"
|
|
102
|
+
tsv, table_options = load_tsv(fragment_file, true)
|
|
103
|
+
begin
|
|
104
|
+
res = tsv[@entity]
|
|
105
|
+
res = [res] if tsv.type == :single or tsv.type == :flat
|
|
106
|
+
rescue
|
|
107
|
+
res = nil.to_json
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
fields = tsv.fields
|
|
111
|
+
content_type "application/json"
|
|
112
|
+
hash = {}
|
|
113
|
+
fields.each_with_index do |f,i|
|
|
114
|
+
hash[f] = res.nil? ? nil : res[i]
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
halt 200, hash.to_json
|
|
118
|
+
when "table"
|
|
119
|
+
html_halt tsv2html(fragment_file)
|
|
120
|
+
when "json"
|
|
121
|
+
content_type "application/json"
|
|
122
|
+
halt 200, tsv_process(load_tsv(fragment_file).first).to_json
|
|
123
|
+
when "tsv"
|
|
124
|
+
content_type "text/tab-separated-values"
|
|
125
|
+
halt 200, tsv_process(load_tsv(fragment_file).first).to_s
|
|
126
|
+
when "values"
|
|
127
|
+
tsv = tsv_process(load_tsv(fragment_file).first)
|
|
128
|
+
list = tsv.values.flatten
|
|
129
|
+
content_type "application/json"
|
|
130
|
+
halt 200, list.compact.to_json
|
|
131
|
+
when "entities"
|
|
132
|
+
raw_tsv, tsv_options = load_tsv(fragment_file)
|
|
133
|
+
tsv = tsv_process(raw_tsv)
|
|
134
|
+
|
|
135
|
+
list = tsv.values.flatten
|
|
136
|
+
list = tsv.prepare_entity(list, tsv.fields.first, tsv.entity_options)
|
|
137
|
+
type = list.annotation_types.last
|
|
138
|
+
list_id = "List of #{type} in table #{ @fragment }"
|
|
139
|
+
list_id << " (#{ @filter })" if @filter
|
|
140
|
+
Entity::List.save_list(type.to_s, list_id, list, user)
|
|
141
|
+
url = Entity::REST.entity_list_url(list_id, type)
|
|
142
|
+
url = url + '?_layout=false' unless @layout
|
|
143
|
+
url = escape_url(url)
|
|
144
|
+
redirect to(url)
|
|
145
|
+
when "map"
|
|
146
|
+
raw_tsv, tsv_options = load_tsv(fragment_file)
|
|
147
|
+
raw_tsv.unnamed = true
|
|
148
|
+
tsv = tsv_process(raw_tsv)
|
|
149
|
+
|
|
150
|
+
field = tsv.key_field
|
|
151
|
+
column = tsv.fields.first
|
|
152
|
+
|
|
153
|
+
if tsv.entity_templates[field]
|
|
154
|
+
type = tsv.entity_templates[field].annotation_types.first
|
|
155
|
+
else
|
|
156
|
+
type = [Entity.formats[field]].compact.first || field
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
map_id = "Map #{type}-#{column} in #{ @fragment }"
|
|
160
|
+
map_id << " (#{ @filter.gsub(';','|') })" if @filter
|
|
161
|
+
Entity::Map.save_map(type.to_s, column, map_id, tsv, user)
|
|
162
|
+
url = Entity::REST.entity_map_url(map_id, type, column)
|
|
163
|
+
url = url + '?_layout=false' unless @layout
|
|
164
|
+
url = escape_url(url)
|
|
165
|
+
redirect to(url)
|
|
166
|
+
when "excel"
|
|
167
|
+
require 'rbbt/tsv/excel'
|
|
168
|
+
tsv, tsv_options = load_tsv(fragment_file)
|
|
169
|
+
tsv = tsv_process(tsv)
|
|
170
|
+
data = nil
|
|
171
|
+
excel_file = TmpFile.tmp_file
|
|
172
|
+
tsv.excel(excel_file, :sort_by => @excel_sort_by, :sort_by_cast => @excel_sort_by_cast, :name => true, :remove_links => true)
|
|
173
|
+
name = tsv_options[:table_id]
|
|
174
|
+
name ||= "rbbt-table"
|
|
175
|
+
name = name.sub(/\s/,'_')
|
|
176
|
+
name = name.sub('.tsv','')
|
|
177
|
+
send_file excel_file, :type => 'application/vnd.ms-excel', :filename => "#{name}.xls"
|
|
178
|
+
when "heatmap"
|
|
179
|
+
require 'rbbt/util/R'
|
|
180
|
+
tsv, tsv_options = load_tsv(fragment_file)
|
|
181
|
+
content_type "text/html"
|
|
182
|
+
data = nil
|
|
183
|
+
png_file = TmpFile.tmp_file + '.png'
|
|
184
|
+
width = tsv.fields.length * 10 + 500
|
|
185
|
+
height = tsv.size * 10 + 500
|
|
186
|
+
width = 10000 if width > 10000
|
|
187
|
+
height = 10000 if height > 10000
|
|
188
|
+
tsv.R <<-EOF
|
|
189
|
+
rbbt.pheatmap(file='#{png_file}', data, width=#{width}, height=#{height})
|
|
190
|
+
data = NULL
|
|
191
|
+
EOF
|
|
192
|
+
send_file png_file, :type => 'image/png', :filename => fragment_file + ".heatmap.png"
|
|
193
|
+
when 'binary'
|
|
194
|
+
send_file fragment_file, :type => 'application/octet-stream'
|
|
195
|
+
else
|
|
196
|
+
require 'mimemagic'
|
|
197
|
+
mime = nil
|
|
198
|
+
Open.open(fragment_file) do |io|
|
|
199
|
+
begin
|
|
200
|
+
mime = MimeMagic.by_path(fragment_file)
|
|
201
|
+
if mime.nil?
|
|
202
|
+
io.rewind
|
|
203
|
+
mime = MimeMagic.by_magic(io)
|
|
204
|
+
end
|
|
205
|
+
if mime.nil?
|
|
206
|
+
io.rewind if IO === io
|
|
207
|
+
mime = "text/tab-separated-values" if io.gets =~ /^#/ and io.gets.include? "\t"
|
|
208
|
+
end
|
|
209
|
+
rescue Exception
|
|
210
|
+
Log.exception $!
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
if mime.nil?
|
|
215
|
+
txt = Open.read(fragment_file)
|
|
216
|
+
|
|
217
|
+
if txt =~ /<([^> ]+)[^>]*>.*?<\/\1>/m
|
|
218
|
+
mime = "text/html"
|
|
219
|
+
else
|
|
220
|
+
begin
|
|
221
|
+
JSON.parse(txt)
|
|
222
|
+
mime = "application/json"
|
|
223
|
+
rescue
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
else
|
|
227
|
+
txt = nil
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
if mime
|
|
231
|
+
content_type mime
|
|
232
|
+
else
|
|
233
|
+
content_type "text/plain"
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
if mime && mime.to_s.include?("text/html")
|
|
237
|
+
html_halt txt || Open.read(fragment_file)
|
|
238
|
+
else
|
|
239
|
+
if File.exist?(fragment_file)
|
|
240
|
+
send_file fragment_file
|
|
241
|
+
else
|
|
242
|
+
halt 200, Open.read(fragment_file)
|
|
243
|
+
end
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
elsif Open.exists?(fragment_file + '.error')
|
|
247
|
+
klass, _sep, message = Open.read(fragment_file + '.error').partition(": ")
|
|
248
|
+
backtrace = Open.read(fragment_file + '.backtrace').split("\n")
|
|
249
|
+
exception = Kernel.const_get(klass).new message || "no message"
|
|
250
|
+
exception.set_backtrace backtrace
|
|
251
|
+
raise exception
|
|
252
|
+
#halt 500, html_tag(:span, File.read(fragment_file + '.error'), :class => "message") +
|
|
253
|
+
# html_tag(:ul, File.read(fragment_file + '.backtrace').split("\n").collect{|l| html_tag(:li, l)} * "\n", :class => "backtrace")
|
|
254
|
+
elsif Open.exists?(fragment_file + '.pid')
|
|
255
|
+
pid = Open.read(fragment_file + '.pid')
|
|
256
|
+
if Misc.pid_exists?(pid.to_i)
|
|
257
|
+
halt 202, "Fragment not completed"
|
|
258
|
+
else
|
|
259
|
+
halt 500, "Fragment aborted"
|
|
260
|
+
end
|
|
261
|
+
else
|
|
262
|
+
halt 500, "Fragment not completed and no pid file"
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
end
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
SinatraScoutParameters.register_common_parameter(:_fragment, :string)
|
|
270
|
+
|
|
271
|
+
SinatraScoutPostProcessing.register_post_processing do |step|
|
|
272
|
+
if _fragment
|
|
273
|
+
process_fragment(_fragment)
|
|
274
|
+
end
|
|
275
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
module SinatraScoutHTMX
|
|
3
|
+
|
|
4
|
+
def self.registered(app)
|
|
5
|
+
app.before do
|
|
6
|
+
headers "X-Frame-Options" => "DENY"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
app.after do
|
|
10
|
+
triggers = []
|
|
11
|
+
|
|
12
|
+
status = case response.status
|
|
13
|
+
when 200
|
|
14
|
+
['done', 'complete']
|
|
15
|
+
when 500
|
|
16
|
+
['error', 'complete']
|
|
17
|
+
when 202
|
|
18
|
+
['running']
|
|
19
|
+
else
|
|
20
|
+
[]
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
if defined?(entity_type) && entity_type
|
|
24
|
+
entity = (splat*"/").gsub(/\s/,'_')
|
|
25
|
+
triggers << 'entity'
|
|
26
|
+
triggers << entity_type
|
|
27
|
+
triggers << entity
|
|
28
|
+
triggers << [entity_type, entity]*'_'
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
if defined?(entity_property) && entity_property
|
|
32
|
+
triggers << 'entity_property'
|
|
33
|
+
triggers << [entity_type, entity_property]*'_'
|
|
34
|
+
triggers << [entity, entity_property]*'_'
|
|
35
|
+
triggers << [entity_type, entity, entity_property]*'_'
|
|
36
|
+
triggers << entity_property
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
if defined?(entity_action) && entity_action
|
|
40
|
+
triggers << 'entity_action'
|
|
41
|
+
triggers << [entity_type, entity_action]*'_'
|
|
42
|
+
triggers << [entity, entity_action]*'_'
|
|
43
|
+
triggers << [entity_type, entity, entity_action]*'_'
|
|
44
|
+
triggers << entity_action
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
if defined?(task_name) && task_name
|
|
48
|
+
triggers << 'task'
|
|
49
|
+
triggers << task_name
|
|
50
|
+
triggers << [workflow, task_name]*"_"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
if defined?(preferences_changed) && preferences_changed.any?
|
|
54
|
+
triggers << ['preference']
|
|
55
|
+
preferences_changed.each do |preference|
|
|
56
|
+
triggers << [preference]
|
|
57
|
+
triggers << ['preference_' + preference]
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
triggers += triggers.collect{|t| status.collect{|s| [t, s]*"_" }}.flatten
|
|
62
|
+
|
|
63
|
+
triggers << status
|
|
64
|
+
|
|
65
|
+
headers['HX-Trigger'] = triggers * ", "
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'scout/knowledge_base'
|
|
2
|
+
|
|
3
|
+
module SinatraScoutKnowledgeBase
|
|
4
|
+
def self.registered(app)
|
|
5
|
+
# helpers for REST-style responses & params
|
|
6
|
+
app.set :knowledge_base, KnowledgeBase.load(:default)
|
|
7
|
+
|
|
8
|
+
app.helpers do
|
|
9
|
+
def knowledge_base
|
|
10
|
+
settings.knowledge_base
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module SinatraScoutTool
|
|
2
|
+
def self.registered(app)
|
|
3
|
+
app.helpers do
|
|
4
|
+
def tool(name, params = {})
|
|
5
|
+
record_js "/js/tool/#{name}.js" if ScoutRender.exists?("public/js/tool/#{name}.js")
|
|
6
|
+
record_css "/css/tool/#{name}.css" if ScoutRender.exists?("public/css/#{name}.css")
|
|
7
|
+
render_partial("tool/#{name}", params)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
require 'sinatra'
|
|
2
|
+
require_relative 'base'
|
|
3
|
+
require_relative 'knowledge_base'
|
|
4
|
+
|
|
5
|
+
module SinatraScoutWorkflow
|
|
6
|
+
def self.registered(app)
|
|
7
|
+
app.register SinatraScoutKnowledgeBase
|
|
8
|
+
|
|
9
|
+
app.set :registered_workflows, {}
|
|
10
|
+
|
|
11
|
+
# helpers for REST-style responses & params
|
|
12
|
+
app.helpers do
|
|
13
|
+
# prepare task inputs: read keys from provided task_info[:inputs]
|
|
14
|
+
def consume_task_parameters_for(workflow, task, params_hash)
|
|
15
|
+
task_info = workflow.task_info(task.to_sym)
|
|
16
|
+
inputs = {}
|
|
17
|
+
task_info[:inputs].each do |k|
|
|
18
|
+
v = params_hash[k.to_s]
|
|
19
|
+
inputs[k.to_sym] = v unless v.nil?
|
|
20
|
+
# accept file parts named "#{k}__param_file" (Rack file upload hash)
|
|
21
|
+
if params_hash["#{k}__param_file"]
|
|
22
|
+
inputs["#{k}__param_file"] = params_hash["#{k}__param_file"]
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
inputs
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def workflow_render(workflow, template, params = {})
|
|
29
|
+
params[:workflow] = workflow
|
|
30
|
+
case template
|
|
31
|
+
when :tasks
|
|
32
|
+
render_template('tasks', params)
|
|
33
|
+
when Symbol, String
|
|
34
|
+
render_template("#{workflow}/#{template}", params.merge(task: template))
|
|
35
|
+
when Step
|
|
36
|
+
job = template
|
|
37
|
+
task_name = job.task_name
|
|
38
|
+
render_template("#{workflow}/#{task_name}", params.merge(task: task_name, job: job))
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def workflow_template(workflow, task, type = :job)
|
|
43
|
+
workflow_name = Workflow === workflow ? workflow.name : workflow.to_s
|
|
44
|
+
file = File.join(workflow_name, task.to_s, type.to_s)
|
|
45
|
+
return file if ScoutRender.exists?(file)
|
|
46
|
+
|
|
47
|
+
workflow_name = Workflow === workflow ? workflow.name : workflow.to_s
|
|
48
|
+
file = File.join(workflow_name, task.to_s)
|
|
49
|
+
return file if ScoutRender.exists?(file)
|
|
50
|
+
|
|
51
|
+
file = File.join(workflow_name, type.to_s)
|
|
52
|
+
return file if ScoutRender.exists?(file)
|
|
53
|
+
|
|
54
|
+
file = File.join(type.to_s)
|
|
55
|
+
return file if ScoutRender.exists?(file)
|
|
56
|
+
|
|
57
|
+
raise TemplateNotFoundException, "Workflow template not fond for workflow #{workflow_name} task #{task} type #{type}"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def render_job(workflow, job, params = {})
|
|
61
|
+
task = job.task_name
|
|
62
|
+
template = workflow_template(workflow, task)
|
|
63
|
+
render_template(template, params.merge(job: job, task: task, workflow: workflow))
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def job_url(job)
|
|
67
|
+
workflow = job.workflow
|
|
68
|
+
task = job.task_name
|
|
69
|
+
name = job.name
|
|
70
|
+
workflow_name = Workflow === workflow ? workflow.name : workflow.to_s
|
|
71
|
+
|
|
72
|
+
'/' + [workflow_name, task, name] * "/"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def workflow_name
|
|
76
|
+
return nil unless task_name
|
|
77
|
+
return fullpath.split("/")[1]
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def workflow
|
|
81
|
+
return nil unless workflow_name
|
|
82
|
+
Kernel.const_get workflow_name
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def job_name
|
|
86
|
+
splat * "/"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def job
|
|
90
|
+
return nil unless task_name
|
|
91
|
+
return nil unless job_name
|
|
92
|
+
job = workflow.load_job task_name, job_name
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# expose method to register a workflow at runtime
|
|
97
|
+
app.define_singleton_method(:add_workflow) do |workflow, opts = {}|
|
|
98
|
+
name = workflow.to_s.split('::').last
|
|
99
|
+
settings.registered_workflows[name] = workflow
|
|
100
|
+
settings.knowledge_base = workflow.knowledge_base if workflow.knowledge_base
|
|
101
|
+
ScoutRender.prepend_path name, workflow.libdir
|
|
102
|
+
|
|
103
|
+
# GET /<workflow> - exports
|
|
104
|
+
app.get "/#{name}/:task_name/*" do
|
|
105
|
+
job = workflow.load_job task_name, job_name
|
|
106
|
+
|
|
107
|
+
case _format
|
|
108
|
+
when :info
|
|
109
|
+
serve_step_info job
|
|
110
|
+
when :json
|
|
111
|
+
serve_step_json job
|
|
112
|
+
when :raw
|
|
113
|
+
serve_step_raw job
|
|
114
|
+
else
|
|
115
|
+
serve_step job, _layout, params do
|
|
116
|
+
begin
|
|
117
|
+
render_job workflow, job, params
|
|
118
|
+
rescue TemplateNotFoundException
|
|
119
|
+
halt 200, "Job #{job.short_path} done"
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
app.register_common_parameter(:task_name, :symbol)
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
data/lib/scout-camp.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
require 'scout'
|
|
2
2
|
require 'scout/path'
|
|
3
3
|
require 'scout/resource'
|
|
4
|
-
Path.add_path :
|
|
4
|
+
Path.add_path :scout_camp_lib, File.join(Path.caller_lib_dir(__FILE__), "{TOPLEVEL}/{SUBPATH}")
|
|
5
5
|
require 'scout/terraform_dsl'
|
|
6
6
|
require 'scout/offsite'
|
|
7
7
|
require 'scout/aws/s3'
|
data/scout-camp.gemspec
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
|
3
3
|
# Instead, edit Juwelier::Tasks in Rakefile, and run 'rake gemspec'
|
|
4
4
|
# -*- encoding: utf-8 -*-
|
|
5
|
-
# stub: scout-camp 0.1.
|
|
5
|
+
# stub: scout-camp 0.1.14 ruby lib
|
|
6
6
|
|
|
7
7
|
Gem::Specification.new do |s|
|
|
8
8
|
s.name = "scout-camp".freeze
|
|
9
|
-
s.version = "0.1.
|
|
9
|
+
s.version = "0.1.14".freeze
|
|
10
10
|
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
|
|
12
12
|
s.require_paths = ["lib".freeze]
|
|
@@ -26,6 +26,7 @@ Gem::Specification.new do |s|
|
|
|
26
26
|
"Rakefile",
|
|
27
27
|
"VERSION",
|
|
28
28
|
"bin/scout-camp",
|
|
29
|
+
"doc/terraform.md",
|
|
29
30
|
"lib/scout-camp.rb",
|
|
30
31
|
"lib/scout/aws/s3.rb",
|
|
31
32
|
"lib/scout/offsite.rb",
|
|
@@ -34,10 +35,32 @@ Gem::Specification.new do |s|
|
|
|
34
35
|
"lib/scout/offsite/ssh.rb",
|
|
35
36
|
"lib/scout/offsite/step.rb",
|
|
36
37
|
"lib/scout/offsite/sync.rb",
|
|
38
|
+
"lib/scout/render.rb",
|
|
39
|
+
"lib/scout/render/engine.rb",
|
|
40
|
+
"lib/scout/render/helpers.rb",
|
|
41
|
+
"lib/scout/render/resource.rb",
|
|
42
|
+
"lib/scout/sinatra/auth.rb",
|
|
43
|
+
"lib/scout/sinatra/base.rb",
|
|
44
|
+
"lib/scout/sinatra/base/assets.rb",
|
|
45
|
+
"lib/scout/sinatra/base/favicon.rb",
|
|
46
|
+
"lib/scout/sinatra/base/headers.rb",
|
|
47
|
+
"lib/scout/sinatra/base/helpers.rb",
|
|
48
|
+
"lib/scout/sinatra/base/parameters.rb",
|
|
49
|
+
"lib/scout/sinatra/base/post_processing.rb",
|
|
50
|
+
"lib/scout/sinatra/base/session.rb",
|
|
51
|
+
"lib/scout/sinatra/entity.rb",
|
|
52
|
+
"lib/scout/sinatra/finder.rb",
|
|
53
|
+
"lib/scout/sinatra/fragment.rb",
|
|
54
|
+
"lib/scout/sinatra/htmx.rb",
|
|
55
|
+
"lib/scout/sinatra/knowledge_base.rb",
|
|
56
|
+
"lib/scout/sinatra/tool.rb",
|
|
57
|
+
"lib/scout/sinatra/workflow.rb",
|
|
37
58
|
"lib/scout/terraform_dsl.rb",
|
|
38
59
|
"lib/scout/terraform_dsl/deployment.rb",
|
|
39
60
|
"lib/scout/terraform_dsl/util.rb",
|
|
40
61
|
"scout-camp.gemspec",
|
|
62
|
+
"scout_commands/find",
|
|
63
|
+
"scout_commands/glob",
|
|
41
64
|
"scout_commands/offsite",
|
|
42
65
|
"scout_commands/sync",
|
|
43
66
|
"scout_commands/terraform/add/lambda",
|
|
@@ -111,16 +134,29 @@ Gem::Specification.new do |s|
|
|
|
111
134
|
"test/scout/offsite/test_ssh.rb",
|
|
112
135
|
"test/scout/offsite/test_step.rb",
|
|
113
136
|
"test/scout/offsite/test_sync.rb",
|
|
137
|
+
"test/scout/render/test_engine.rb",
|
|
138
|
+
"test/scout/render/test_resource.rb",
|
|
139
|
+
"test/scout/sinatra/base/test_headers.rb",
|
|
140
|
+
"test/scout/sinatra/base/test_parameters.rb",
|
|
141
|
+
"test/scout/sinatra/test_base.rb",
|
|
142
|
+
"test/scout/sinatra/test_entity.rb",
|
|
143
|
+
"test/scout/sinatra/test_render.rb",
|
|
144
|
+
"test/scout/sinatra/test_workflow.rb",
|
|
114
145
|
"test/scout/test_terraform_dsl.rb",
|
|
115
146
|
"test/test_helper.rb"
|
|
116
147
|
]
|
|
117
148
|
s.homepage = "http://github.com/mikisvaz/scout-camp".freeze
|
|
118
149
|
s.licenses = ["MIT".freeze]
|
|
119
|
-
s.rubygems_version = "3.
|
|
150
|
+
s.rubygems_version = "3.7.0.dev".freeze
|
|
120
151
|
s.summary = "Deploy you scouts".freeze
|
|
121
152
|
|
|
122
153
|
s.specification_version = 4
|
|
123
154
|
|
|
124
155
|
s.add_runtime_dependency(%q<scout-essentials>.freeze, [">= 0".freeze])
|
|
156
|
+
s.add_runtime_dependency(%q<aws-sdk-s3>.freeze, [">= 0".freeze])
|
|
157
|
+
s.add_runtime_dependency(%q<sinatra>.freeze, [">= 0".freeze])
|
|
158
|
+
s.add_runtime_dependency(%q<omniauth>.freeze, [">= 0".freeze])
|
|
159
|
+
s.add_runtime_dependency(%q<mimemagic>.freeze, [">= 0".freeze])
|
|
160
|
+
s.add_runtime_dependency(%q<omniauth-google-oauth2>.freeze, [">= 0".freeze])
|
|
125
161
|
end
|
|
126
162
|
|
data/scout_commands/find
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
|
|
3
|
+
require 'scout-camp'
|
|
4
|
+
|
|
5
|
+
$0 = "scout #{$previous_commands.any? ? $previous_commands*" " + " " : "" }#{ File.basename(__FILE__) }" if $previous_commands
|
|
6
|
+
|
|
7
|
+
options = SOPT.setup <<EOF
|
|
8
|
+
|
|
9
|
+
Find files
|
|
10
|
+
|
|
11
|
+
$ #{$0} [<options>] (<resource> <path>|<path>)
|
|
12
|
+
|
|
13
|
+
-h--help Print this help
|
|
14
|
+
-r--requires* Files to require; 'all' for all in Scout.etc.requires
|
|
15
|
+
-lw--load_workflow* Files to require; 'all' for all in Scout.etc.requires
|
|
16
|
+
-w--where* Where to look for the path
|
|
17
|
+
EOF
|
|
18
|
+
if options[:help]
|
|
19
|
+
if defined? scout_usage
|
|
20
|
+
scout_usage
|
|
21
|
+
else
|
|
22
|
+
puts SOPT.doc
|
|
23
|
+
end
|
|
24
|
+
exit 0
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
resource, path = ARGV
|
|
28
|
+
path, resource = resource, nil if path.nil?
|
|
29
|
+
|
|
30
|
+
raise MissingParameterException.new(:path) if path.nil?
|
|
31
|
+
|
|
32
|
+
case options[:workflows]
|
|
33
|
+
when nil, false, "false", "none"
|
|
34
|
+
when "all"
|
|
35
|
+
Scout.etc.workflows.list.each do |workflow|
|
|
36
|
+
Workflow.require_workflow file
|
|
37
|
+
end if Scout.etc.workflows.exists?
|
|
38
|
+
else
|
|
39
|
+
options[:workflows].split(/[ ,;|]/).each do |workflow|
|
|
40
|
+
Workflow.require_workflow workflow
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
case options[:requires]
|
|
45
|
+
when nil, false, "false", "none"
|
|
46
|
+
when "all"
|
|
47
|
+
Scout.etc.requires.list.each do |file|
|
|
48
|
+
require file
|
|
49
|
+
end if Scout.etc.requires.exists?
|
|
50
|
+
else
|
|
51
|
+
options[:requires].split(/[ ,;|]/).each do |file|
|
|
52
|
+
require file
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
location = nil
|
|
57
|
+
where = options[:where]
|
|
58
|
+
all = options[:all]
|
|
59
|
+
|
|
60
|
+
begin
|
|
61
|
+
resource = Workflow.require_workflow resource
|
|
62
|
+
rescue
|
|
63
|
+
begin
|
|
64
|
+
resource = Kernel.const_get(resource)
|
|
65
|
+
rescue
|
|
66
|
+
raise "Resource not found: #{ resource }"
|
|
67
|
+
end
|
|
68
|
+
end if resource
|
|
69
|
+
|
|
70
|
+
path = (resource || Scout)[path.dup]
|
|
71
|
+
|
|
72
|
+
if where.nil? || where == 'all' || path.path_maps.include?(where.to_sym)
|
|
73
|
+
location = path.find(where)
|
|
74
|
+
|
|
75
|
+
if Array === location
|
|
76
|
+
puts location * "\n"
|
|
77
|
+
else
|
|
78
|
+
location = nil if ! Open.exists?(location)
|
|
79
|
+
puts location
|
|
80
|
+
end
|
|
81
|
+
else
|
|
82
|
+
puts SSHLine.command(where, $0, ARGV, options.merge("where" => :all, add_option_dashes: true))
|
|
83
|
+
end
|