gd_bam 0.1.14 → 0.1.15
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/bam/version.rb +1 -1
- data/lib/generators/downloaders.rb +62 -53
- metadata +2 -4
- data/bin/bam.orig +0 -375
- data/lib/generators/downloaders.rb.orig +0 -663
data/lib/bam/version.rb
CHANGED
@@ -378,72 +378,81 @@ HEREDOC
|
|
378
378
|
builder.Phase(:number => phase += 1) do
|
379
379
|
|
380
380
|
f = field[:name]
|
381
|
-
selects =
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
[
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
]}}",
|
405
|
-
["#{sf_object}Id", "NewValue", "CreatedDate"]
|
406
|
-
]
|
407
|
-
elsif specific_history
|
408
|
-
if f == "CreatedDate"
|
381
|
+
selects = if (f == "CreatedDate") then
|
382
|
+
[{
|
383
|
+
:object => sf_object,
|
384
|
+
:query => "SELECT Id, CreatedDate FROM #{sf_object}",
|
385
|
+
:mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
|
386
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Value\"}},
|
387
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
388
|
+
{\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
|
389
|
+
]}}",
|
390
|
+
:mandatory => ["Id", "CreatedDate"]
|
391
|
+
}]
|
392
|
+
# binding.pry
|
393
|
+
# temp
|
394
|
+
else
|
395
|
+
objects_to_get.reduce([]) do |memo, o|
|
396
|
+
fields = client.fields(o)
|
397
|
+
# how the history is stored does not rely on table naming convention. It is a couple of conventionsmangled together.This piece of code is trying to recognize which it is and produce the right downloader
|
398
|
+
generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|fl| fields.include?(fl)}
|
399
|
+
specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
|
400
|
+
specific_history = ["CreatedDate", "#{sf_object}Id"].all? {|fl| fields.include?(fl)}
|
401
|
+
|
402
|
+
select, mapping, mandatory = if generic_field_history
|
403
|
+
# This kicks in when you have Field History type of table. There are several versions in SF. This one deals with the one that references ID of the record as Pernt Id. This is not true for opportunity, account.
|
409
404
|
[
|
410
|
-
"SELECT CreatedDate, #{
|
405
|
+
"SELECT NewValue, CreatedDate, ParentId FROM #{o} WHERE Field = '#{f}'",
|
411
406
|
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
412
|
-
{\"xmlFieldMapping\":{\"name\":\"
|
407
|
+
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
413
408
|
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
414
|
-
{\"xmlFieldMapping\":{\"name\":\"
|
409
|
+
{\"xmlFieldMapping\":{\"name\":\"ParentId\",\"label\":\"ParentId\",\"xmlPath\":\"ParentId\",\"metadataField\":\"Id\"}}
|
415
410
|
]}}",
|
416
|
-
["
|
411
|
+
["ParentId", "NewValue", "CreatedDate"]
|
417
412
|
]
|
418
|
-
elsif
|
413
|
+
elsif specific_field_history
|
414
|
+
# This is like the previous with the difference that it specifically names the id of the record. Like OpportunityId, AccountId, etc.
|
419
415
|
[
|
420
|
-
"SELECT
|
416
|
+
"SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
|
421
417
|
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
422
|
-
{\"xmlFieldMapping\":{\"name\":\"
|
418
|
+
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
423
419
|
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
424
420
|
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
425
421
|
]}}",
|
426
|
-
["#{sf_object}Id",
|
422
|
+
["#{sf_object}Id", "NewValue", "CreatedDate"]
|
427
423
|
]
|
424
|
+
elsif specific_history
|
425
|
+
# Specific history is the row like history. The only instance I know of is OpportunityHistory.
|
426
|
+
if fields.include?(f)
|
427
|
+
[
|
428
|
+
"SELECT #{f}, CreatedDate, #{sf_object}Id FROM #{o}",
|
429
|
+
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
430
|
+
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
431
|
+
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
432
|
+
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
433
|
+
]}}",
|
434
|
+
["#{sf_object}Id", f, "CreatedDate"]
|
435
|
+
]
|
436
|
+
else
|
437
|
+
[nil, nil, nil]
|
438
|
+
end
|
428
439
|
else
|
429
|
-
|
440
|
+
fail "Unrecognized fields configuration for historization in SF."
|
441
|
+
end
|
442
|
+
if select.nil?
|
443
|
+
memo
|
444
|
+
else
|
445
|
+
memo.concat([{
|
446
|
+
:object => o,
|
447
|
+
:query => select,
|
448
|
+
:mapping => mapping,
|
449
|
+
:mandatory => mandatory
|
450
|
+
}])
|
430
451
|
end
|
431
|
-
else
|
432
|
-
fail "Unrecognized fields configuration for historization in SF."
|
433
|
-
end
|
434
|
-
if select.nil?
|
435
|
-
memo
|
436
|
-
else
|
437
|
-
memo.concat([{
|
438
|
-
:object => o,
|
439
|
-
:query => select,
|
440
|
-
:mapping => mapping,
|
441
|
-
:mandatory => mandatory
|
442
|
-
}])
|
443
452
|
end
|
444
453
|
end
|
445
|
-
|
446
454
|
unless selects.empty?
|
455
|
+
# binding.pry if f== "CreatedDate"
|
447
456
|
taps_with_history.concat([tap])
|
448
457
|
selects = selects.concat([{
|
449
458
|
:object => sf_object,
|
@@ -456,15 +465,15 @@ HEREDOC
|
|
456
465
|
:mandatory => ["Id", f, "SystemModstamp"]
|
457
466
|
}])
|
458
467
|
selects.each_with_index do |obj, i|
|
459
|
-
|
468
|
+
# binding.pry if f== "CreatedDate"
|
460
469
|
o = obj[:object]
|
461
470
|
mapping = obj[:mapping]
|
462
471
|
select = obj[:query]
|
463
472
|
mandatory = obj[:mandatory]
|
464
473
|
# puts "#{f}_#{o}_reader:0 -> #{f}_#{sf_object}_gather:#{i}"
|
465
474
|
|
466
|
-
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
|
467
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_reader:0", :metadata => "data_metadata"}))
|
475
|
+
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_#{i}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
|
476
|
+
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_#{i}_reader:0", :metadata => "data_metadata"}))
|
468
477
|
end
|
469
478
|
Core::build_node2(builder, Nodes.gather2({:name => "#{f} Gather", :id => "#{f}_#{sf_object}_gather"}))
|
470
479
|
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{f}_#{sf_object}_sort", :id => "#{f}_#{sf_object}_sort"}))
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gd_bam
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.15
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-07-
|
12
|
+
date: 2013-07-23 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rake
|
@@ -308,7 +308,6 @@ extra_rdoc_files:
|
|
308
308
|
- README.md
|
309
309
|
files:
|
310
310
|
- bin/bam
|
311
|
-
- bin/bam.orig
|
312
311
|
- lib/bam/version.rb
|
313
312
|
- lib/bam.rb
|
314
313
|
- lib/base/errors.rb
|
@@ -339,7 +338,6 @@ files:
|
|
339
338
|
- lib/compiler/etl_visitor.rb
|
340
339
|
- lib/dsl/dsl.rb
|
341
340
|
- lib/generators/downloaders.rb
|
342
|
-
- lib/generators/downloaders.rb.orig
|
343
341
|
- lib/generators/etl.rb
|
344
342
|
- lib/generators/validators.rb
|
345
343
|
- lib/graphs/docentize.grf
|
data/bin/bam.orig
DELETED
@@ -1,375 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
require 'gli'
|
3
|
-
require 'bam'
|
4
|
-
|
5
|
-
include GLI::App
|
6
|
-
|
7
|
-
program_desc 'Describe your application here'
|
8
|
-
|
9
|
-
version Bam::VERSION
|
10
|
-
|
11
|
-
# desc 'Describe some switch here'
|
12
|
-
# switch [:s,:switch]
|
13
|
-
#
|
14
|
-
desc 'Verbose'
|
15
|
-
default_value false
|
16
|
-
arg_name 'verbose'
|
17
|
-
switch [:v,:verbose]
|
18
|
-
|
19
|
-
desc 'Http logger'
|
20
|
-
default_value false
|
21
|
-
arg_name 'logger'
|
22
|
-
switch [:l,:logger]
|
23
|
-
|
24
|
-
desc 'Generates clover project based on information in current directory. The default ouptut is the directory ./clover-project'
|
25
|
-
# arg_name 'Describe arguments to new here'
|
26
|
-
command :generate do |c|
|
27
|
-
|
28
|
-
c.desc 'generate only specified flow'
|
29
|
-
c.arg_name 'only'
|
30
|
-
c.flag :only
|
31
|
-
|
32
|
-
c.action do |global_options,options,args|
|
33
|
-
params = PARAMS.merge(options).merge({
|
34
|
-
:project_name => "etl-#{PARAMS[:project_name]}",
|
35
|
-
:graph_repos => [
|
36
|
-
GoodData::Bam::Repository.create(:type => :file, :base => Pathname('./local_graphs').expand_path),
|
37
|
-
GoodData::Bam::Repository.create(:type => :file, :base => GoodData::CloverGenerator::BAM_DEFINED_GRAPHS_ROOT)
|
38
|
-
]})
|
39
|
-
GoodData::Bam::Commands::generate('.', params)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
desc 'Jacks into SF.'
|
44
|
-
# arg_name 'Describe arguments to new here'
|
45
|
-
command :sf_jack_in do |c|
|
46
|
-
|
47
|
-
c.action do |global_options,options,args|
|
48
|
-
GoodData::Bam::Commands::sf_jack_in(PARAMS)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
# desc 'Jacks into project.'
|
53
|
-
# # arg_name 'Describe arguments to new here'
|
54
|
-
# command :project_jack_in do |c|
|
55
|
-
#
|
56
|
-
# c.action do |global_options,options,args|
|
57
|
-
# GoodData::Bam::Commands::project_jack_in(PARAMS)
|
58
|
-
# end
|
59
|
-
# end
|
60
|
-
|
61
|
-
|
62
|
-
desc 'Validatates connection to SalesForce.'
|
63
|
-
# arg_name 'Describe arguments to new here'
|
64
|
-
command :sf_validate_connection do |c|
|
65
|
-
|
66
|
-
c.action do |global_options,options,args|
|
67
|
-
GoodData::Bam::Commands::sf_validate_connection(PARAMS)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
|
71
|
-
|
72
|
-
desc 'Generate data validator.'
|
73
|
-
# arg_name 'Describe arguments to new here'
|
74
|
-
command :generate_validator do |c|
|
75
|
-
c.action do |global_options,options,args|
|
76
|
-
GoodData::Bam::Commands::generate_validators('.', PARAMS.merge(options).merge({
|
77
|
-
:project_name => "validator-#{PARAMS[:project_name]}",
|
78
|
-
:graph_repos => [
|
79
|
-
GoodData::Bam::Repository.create(:type => :file, :base => './local_graphs'),
|
80
|
-
GoodData::Bam::Repository.create(:type => :file, :base => GoodData::CloverGenerator::BAM_DEFINED_GRAPHS_ROOT)
|
81
|
-
]
|
82
|
-
}))
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
desc 'Run data validator.'
|
87
|
-
# arg_name 'Describe arguments to new here'
|
88
|
-
command :run_validator do |c|
|
89
|
-
|
90
|
-
c.desc 'Checker process ID'
|
91
|
-
c.arg_name 'process'
|
92
|
-
c.flag :process
|
93
|
-
|
94
|
-
c.action do |global_options,options,args|
|
95
|
-
process = options[:process]
|
96
|
-
files = args.map {|f| Pathname(f)}
|
97
|
-
files.each do |f|
|
98
|
-
fail "Provded file \"#{f}\" does not exist." unless File.exist?(f)
|
99
|
-
end
|
100
|
-
fail "You need to specify process" if process.blank?
|
101
|
-
|
102
|
-
GoodData::Bam::Commands::connect_to_gd()
|
103
|
-
GoodData::Bam::Commands::run_validator(process, files, PARAMS)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
|
108
|
-
desc 'Generates clover project for downloaders.'
|
109
|
-
# arg_name 'Describe arguments to new here'
|
110
|
-
command :generate_downloaders do |c|
|
111
|
-
|
112
|
-
c.desc 's3 backup'
|
113
|
-
c.arg_name 'backup'
|
114
|
-
c.flag :backup
|
115
|
-
|
116
|
-
c.action do |global_options,options,args|
|
117
|
-
params = global_options[:user_params]
|
118
|
-
params = PARAMS.merge({
|
119
|
-
:project_name => "downloaders-#{PARAMS[:project_name]}",
|
120
|
-
:graph_repos => [
|
121
|
-
GoodData::Bam::Repository.create(:type => :file, :base => './local_graphs'),
|
122
|
-
GoodData::Bam::Repository.create(:type => :file, :base => GoodData::CloverGenerator::BAM_DEFINED_GRAPHS_ROOT)]
|
123
|
-
})
|
124
|
-
GoodData::Bam::Commands::generate_downloaders(".", params)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
command :generate_history_downloaders do |c|
|
129
|
-
|
130
|
-
c.desc 's3 backup'
|
131
|
-
c.arg_name 'backup'
|
132
|
-
c.flag :backup
|
133
|
-
|
134
|
-
c.action do |global_options,options,args|
|
135
|
-
params = global_options[:user_params]
|
136
|
-
params = PARAMS.merge({
|
137
|
-
:project_name => "downloaders-#{PARAMS[:project_name]}",
|
138
|
-
:graph_repos => [
|
139
|
-
GoodData::Bam::Repository.create(:type => :file, :base => './local_graphs'),
|
140
|
-
GoodData::Bam::Repository.create(:type => :file, :base => GoodData::CloverGenerator::BAM_DEFINED_GRAPHS_ROOT)]
|
141
|
-
})
|
142
|
-
<<<<<<< HEAD
|
143
|
-
GoodData::Bam::Commands::generate_downloaders(".", params)
|
144
|
-
=======
|
145
|
-
GoodData::Bam::Commands::generate_history_downloaders(".", params)
|
146
|
-
>>>>>>> Added historical SF downloader
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
desc 'Validates that the tap has the fields it is claimed it should have. This is supposed to make the mitigate errors during deploy.'
|
153
|
-
# arg_name 'Describe arguments to new here'
|
154
|
-
command :sf_taps_validate do |c|
|
155
|
-
c.action do |global_options,options,args|
|
156
|
-
verbose = global_options[:v]
|
157
|
-
params = PARAMS.merge({
|
158
|
-
:graph_repos => [
|
159
|
-
GoodData::Bam::Repository.create(:type => :file, :base => './local_graphs'),
|
160
|
-
GoodData::Bam::Repository.create(:type => :file, :base => GoodData::CloverGenerator::BAM_DEFINED_GRAPHS_ROOT)]})
|
161
|
-
result = GoodData::Bam::Commands::validate_sf_taps(params)
|
162
|
-
|
163
|
-
error = false
|
164
|
-
result.each_pair do |obj, fields|
|
165
|
-
if fields.empty?
|
166
|
-
puts HighLine::color("GOOD", :green) + " #{obj}"
|
167
|
-
else
|
168
|
-
error = true
|
169
|
-
puts HighLine::color("BAD", :red) + " #{obj} [" + fields.join(', ') + "]"
|
170
|
-
end
|
171
|
-
end
|
172
|
-
exit_now!("Errors found",exit_code=1) if error
|
173
|
-
end
|
174
|
-
end
|
175
|
-
|
176
|
-
desc "Prepares params.prm file for debugging that particular graph"
|
177
|
-
command :debug do |c|
|
178
|
-
c.action do |global_options,options,args|
|
179
|
-
fail "Arguments should be passed as \"project\" \"flow\" \"graph\"" if args.length < 3
|
180
|
-
GoodData::Bam::Commands::set_up_debug(args.first, args[1], args[2])
|
181
|
-
end
|
182
|
-
end
|
183
|
-
|
184
|
-
desc 'Validates that the tap has the fields it is claimed it should have. This is supposed to make the mitigate errors during deploy.'
|
185
|
-
# arg_name 'Describe arguments to new here'
|
186
|
-
command :docs do |c|
|
187
|
-
c.action do |global_options,options,args|
|
188
|
-
GoodData::Bam::Commands::generate_docs
|
189
|
-
end
|
190
|
-
end
|
191
|
-
|
192
|
-
desc 'Lists processes for the project.'
|
193
|
-
# arg_name 'Describe arguments to new here'
|
194
|
-
command :procs do |c|
|
195
|
-
|
196
|
-
c.desc 'procs for all projects'
|
197
|
-
c.arg_name 'all'
|
198
|
-
c.switch :all
|
199
|
-
|
200
|
-
c.action do |global_options,options,args|
|
201
|
-
out = GoodData::Bam::Commands::procs_list(options)
|
202
|
-
out.each do |proc|
|
203
|
-
puts proc.join(',')
|
204
|
-
end
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
|
209
|
-
desc 'Creates project'
|
210
|
-
command :project do |c|
|
211
|
-
|
212
|
-
c.desc 'blueprint name. Currently support goodsales'
|
213
|
-
c.arg_name 'blueprint'
|
214
|
-
c.flag :blueprint
|
215
|
-
|
216
|
-
c.desc 'token'
|
217
|
-
c.arg_name 'token'
|
218
|
-
c.flag :token
|
219
|
-
|
220
|
-
c.action do |global_options,options,args|
|
221
|
-
fail "You need to specify token to create a project" if options[:token].nil?
|
222
|
-
|
223
|
-
GoodData::Bam::Commands::connect_to_gd()
|
224
|
-
pid = case options[:blueprint]
|
225
|
-
when "goodsales"
|
226
|
-
"nt935rwzls50zfqwy6dh62tabu8h0ocy"
|
227
|
-
end
|
228
|
-
|
229
|
-
params = PARAMS.merge({:token => options[:token]})
|
230
|
-
|
231
|
-
new_project = if pid
|
232
|
-
GoodData::Bam::Commands.clone_project(pid, params)
|
233
|
-
else
|
234
|
-
GoodData::Bam::Commands.create_project(params)
|
235
|
-
end
|
236
|
-
|
237
|
-
puts "Your project pid is #{new_project}"
|
238
|
-
end
|
239
|
-
|
240
|
-
end
|
241
|
-
|
242
|
-
|
243
|
-
desc 'Generates structures'
|
244
|
-
arg_name 'what you want to generate project, tap, flow, sink'
|
245
|
-
command :scaffold do |c|
|
246
|
-
|
247
|
-
c.desc 'blueprint name. Currently support goodsales'
|
248
|
-
c.arg_name 'blueprint'
|
249
|
-
c.flag :blueprint
|
250
|
-
|
251
|
-
c.action do |global_options,options,args|
|
252
|
-
command = args.first
|
253
|
-
fail "You did not provide what I should scaffold. I can generate project, tap, flow, sink, graph_template nothing else" unless ["project", "tap", "flow", "sink", "graph_template"].include?(command)
|
254
|
-
case command
|
255
|
-
when "project"
|
256
|
-
directory = args[1]
|
257
|
-
fail "Directory has to be provided as an argument. See help" if directory.nil?
|
258
|
-
if options[:blueprint].nil?
|
259
|
-
GoodData::Bam::Commands::setup_bash_structure(directory)
|
260
|
-
else
|
261
|
-
case options[:blueprint]
|
262
|
-
when "goodsales"
|
263
|
-
system "git clone git://github.com/gooddata/goodsales_base.git #{directory}"
|
264
|
-
end
|
265
|
-
end
|
266
|
-
when "flow"
|
267
|
-
name = args[1]
|
268
|
-
fail "Name of the flow has to be provided as an argument. See help" if name.nil?
|
269
|
-
GoodData::Bam::Commands::setup_flow(name)
|
270
|
-
when "tap"
|
271
|
-
name = args[1]
|
272
|
-
fail "Name of the tap has to be provided as an argument. See help" if name.nil?
|
273
|
-
GoodData::Bam::Commands::setup_tap(name)
|
274
|
-
when "sink"
|
275
|
-
name = args[1]
|
276
|
-
fail "Name of the sink has to be provided as an argument. See help" if name.nil?
|
277
|
-
GoodData::Bam::Commands::setup_sink(name)
|
278
|
-
when "graph_template"
|
279
|
-
name = args[1]
|
280
|
-
target = args[2]
|
281
|
-
fail "Name of the template has to be provided as an argument. See help" if name.nil?
|
282
|
-
fail "Name of the target has to be provided as an argument. See help" if target.nil?
|
283
|
-
GoodData::Bam::Commands::generate_graph_template(name, target)
|
284
|
-
end
|
285
|
-
end
|
286
|
-
end
|
287
|
-
|
288
|
-
desc 'Runs the project on server'
|
289
|
-
command :model_sync do |c|
|
290
|
-
|
291
|
-
c.desc 'do not execute'
|
292
|
-
c.arg_name 'dry'
|
293
|
-
c.switch :dry
|
294
|
-
|
295
|
-
c.action do |global_options,options,args|
|
296
|
-
GoodData::Bam::Commands::model_sync('.', options)
|
297
|
-
end
|
298
|
-
end
|
299
|
-
|
300
|
-
|
301
|
-
desc 'Deploys the project on server and schedules it'
|
302
|
-
command :deploy do |c|
|
303
|
-
|
304
|
-
c.desc 'existing process id under which it is going to be redeployed'
|
305
|
-
c.arg_name 'process'
|
306
|
-
c.flag :process
|
307
|
-
|
308
|
-
c.desc 'name of the process'
|
309
|
-
c.arg_name 'name'
|
310
|
-
c.flag :name
|
311
|
-
|
312
|
-
c.action do |global_options,options,args|
|
313
|
-
dir = args.first
|
314
|
-
fail "You have to specify directory to deploy as an argument" if dir.nil?
|
315
|
-
fail "Specified directory does not exist" unless File.exist?(dir)
|
316
|
-
|
317
|
-
GoodData::Bam::Commands::connect_to_gd()
|
318
|
-
params = PARAMS.merge(global_options.merge(options))
|
319
|
-
response = GoodData::Bam::Commands::deploy(dir, params)
|
320
|
-
end
|
321
|
-
end
|
322
|
-
|
323
|
-
desc 'Runs the project on server'
|
324
|
-
command :run do |c|
|
325
|
-
|
326
|
-
c.desc 'email to addresses when the run is finished'
|
327
|
-
c.arg_name 'email'
|
328
|
-
c.flag :email
|
329
|
-
|
330
|
-
c.action do |global_options,options,args|
|
331
|
-
|
332
|
-
dir = args.first
|
333
|
-
fail "You have to specify directory to deploy as an argument" if dir.nil?
|
334
|
-
fail "Specified directory does not exist" unless File.exist?(dir)
|
335
|
-
|
336
|
-
params = PARAMS.merge(global_options.merge(options))
|
337
|
-
GoodData::Bam::Commands::connect_to_gd()
|
338
|
-
GoodData::Bam::Commands::run(dir, params)
|
339
|
-
end
|
340
|
-
end
|
341
|
-
|
342
|
-
|
343
|
-
pre do |global_options,command,options,args|
|
344
|
-
|
345
|
-
logger = Logger.new(STDOUT) if global_options[:l]
|
346
|
-
GoodData.logger = logger
|
347
|
-
params = GoodData::Bam::Utils::get_user_params('.')
|
348
|
-
s3_backup = GoodData::Bam::Utils::should_backup_to_s3?(params)
|
349
|
-
PARAMS = params.merge({:s3_backup => s3_backup})
|
350
|
-
|
351
|
-
# Pre logic here
|
352
|
-
# Return true to proceed; false to abort and not call the
|
353
|
-
# chosen command
|
354
|
-
# Use skips_pre before a command to skip this block
|
355
|
-
# on that command only
|
356
|
-
|
357
|
-
true
|
358
|
-
end
|
359
|
-
|
360
|
-
post do |global_options,command,options,args|
|
361
|
-
# Post logic here
|
362
|
-
# Use skips_post before a command to skip this
|
363
|
-
# block on that command only
|
364
|
-
verbose = global_options[:v]
|
365
|
-
puts HighLine::color("DONE", :green) if verbose
|
366
|
-
end
|
367
|
-
|
368
|
-
on_error do |exception|
|
369
|
-
pp exception.backtrace
|
370
|
-
# Error logic here
|
371
|
-
# return false to skip default error handling
|
372
|
-
true
|
373
|
-
end
|
374
|
-
|
375
|
-
exit run(ARGV)
|
@@ -1,663 +0,0 @@
|
|
1
|
-
module GoodData
|
2
|
-
module Bam
|
3
|
-
module Generators
|
4
|
-
module Downloaders
|
5
|
-
|
6
|
-
include GoodData::Bam
|
7
|
-
include GoodData::CloudConnect
|
8
|
-
|
9
|
-
def self.create_incremental_downloader_run_graph(file, taps, options={})
|
10
|
-
|
11
|
-
File.open(file, "w") do |file|
|
12
|
-
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
13
|
-
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
14
|
-
builder.Graph({
|
15
|
-
:name => "Run graph"
|
16
|
-
}) do
|
17
|
-
builder.Global do
|
18
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
19
|
-
Helpers::property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
|
20
|
-
Helpers::create_trash_meta(builder)
|
21
|
-
Helpers::create_lookup_meta(builder)
|
22
|
-
Helpers::create_file_list_meta(builder)
|
23
|
-
Helpers::create_run_graph_failure_metadata(builder)
|
24
|
-
|
25
|
-
Core::build_node2(builder, Nodes.lookup2({:name => "gdLookup0", :id => "gdLookup0", :type => Nodes::GD_LOOKUP, :metadata => "lookup_metadata"}))
|
26
|
-
|
27
|
-
end
|
28
|
-
phase = 0
|
29
|
-
sf_taps = Taps.get_salesforce(taps)
|
30
|
-
|
31
|
-
sf_taps.each do |tap|
|
32
|
-
module_name = tap[:object]
|
33
|
-
file = tap[:id] || module_name
|
34
|
-
dataset = file || module_name
|
35
|
-
|
36
|
-
|
37
|
-
normalize_code = <<HEREDOC
|
38
|
-
boolean done = false;
|
39
|
-
function integer count() {
|
40
|
-
|
41
|
-
if (indexOf($in.0.key, "#{dataset}_LAST_RUN") != -1) {
|
42
|
-
return 4;
|
43
|
-
}
|
44
|
-
else {
|
45
|
-
return 0;
|
46
|
-
}
|
47
|
-
}
|
48
|
-
|
49
|
-
string last_run = null;
|
50
|
-
string end_date = null;
|
51
|
-
|
52
|
-
function integer transform(integer idx) {
|
53
|
-
if (last_run == null) {
|
54
|
-
last_run = $in.0.value;
|
55
|
-
}
|
56
|
-
if (end_date == null) {
|
57
|
-
end_date = jodaDate2str(today(), "yyyy-MM-dd'T'HH:mm:ss.SSSZZ", "en_US", 'UTC');
|
58
|
-
}
|
59
|
-
|
60
|
-
|
61
|
-
if (idx == 1) {
|
62
|
-
$out.0.all = "#{dataset}_TRUNCATE_DATE=" + jodaDate2str(jodaStr2date(last_run, ["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC'), "yyyy-MM-dd HH:mm:ss", 'en_US', 'UTC');
|
63
|
-
} else if (idx == 2) {
|
64
|
-
$out.0.all = "#{dataset}_START=" + last_run;
|
65
|
-
} else if (idx == 3) {
|
66
|
-
$out.0.all = "#{dataset}_END=" + end_date;
|
67
|
-
} else {
|
68
|
-
$out.0.all = "#{dataset}_LAST_RUN=" + end_date;
|
69
|
-
}
|
70
|
-
|
71
|
-
return OK;
|
72
|
-
}
|
73
|
-
|
74
|
-
HEREDOC
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
builder.Phase(:number => phase += 1) do
|
80
|
-
generate_func = <<HEREDOC
|
81
|
-
function integer generate() {
|
82
|
-
$out.0.key = "#{dataset}_LAST_RUN";
|
83
|
-
$out.0.value = "1970-01-01T00:00:00.000+00:00";
|
84
|
-
return OK;
|
85
|
-
}
|
86
|
-
HEREDOC
|
87
|
-
|
88
|
-
join_func = <<HEREDOC
|
89
|
-
function integer transform() {
|
90
|
-
$out.0.key = nvl2($in.1.value, $in.1.key, $in.0.key);
|
91
|
-
$out.0.value = nvl2($in.1.value, $in.1.value, $in.0.value);
|
92
|
-
return OK;
|
93
|
-
}
|
94
|
-
HEREDOC
|
95
|
-
|
96
|
-
Core::build_node2(builder, Nodes.data_generator2({:name => "generator_#{dataset}", :id => "generator_#{dataset}", :generate => generate_func}))
|
97
|
-
Core::build_node2(builder, Nodes.lookup_reader_writer2({:lookupTable => "gdLookup0", :id => "gd_lookup_reader_#{dataset}" }))
|
98
|
-
Core::build_node2(builder, Nodes.hash_join2({:id => "join_#{dataset}", :joinType => "leftOuter", :joinKey => "$key=$key", :transformation => join_func}))
|
99
|
-
|
100
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "join_#{dataset}:0", :fromNode => "generator_#{dataset}:0", :metadata => "lookup_metadata"}))
|
101
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "join_#{dataset}:1", :fromNode => "gd_lookup_reader_#{dataset}:0", :metadata => "lookup_metadata"}))
|
102
|
-
|
103
|
-
Core::build_node2(builder, Nodes.normalizer2({:name => "normalizer_#{dataset}", :id => "normalizer_#{dataset}", :normalize => normalize_code }))
|
104
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "normalizer_#{dataset}:0", :fromNode => "join_#{dataset}:0", :metadata => "lookup_metadata"}))
|
105
|
-
|
106
|
-
Core::build_node2(builder, Nodes.writer2({:quotedStrings => "false", :name => "params_writer_#{dataset}", :id => "params_writer_#{dataset}", :fileURL => "params.prm", :outputFieldNames => "false", :append => "true"}))
|
107
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "params_writer_#{dataset}:0", :fromNode => "normalizer_#{dataset}:0", :metadata => "trash_metadata"}))
|
108
|
-
end
|
109
|
-
end
|
110
|
-
builder.Phase(:number => phase += 1) do
|
111
|
-
if !sf_taps.empty?
|
112
|
-
Core::build_node2(builder, Nodes.run_graph2({:guiName => "incremental", :name => "incremental_downloaders", :id => "downlaoders", :graphName => "graphs/incremental.grf"}))
|
113
|
-
end
|
114
|
-
end
|
115
|
-
|
116
|
-
file_taps = Taps.get_file(taps)
|
117
|
-
|
118
|
-
file_taps.each do |tap|
|
119
|
-
source = tap[:source]
|
120
|
-
id = tap[:id]
|
121
|
-
|
122
|
-
|
123
|
-
reformat_func = <<HEREDOC
|
124
|
-
|
125
|
-
function integer transform() {
|
126
|
-
$out.0.filePath = replace($in.0.filePath, "${GDC_WEBDAV_HOST}", replace(replace(\"${GD_LOGIN}\",\"@\",\"%40\"),\"\\\\+\",\"%2B\") + ":${GD_PASSWORD}@${GDC_WEBDAV_HOST}");
|
127
|
-
$out.0.fileName = $in.0.fileName;
|
128
|
-
return ALL;
|
129
|
-
}
|
130
|
-
HEREDOC
|
131
|
-
|
132
|
-
builder.Phase(:number => phase += 1) do
|
133
|
-
Core::build_node2(builder, Nodes.file_list2({:id => "#{id}_file_list", :name => "#{id}_file_list", :dataPolicy => "Strict", :baseURL => "#{tap[:source]}", :output_mapping => Nodes::MAP_ALL}))
|
134
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{id} Reformat", :id => "#{id}_reformat", :transformation => reformat_func}))
|
135
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_reformat:0", :fromNode => "#{id}_file_list:0", :metadata => "file_list"}))
|
136
|
-
Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id}_writer", :fileURL => "data/#{id}_files_to_read.csv"}))
|
137
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_writer:0", :fromNode => "#{id}_reformat:0", :metadata => "file_list"}))
|
138
|
-
end
|
139
|
-
|
140
|
-
builder.Phase(:number => phase += 1) do
|
141
|
-
ctl = "function integer generate() {$out.0.all = \"#{id}_SKIP_LINES=0\";return OK;}"
|
142
|
-
Core::build_node2(builder, Nodes.data_generator2({:name => "#{id}_generator", :id => "#{id}_generator", :generate => ctl}))
|
143
|
-
Core::build_node2(builder, Nodes.writer2({:name => "PARAMS CSV Writer", :id => "#{id}_csv_writer", :fileURL => "#{id}_counter.prm", :outputFieldNames => "false", :quotedStrings => "false"}))
|
144
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_csv_writer:0", :fromNode => "#{id}_generator:0", :metadata => "trash_metadata"}))
|
145
|
-
end
|
146
|
-
|
147
|
-
subgraph_reformat_func = <<HEREDOC
|
148
|
-
|
149
|
-
function integer transform() {
|
150
|
-
$out.0.all = "graphs/#{id}_loop.grf";
|
151
|
-
return ALL;
|
152
|
-
}
|
153
|
-
HEREDOC
|
154
|
-
|
155
|
-
fail_reformat = <<HEREDOC
|
156
|
-
function integer transform() {
|
157
|
-
raiseError("Loop failed");
|
158
|
-
}
|
159
|
-
HEREDOC
|
160
|
-
|
161
|
-
|
162
|
-
builder.Phase(:number => phase += 1) do
|
163
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{id} Reformat graph", :id => "#{id}_reformat_graph", :transformation => subgraph_reformat_func}))
|
164
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_reformat_graph:0", :fromNode => "#{id}_reformat:1", :metadata => "file_list"}))
|
165
|
-
Core::build_node2(builder, Nodes.run_graph2({
|
166
|
-
:guiName => id,
|
167
|
-
:name => id,
|
168
|
-
:id => "#{id}_run_graph"
|
169
|
-
}))
|
170
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_run_graph:0", :fromNode => "#{id}_reformat_graph:0", :metadata => "trash_metadata"}))
|
171
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{id} Reformat fail", :id => "#{id}_reformat_fail", :transformation => fail_reformat}))
|
172
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_reformat_fail:0", :fromNode => "#{id}_run_graph:1", :metadata => "run_graph_failure_metadata"}))
|
173
|
-
Core::build_node2(builder, Nodes.trash2({:name => "#{id}_trash", :id => "#{id}_trash", :debugPrint => true}))
|
174
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{id}_trash:0", :fromNode => "#{id}_reformat_fail:0", :metadata => "run_graph_failure_metadata"}))
|
175
|
-
end
|
176
|
-
end
|
177
|
-
|
178
|
-
|
179
|
-
end
|
180
|
-
end
|
181
|
-
end
|
182
|
-
|
183
|
-
def self.create_incremental_sf_downloading_graph(file, taps, options={})
|
184
|
-
metadata = options[:metadata]
|
185
|
-
store = options[:store] || "${GDC_EVENTSTORE}"
|
186
|
-
s3_backup = options[:s3_backup]
|
187
|
-
|
188
|
-
File.open(file, "w") do |file|
|
189
|
-
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
190
|
-
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
191
|
-
builder.Graph({:name => "Goodsales incremental Downloader"}) do
|
192
|
-
builder.Global do
|
193
|
-
Helpers::property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
|
194
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
195
|
-
|
196
|
-
Helpers::create_lookup_meta(builder)
|
197
|
-
taps.each do |tap|
|
198
|
-
module_name = tap[:object]
|
199
|
-
file = tap[:id] || module_name
|
200
|
-
|
201
|
-
builder.Metadata({:id => "#{file}_s3_metadata"}) do |builder|
|
202
|
-
Helpers::csv_metadata(builder, GoodData::Bam::Metadata.add_field(Metadata.get_target_metadata(Tap.prepare_for_s3_backup(tap)), {:name => "Timestamp"}))
|
203
|
-
end
|
204
|
-
|
205
|
-
tap = Tap.prepare_for_sf_downloader(tap)
|
206
|
-
builder.Metadata({:id => "#{file}_source_metadata"}) do |builder|
|
207
|
-
Helpers::csv_metadata(builder, Metadata.get_source_metadata(tap))
|
208
|
-
end
|
209
|
-
|
210
|
-
builder.Metadata({:id => "#{file}_es_metadata"}) do |builder|
|
211
|
-
Helpers::csv_metadata(builder, Metadata.add_timestamp_as_date(Metadata.get_target_metadata(tap)))
|
212
|
-
end
|
213
|
-
|
214
|
-
Core::build_node2(builder, Nodes.lookup2({:name => "gdLookup0", :id => "gdLookup0", :type => Nodes::GD_LOOKUP, :metadata => "lookup_metadata"}))
|
215
|
-
|
216
|
-
end
|
217
|
-
|
218
|
-
Helpers::sf_connection(builder, {})
|
219
|
-
Helpers::property(builder, {:id => "SFDC_CLIENT_ID", :value => "gooddata/gooddata/"})
|
220
|
-
Helpers::property(builder, {:id => "SFDC_LOGIN_HOSTNAME", :value => options[:sf_server] || "login.salesforce.com"})
|
221
|
-
Helpers::property(builder, {:id => "SFDC_NAME", :value => "Salesforce connection"})
|
222
|
-
Helpers::property(builder, {:id => "SFDC_PASSWORD", :value => options[:sf_password]})
|
223
|
-
Helpers::property(builder, {:id => "SFDC_TOKEN", :value => options[:sf_token]})
|
224
|
-
Helpers::property(builder, {:id => "SFDC_USERNAME", :value => options[:sf_login]})
|
225
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
226
|
-
end
|
227
|
-
|
228
|
-
phase = 1
|
229
|
-
|
230
|
-
taps.each do |tap|
|
231
|
-
module_name = tap[:object]
|
232
|
-
file = tap[:id]
|
233
|
-
dataset = file || module_name
|
234
|
-
source_file = tap[:source]
|
235
|
-
|
236
|
-
has_timestamp = Tap.has_output_field?(tap, "Timestamp")
|
237
|
-
timestamp_field = Tap.find_output_field(tap, "Timestamp")
|
238
|
-
id_field = Tap.find_output_field(tap, "Id")
|
239
|
-
tap = Tap.prepare_for_sf_downloader(tap)
|
240
|
-
builder.Phase(:number => phase += 1) do
|
241
|
-
Core::build_node2(builder, Nodes.es_truncate2({:guiName => dataset, :store => store, :entity => dataset, :timestamp => "${#{dataset}_TRUNCATE_DATE}", :name => "#{module_name} es truncate", :id => "#{module_name}_es_truncate"}))
|
242
|
-
end
|
243
|
-
|
244
|
-
builder.Phase(:number => phase += 1) do
|
245
|
-
fields = tap[:fields]
|
246
|
-
mapping = "{\"xmlFieldsMapping\":{\"xmlFields\":["
|
247
|
-
add = fields.map do |f|
|
248
|
-
"{\"xmlFieldMapping\":{\"name\":\"#{f[:name]}\",\"label\":\"#{f[:label]}\",\"xmlPath\":\"#{f[:name]}\",\"metadataField\":\"#{f[:name]}\"}}"
|
249
|
-
end
|
250
|
-
stuff = mapping + add.join(",") + "]}}"
|
251
|
-
|
252
|
-
mandatory_fields = fields.reject {|f| f[:is_mandatory] == false }.map {|f| f[:name] + ";"}.join
|
253
|
-
|
254
|
-
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{file} SF Reader", :id => "#{file}_reader", :soql => Helpers::generate_incremental_select(tap), :sfdcConnection => "SFDC", :fieldsMapping => stuff, :mandatoryFields => mandatory_fields}))
|
255
|
-
|
256
|
-
|
257
|
-
es_transformation_source = if has_timestamp
|
258
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");;\nreturn OK;\n}"
|
259
|
-
else
|
260
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = long2date(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"
|
261
|
-
end
|
262
|
-
|
263
|
-
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
|
264
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_copy:0", :fromNode => "#{file}_reader:0", :metadata => "#{file}_source_metadata"}))
|
265
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "disabled", :name => "#{file} CSV Writer", :id => "#{file}_csv", :fileURL => "data/#{dataset.downcase}.csv", :outputFieldNames => "true"}))
|
266
|
-
|
267
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_es_reformat", :transformation => es_transformation_source}))
|
268
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_reformat:0", :fromNode => "#{file}_copy:1", :metadata => "#{file}_source_metadata"}))
|
269
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_csv:0", :fromNode => "#{file}_copy:0", :metadata => "#{file}_source_metadata"}))
|
270
|
-
|
271
|
-
if s3_backup then
|
272
|
-
if has_timestamp
|
273
|
-
|
274
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
275
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
276
|
-
|
277
|
-
else
|
278
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_s3_reformat", :transformation => "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = toString(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"}))
|
279
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3_reformat:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
280
|
-
|
281
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
282
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_s3_reformat:0", :metadata => "#{file}_s3_metadata"}))
|
283
|
-
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
|
288
|
-
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{file} es Sort", :id => "#{file}_es_sort"}))
|
289
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_sort:0", :fromNode => "#{file}_es_reformat:0", :metadata => "#{file}_es_metadata"}))
|
290
|
-
|
291
|
-
Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{file}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json(Tap.add_timestamp_field(tap)).to_json}))
|
292
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es:0", :fromNode => "#{file}_es_sort:0", :metadata => "#{file}_es_metadata"}))
|
293
|
-
|
294
|
-
end
|
295
|
-
|
296
|
-
builder.Phase(:number => phase += 1) do
|
297
|
-
generate_func = <<HEREDOC
|
298
|
-
function integer generate() {
|
299
|
-
date time_end = jodaStr2date("${#{dataset}_END}",["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC');
|
300
|
-
$out.0.key = "#{dataset}_LAST_RUN";
|
301
|
-
$out.0.value = jodaDate2str(time_end,"yyyy-MM-dd'T'HH:mm:ss.SSSZZ", 'en_US', 'UTC');
|
302
|
-
return OK;
|
303
|
-
}
|
304
|
-
HEREDOC
|
305
|
-
|
306
|
-
Core::build_node2(builder, Nodes.data_generator2({:guiName => dataset, :name => "generator_#{phase}", :id => "generator_#{phase}", :generate => generate_func}))
|
307
|
-
Core::build_node2(builder, Nodes.lookup_reader_writer2({:guiName => dataset, :lookupTable => "gdLookup0", :id => "gd_lookup_reader_#{phase}" }))
|
308
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "gd_lookup_reader_#{phase}:0", :fromNode => "generator_#{phase}:0", :metadata => "lookup_metadata"}))
|
309
|
-
|
310
|
-
end
|
311
|
-
end
|
312
|
-
end
|
313
|
-
end
|
314
|
-
end
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
def self.create_incremental_sf_history_init_graph(file, taps, options={})
|
319
|
-
metadata = options[:metadata]
|
320
|
-
store = options[:store] || "${GDC_EVENTSTORE}"
|
321
|
-
s3_backup = options[:s3_backup]
|
322
|
-
|
323
|
-
|
324
|
-
client = GoodData::Bam::Commands.get_sf_client(options)
|
325
|
-
|
326
|
-
File.open(file, "w") do |file|
|
327
|
-
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
328
|
-
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
329
|
-
builder.Graph({:name => "Goodsales incremental Downloader"}) do
|
330
|
-
builder.Global do
|
331
|
-
Helpers::property_file(builder, {:id => "params_params", :fileURL => "params.prm"})
|
332
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
333
|
-
|
334
|
-
Helpers::create_lookup_meta(builder)
|
335
|
-
builder.Metadata({:id => "data_metadata"}) do |builder|
|
336
|
-
Helpers::csv_metadata(builder, {:name => "data_metadata",:fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => "Value"}]})
|
337
|
-
end
|
338
|
-
|
339
|
-
builder.Metadata({:id => "es_metadata"}) do |builder|
|
340
|
-
Helpers::csv_metadata(builder, {:name => "data_metadata",:fields => [{:name => "Id"}, {:name => "Timestamp", :type => "date"}, {:name => "Value"}]})
|
341
|
-
end
|
342
|
-
|
343
|
-
Core::build_node2(builder, Nodes.lookup2({:name => "gdLookup0", :id => "gdLookup0", :type => Nodes::GD_LOOKUP, :metadata => "lookup_metadata"}))
|
344
|
-
|
345
|
-
Helpers::sf_connection(builder, {})
|
346
|
-
Helpers::property(builder, {:id => "SFDC_CLIENT_ID", :value => "gooddata/gooddata/"})
|
347
|
-
Helpers::property(builder, {:id => "SFDC_LOGIN_HOSTNAME", :value => options[:sf_server] || "login.salesforce.com"})
|
348
|
-
Helpers::property(builder, {:id => "SFDC_NAME", :value => "Salesforce connection"})
|
349
|
-
Helpers::property(builder, {:id => "SFDC_PASSWORD", :value => options[:sf_password]})
|
350
|
-
Helpers::property(builder, {:id => "SFDC_TOKEN", :value => options[:sf_token]})
|
351
|
-
Helpers::property(builder, {:id => "SFDC_USERNAME", :value => options[:sf_login]})
|
352
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
353
|
-
end
|
354
|
-
|
355
|
-
phase = 1
|
356
|
-
|
357
|
-
taps_with_history = []
|
358
|
-
taps.each do |tap|
|
359
|
-
module_name = tap[:object]
|
360
|
-
dataset = tap[:id]
|
361
|
-
source_file = tap[:source]
|
362
|
-
|
363
|
-
has_timestamp = Tap.has_output_field?(tap, "Timestamp")
|
364
|
-
timestamp_field = Tap.find_output_field(tap, "Timestamp")
|
365
|
-
id_field = Tap.find_output_field(tap, "Id")
|
366
|
-
tap = Tap.prepare_for_sf_downloader(tap)
|
367
|
-
builder.Phase(:number => phase += 1) do
|
368
|
-
# Core::build_node2(builder, Nodes.es_truncate2({:guiName => dataset, :store => store, :entity => dataset, :timestamp => "${#{dataset}_TRUNCATE_DATE}", :name => "#{module_name} es truncate", :id => "#{module_name}_es_truncate"}))
|
369
|
-
end
|
370
|
-
|
371
|
-
fields = tap[:fields]
|
372
|
-
|
373
|
-
puts tap[:object]
|
374
|
-
sf_object = tap[:object]
|
375
|
-
id_field = Tap.find_output_field(tap, "Id")
|
376
|
-
timestamp_field = Tap.find_output_field(tap, "Timestamp")
|
377
|
-
|
378
|
-
|
379
|
-
objects_to_get = Helpers.objects_for_history(client, tap)
|
380
|
-
|
381
|
-
(tap[:fields] - [id_field, timestamp_field]).each_with_index do |field, i|
|
382
|
-
builder.Phase(:number => phase += 1) do
|
383
|
-
|
384
|
-
f = field[:name]
|
385
|
-
|
386
|
-
selects = objects_to_get.reduce([]) do |memo, o|
|
387
|
-
fields = client.fields(o)
|
388
|
-
generic_field_history = ["NewValue", "OldValue", "ParentId"].all? {|f| fields.include?(f)}
|
389
|
-
specific_field_history = ["NewValue", "OldValue", "#{sf_object}Id"].all? {|f| fields.include?(f)}
|
390
|
-
specific_history = ["SystemModstamp", "#{sf_object}Id"].all? {|f| fields.include?(f)}
|
391
|
-
|
392
|
-
select, mapping, mandatory = if generic_field_history
|
393
|
-
[
|
394
|
-
"SELECT NewValue, CreatedDate, ParentId FROM #{o} WHERE Field = '#{f}'",
|
395
|
-
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
396
|
-
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
397
|
-
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
398
|
-
{\"xmlFieldMapping\":{\"name\":\"ParentId\",\"label\":\"ParentId\",\"xmlPath\":\"ParentId\",\"metadataField\":\"Id\"}}
|
399
|
-
]}}",
|
400
|
-
["ParentId", "NewValue", "CreatedDate"]
|
401
|
-
]
|
402
|
-
elsif specific_field_history
|
403
|
-
[
|
404
|
-
|
405
|
-
"SELECT NewValue, CreatedDate, #{sf_object}Id FROM #{o} WHERE Field = '#{f}'",
|
406
|
-
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
407
|
-
{\"xmlFieldMapping\":{\"name\":\"NewValue\",\"label\":\"NewValue\",\"xmlPath\":\"NewValue\",\"metadataField\":\"Value\"}},
|
408
|
-
{\"xmlFieldMapping\":{\"name\":\"CreatedDate\",\"label\":\"CreatedDate\",\"xmlPath\":\"CreatedDate\",\"metadataField\":\"Timestamp\"}},
|
409
|
-
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{sf_object}Id\",\"xmlPath\":\"#{sf_object}Id\",\"metadataField\":\"Id\"}}
|
410
|
-
]}}",
|
411
|
-
["#{sf_object}Id", "NewValue", "CreatedDate"]
|
412
|
-
]
|
413
|
-
elsif specific_history
|
414
|
-
if fields.include?(f)
|
415
|
-
[
|
416
|
-
"SELECT #{f}, SystemModstamp, #{sf_object}Id FROM #{o}",
|
417
|
-
"{\"xmlFieldsMapping\":{\"xmlFields\":[
|
418
|
-
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
419
|
-
{\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
|
420
|
-
{\"xmlFieldMapping\":{\"name\":\"#{sf_object}Id\",\"label\":\"#{o}Id\",\"xmlPath\":\"#{o}Id\",\"metadataField\":\"Id\"}}
|
421
|
-
]}}",
|
422
|
-
["#{sf_object}Id", f, "SystemModstamp"]
|
423
|
-
]
|
424
|
-
else
|
425
|
-
[nil, nil]
|
426
|
-
end
|
427
|
-
else
|
428
|
-
fail "Unrecognized fields configuration for historization in SF."
|
429
|
-
end
|
430
|
-
if select.nil?
|
431
|
-
memo
|
432
|
-
else
|
433
|
-
memo.concat([{
|
434
|
-
:object => o,
|
435
|
-
:query => select,
|
436
|
-
<<<<<<< HEAD
|
437
|
-
:mapping => mapping
|
438
|
-
=======
|
439
|
-
:mapping => mapping,
|
440
|
-
:mandatory => mandatory
|
441
|
-
>>>>>>> Added historical SF downloader
|
442
|
-
}])
|
443
|
-
end
|
444
|
-
end
|
445
|
-
|
446
|
-
unless selects.empty?
|
447
|
-
taps_with_history.concat([tap])
|
448
|
-
selects = selects.concat([{
|
449
|
-
:object => sf_object,
|
450
|
-
:query => "SELECT Id, #{f}, SystemModstamp FROM #{sf_object}",
|
451
|
-
:mapping => "{\"xmlFieldsMapping\":{\"xmlFields\":[
|
452
|
-
{\"xmlFieldMapping\":{\"name\":\"#{f}\",\"label\":\"#{f}\",\"xmlPath\":\"#{f}\",\"metadataField\":\"Value\"}},
|
453
|
-
{\"xmlFieldMapping\":{\"name\":\"SystemModstamp\",\"label\":\"SystemModstamp\",\"xmlPath\":\"SystemModstamp\",\"metadataField\":\"Timestamp\"}},
|
454
|
-
{\"xmlFieldMapping\":{\"name\":\"Id\",\"label\":\"Id\",\"xmlPath\":\"Id\",\"metadataField\":\"Id\"}}
|
455
|
-
]}}",
|
456
|
-
:mandatory => ["Id", f, "SystemModstamp"]
|
457
|
-
}])
|
458
|
-
selects.each_with_index do |obj, i|
|
459
|
-
|
460
|
-
o = obj[:object]
|
461
|
-
mapping = obj[:mapping]
|
462
|
-
select = obj[:query]
|
463
|
-
mandatory = obj[:mandatory]
|
464
|
-
|
465
|
-
Core::build_node2(builder, Nodes.sfdc_reader2({:name => "#{o} SF Reader #{i}", :id => "#{f}_#{o}_reader", :soql => select, :sfdcConnection => "SFDC", :fieldsMapping => mapping, :mandatoryFields => mandatory.join(';')}))
|
466
|
-
puts "#{f}_#{o}_reader:0 -> #{f}_#{sf_object}_gather:#{i}"
|
467
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_gather:#{i}", :fromNode => "#{f}_#{o}_reader:0", :metadata => "data_metadata"}))
|
468
|
-
end
|
469
|
-
Core::build_node2(builder, Nodes.gather2({:name => "#{f} Gather", :id => "#{f}_#{sf_object}_gather"}))
|
470
|
-
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{f}_#{sf_object}_sort", :id => "#{f}_#{sf_object}_sort"}))
|
471
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_sort:0", :fromNode => "#{f}_#{sf_object}_gather:0", :metadata => "data_metadata"}))
|
472
|
-
|
473
|
-
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{f}_#{sf_object}_copy"}))
|
474
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_copy:0", :fromNode => "#{f}_#{sf_object}_sort:0", :metadata => "data_metadata"}))
|
475
|
-
|
476
|
-
if s3_backup
|
477
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{f}_#{sf_object} s3 Writer", :id => "#{f}_#{sf_object}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{sf_object}/#{f}_#{sf_object}_\`date2long(today())\`", :outputFieldNames => true}))
|
478
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_s3:0", :fromNode => "#{f}_#{sf_object}_copy:1", :metadata => "data_metadata"}))
|
479
|
-
end
|
480
|
-
|
481
|
-
transform = "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = str2date($in.0.Timestamp,\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");\nreturn OK;\n}"
|
482
|
-
|
483
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "Reformat", :id => "#{f}_#{sf_object}_reformat", :transformation => transform}))
|
484
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_reformat:0", :fromNode => "#{f}_#{sf_object}_copy:0", :metadata => "data_metadata"}))
|
485
|
-
|
486
|
-
Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{f}_#{sf_object}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json({:type => :tap, :id => tap[:id], :fields => [{:name => "Id"}, {:name => "Timestamp"}, {:name => f, :meta => "Value"}]}).to_json}))
|
487
|
-
|
488
|
-
# Core::build_node2(builder, Nodes.trash2({:name => "#{f}_#{sf_object}_es", :id => "#{f}_#{sf_object}_es", :debugPrint => true}))
|
489
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{f}_#{sf_object}_es:0", :fromNode => "#{f}_#{sf_object}_reformat:0", :metadata => "es_metadata"}))
|
490
|
-
end
|
491
|
-
end
|
492
|
-
end
|
493
|
-
end
|
494
|
-
taps_with_history.each do |tap|
|
495
|
-
puts "#{tap[:id]}_LAST_RUN"
|
496
|
-
builder.Phase(:number => phase += 1) do
|
497
|
-
generate_func = <<HEREDOC
|
498
|
-
function integer generate() {
|
499
|
-
date time_end = jodaStr2date("${#{tap[:id]}_END}",["yyyy-MM-dd'T'HH:mm:ss.SSSZZ"], 'en_US', 'UTC', 'UTC');
|
500
|
-
$out.0.key = "#{tap[:id]}_LAST_RUN";
|
501
|
-
$out.0.value = jodaDate2str(time_end,"yyyy-MM-dd'T'HH:mm:ss.SSSZZ", 'en_US', 'UTC');
|
502
|
-
return OK;
|
503
|
-
}
|
504
|
-
HEREDOC
|
505
|
-
|
506
|
-
Core::build_node2(builder, Nodes.data_generator2({:guiName => tap[:id], :name => "generator_#{phase}", :id => "generator_#{phase}", :generate => generate_func}))
|
507
|
-
Core::build_node2(builder, Nodes.lookup_reader_writer2({:guiName => tap[:id], :lookupTable => "gdLookup0", :id => "gd_lookup_reader_#{phase}" }))
|
508
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "gd_lookup_reader_#{phase}:0", :fromNode => "generator_#{phase}:0", :metadata => "lookup_metadata"}))
|
509
|
-
|
510
|
-
end
|
511
|
-
end
|
512
|
-
end
|
513
|
-
end
|
514
|
-
end
|
515
|
-
|
516
|
-
def self.generate_downloaders(home, project, params)
|
517
|
-
home = Pathname(home)
|
518
|
-
|
519
|
-
incremental_taps = Taps.get_incremental(project[:taps])
|
520
|
-
|
521
|
-
sf_taps = Taps.get_salesforce(incremental_taps)
|
522
|
-
file_taps = Taps.get_file(incremental_taps)
|
523
|
-
|
524
|
-
create_incremental_downloader_run_graph(home + "main.grf", incremental_taps)
|
525
|
-
# create_incremental_sf_downloading_graph(home + "incremental.grf", sf_taps, params)
|
526
|
-
create_incremental_sf_history_init_graph(home + "incremental.grf", sf_taps, params)
|
527
|
-
|
528
|
-
file_taps.each do |tap|
|
529
|
-
id = tap[:id]
|
530
|
-
Helpers::loop_over_file(home + "#{tap[:id]}_loop.grf", {
|
531
|
-
:token => id,
|
532
|
-
:file_to_loop => "data/#{id}_files_to_read.csv",
|
533
|
-
:graph_to_run => "graphs/#{id}_download.grf"
|
534
|
-
})
|
535
|
-
create_incremental_file_downloading_graph(home + "#{tap[:id]}_download.grf", [tap], params)
|
536
|
-
|
537
|
-
end
|
538
|
-
end
|
539
|
-
|
540
|
-
|
541
|
-
def self.generate_history_downloaders(home, project, params)
|
542
|
-
home = Pathname(home)
|
543
|
-
|
544
|
-
incremental_taps = Taps.get_incremental(project[:taps])
|
545
|
-
|
546
|
-
sf_taps = Taps.get_salesforce(incremental_taps)
|
547
|
-
file_taps = Taps.get_file(incremental_taps)
|
548
|
-
|
549
|
-
create_incremental_downloader_run_graph(home + "main.grf", incremental_taps)
|
550
|
-
create_incremental_sf_history_init_graph(home + "incremental.grf", sf_taps, params)
|
551
|
-
end
|
552
|
-
|
553
|
-
def self.create_incremental_file_downloading_graph(file, taps, options={})
|
554
|
-
metadata = options[:metadata]
|
555
|
-
store = options[:store] || "${GDC_EVENTSTORE}"
|
556
|
-
s3_backup = options[:s3_backup]
|
557
|
-
File.open(file, "w") do |file|
|
558
|
-
builder = Builder::XmlMarkup.new(:target=>file, :indent=>2)
|
559
|
-
builder.instruct! :xml, :version=>"1.0", :encoding=>"UTF-8"
|
560
|
-
builder.Graph({:name => "Goodsales incremental Downloader"}) do
|
561
|
-
builder.Global do
|
562
|
-
Helpers::property_file(builder, {:id => "workspace_params", :fileURL => "workspace.prm"})
|
563
|
-
Helpers::create_lookup_meta(builder)
|
564
|
-
taps.each do |tap|
|
565
|
-
module_name = tap[:object]
|
566
|
-
file = tap[:id] || module_name
|
567
|
-
|
568
|
-
Helpers::property_file(builder, {:id => "params_params", :fileURL => "#{file}_item.prm"})
|
569
|
-
|
570
|
-
builder.Metadata({:id => "#{file}_s3_metadata"}) do |builder|
|
571
|
-
Helpers::csv_metadata(builder, GoodData::Bam::Metadata.add_field(Metadata.get_target_metadata(Tap.prepare_for_s3_backup(tap)), {:name => "Timestamp"}))
|
572
|
-
end
|
573
|
-
|
574
|
-
tap = Tap.prepare_for_sf_downloader(tap)
|
575
|
-
builder.Metadata({:id => "#{file}_source_metadata"}) do |builder|
|
576
|
-
Helpers::csv_metadata(builder, Metadata.get_source_metadata(tap))
|
577
|
-
end
|
578
|
-
|
579
|
-
builder.Metadata({:id => "#{file}_es_metadata"}) do |builder|
|
580
|
-
Helpers::csv_metadata(builder, GoodData::Bam::Metadata.add_timestamp_as_date(Metadata.get_target_metadata(tap)))
|
581
|
-
end
|
582
|
-
Core::build_node2(builder, Nodes.lookup2({:name => "gdLookup0", :id => "gdLookup0", :type => Nodes::GD_LOOKUP, :metadata => "lookup_metadata"}))
|
583
|
-
end
|
584
|
-
end
|
585
|
-
|
586
|
-
phase = 1
|
587
|
-
|
588
|
-
taps.each do |tap|
|
589
|
-
module_name = tap[:object]
|
590
|
-
file = tap[:id]
|
591
|
-
dataset = file || module_name
|
592
|
-
source_file = tap[:source]
|
593
|
-
|
594
|
-
|
595
|
-
has_timestamp = GoodData::Bam::Tap.has_output_field?(tap, "Timestamp")
|
596
|
-
timestamp_field = GoodData::Bam::Tap.find_output_field(tap, "Timestamp")
|
597
|
-
id_field = GoodData::Bam::Tap.find_output_field(tap, "Id")
|
598
|
-
|
599
|
-
tap = Tap.prepare_for_sf_downloader(tap)
|
600
|
-
|
601
|
-
builder.Phase(:number => phase += 1) do
|
602
|
-
fields = tap[:fields]
|
603
|
-
mapping = "{\"xmlFieldsMapping\":{\"xmlFields\":["
|
604
|
-
add = fields.map do |f|
|
605
|
-
"{\"xmlFieldMapping\":{\"name\":\"#{f[:name]}\",\"label\":\"#{f[:label]}\",\"xmlPath\":\"#{f[:name]}\",\"metadataField\":\"#{f[:name]}\"}}"
|
606
|
-
end
|
607
|
-
stuff = mapping + add.join(",") + "]}}"
|
608
|
-
|
609
|
-
mandatory_fields = fields.reject {|f| f[:is_mandatory] == false }.map {|f| f[:name] + ";"}.join
|
610
|
-
|
611
|
-
Core::build_node2(builder, Nodes.reader2({:name => "#{file} File Reader", :id => "#{file}_reader", :fileURL => "${FILE}"}))
|
612
|
-
es_transformation_source = if has_timestamp
|
613
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = str2date($in.0.#{timestamp_field[:name]},\"joda:yyyy-MM-dd'T'HH:mm:ss.SSSZZ\");;\nreturn OK;\n}"
|
614
|
-
else
|
615
|
-
"function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Id = $in.0.#{id_field[:name]};\n$out.0.Timestamp = long2date(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"
|
616
|
-
end
|
617
|
-
|
618
|
-
# build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_reformat", :transformation => transformation_source}))
|
619
|
-
|
620
|
-
Core::build_node2(builder, Nodes.copy2({:name => "#{file} copy", :id => "#{file}_copy"}))
|
621
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_copy:0", :fromNode => "#{file}_reader:0", :metadata => "#{file}_source_metadata"}))
|
622
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "disabled", :name => "#{file} CSV Writer", :id => "#{file}_csv", :fileURL => "data/#{dataset.downcase}.csv", :outputFieldNames => "true"}))
|
623
|
-
|
624
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_es_reformat", :transformation => es_transformation_source}))
|
625
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_reformat:0", :fromNode => "#{file}_copy:1", :metadata => "#{file}_source_metadata"}))
|
626
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_csv:0", :fromNode => "#{file}_copy:0", :metadata => "#{file}_source_metadata"}))
|
627
|
-
|
628
|
-
if s3_backup
|
629
|
-
if has_timestamp
|
630
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
631
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
632
|
-
else
|
633
|
-
Core::build_node2(builder, Nodes.reformat2({:name => "#{file} Reformat", :id => "#{file}_s3_reformat", :transformation => "function integer transform() {\n$out.0.* = $in.0.*;\n$out.0.Timestamp = toString(${GRAPH_STARTED_TIMESTAMP});\nreturn OK;\n}"}))
|
634
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3_reformat:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
635
|
-
|
636
|
-
Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
637
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_s3_reformat:0", :metadata => "#{file}_s3_metadata"}))
|
638
|
-
end
|
639
|
-
# Core::build_node2(builder, Nodes.writer2({:enabled => "enabled", :name => "#{file} s3 Writer", :id => "#{file}_s3", :fileURL => "https://${S3_ACCESS_KEY_ID}:\`replace(\"${S3_SECRET_ACCESS_KEY}\",\"/\",\"%2F\")\`@${S3_BUCKETNAME}.s3.amazonaws.com/${GDC_PROJECT_ID}/#{file}/#{file}_\`date2long(today())\`", :outputFieldNames => true}))
|
640
|
-
# Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_s3:0", :fromNode => "#{file}_copy:2", :metadata => "#{file}_source_metadata"}))
|
641
|
-
end
|
642
|
-
|
643
|
-
|
644
|
-
Core::build_node2(builder, Nodes.sort2({:sortKey => "Timestamp(a)",:name => "#{file} es Sort", :id => "#{file}_es_sort"}))
|
645
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es_sort:0", :fromNode => "#{file}_es_reformat:0", :metadata => "#{file}_es_metadata"}))
|
646
|
-
Core::build_node2(builder, Nodes.es_writer2({:name => "#{file} es Writer", :id => "#{file}_es", :store => store, :entityFieldsMapping => Helpers::create_es_write_json(Tap.add_timestamp_field(tap)).to_json}))
|
647
|
-
Core::build_node2(builder, Nodes.edge2({:toNode => "#{file}_es:0", :fromNode => "#{file}_es_sort:0", :metadata => "#{file}_es_metadata"}))
|
648
|
-
end
|
649
|
-
|
650
|
-
builder.Phase(:number => phase += 1) do
|
651
|
-
Core::build_node2(builder, Nodes.file_delete2({:guiName => "#{file}_file_delete", :name => "#{file}_file_delete", :id => "#{file}_file_delete", :baseURL => "${FILE}"}))
|
652
|
-
end
|
653
|
-
|
654
|
-
end
|
655
|
-
|
656
|
-
end
|
657
|
-
end
|
658
|
-
end
|
659
|
-
|
660
|
-
end
|
661
|
-
end
|
662
|
-
end
|
663
|
-
end
|