eco-helpers 2.0.39 → 2.0.43
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +64 -1
- data/eco-helpers.gemspec +1 -1
- data/lib/eco/api/common/people/entry_factory.rb +1 -1
- data/lib/eco/api/common/session/sftp.rb +0 -1
- data/lib/eco/api/error.rb +8 -0
- data/lib/eco/api/microcases/people_refresh.rb +9 -2
- data/lib/eco/api/organization/presets_values.json +4 -1
- data/lib/eco/api/policies/default_policies/99_user_access_policy.rb +1 -1
- data/lib/eco/api/session/batch/errors.rb +36 -37
- data/lib/eco/api/session/batch/feedback.rb +24 -0
- data/lib/eco/api/session/batch/job.rb +20 -4
- data/lib/eco/api/session/batch.rb +40 -3
- data/lib/eco/api/session/config/workflow.rb +21 -2
- data/lib/eco/api/usecases/default_cases/entries_to_csv_case.rb +18 -0
- data/lib/eco/api/usecases/default_cases.rb +1 -0
- data/lib/eco/api/usecases/ooze_samples/ooze_base_case.rb +6 -1
- data/lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb +64 -0
- data/lib/eco/api/usecases/ooze_samples.rb +1 -0
- data/lib/eco/cli/config/default/options.rb +7 -0
- data/lib/eco/cli/config/default/usecases.rb +8 -1
- data/lib/eco/cli/config/default/workflow.rb +17 -6
- data/lib/eco/csv/table.rb +3 -0
- data/lib/eco/version.rb +1 -1
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc85b6b42cc78adcdf2cba976331b5ae0202464ade71bb9f6b72793c28c4e8f0
|
4
|
+
data.tar.gz: 3ab9745bb62f78df1bdd6ec9657607d4135cce910c643fb9adedbb42b315e022
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 339e768dd7de68dd4f87743003bb1d177220a7ac47808b19cbcf837f16a75e1d7c3f65ce427e67542e0fe318be8b2b2531f5bd0e99743bd049c03c1711965aa0
|
7
|
+
data.tar.gz: 26b8d2e9a17e8ae7ad447ea3c28a9ce02d1726c0d78839175fc1a432c5c8aff63dde66a2bcec4bca94c745cdd794e5a0caf3a5e25008e159a3c29ead2fd707c9
|
data/CHANGELOG.md
CHANGED
@@ -1,9 +1,72 @@
|
|
1
1
|
# Change Log
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
|
-
## [2.0.
|
4
|
+
## [2.0.43] - 2021-11-25
|
5
5
|
|
6
6
|
### Added
|
7
|
+
- `Eco::API::Session::Batch::Job` added better **logging**
|
8
|
+
|
9
|
+
### Changed
|
10
|
+
- `Eco::API::Session::Batch` added **resilience** and **recovery** to connection errors
|
11
|
+
- `Eco::API::Policies::DefaultPolicies::UserAccess` changed logging from `warn` to `info`.
|
12
|
+
|
13
|
+
### Fixed
|
14
|
+
|
15
|
+
## [2.0.42] - 2021-10-30
|
16
|
+
|
17
|
+
### Added
|
18
|
+
- `eco/api/organization/presets_values.json` added abilities:
|
19
|
+
- `visitor_management`
|
20
|
+
- `broadcast_notifications`
|
21
|
+
- `cross_register_reporting`
|
22
|
+
- Due to dev pipeline, the `ecoportal-api` version `0.8.4` hasn't been released
|
23
|
+
- This part of the current `eco-helpers` version depends on that gem version (to be upgraded later)
|
24
|
+
- Changed the `workflow` in
|
25
|
+
- `before(:post_launch, :usecases)` => post launch cases are not prevented for **partial** updates
|
26
|
+
- rectified message
|
27
|
+
- `run(:post_launch, :usecases)` => missing **people** error will log in `debug` level
|
28
|
+
- it won't break the script anymore (just prevent a post use case to be run)
|
29
|
+
- New use case `Eco::API::UseCases::DefaultCases::EntriesToCsv`: to export input entries as `csv`
|
30
|
+
- invokable via `-entries-to-csv`
|
31
|
+
- More errors:
|
32
|
+
- `Eco::API::Error::ExternalIdTaken`
|
33
|
+
- `Eco::API::Error::InternalServerError`
|
34
|
+
- **Added** option `processed-people-to-csv file.csv` to export a `csv` with the results of processing people
|
35
|
+
- This option allows to preview the final data when launching a `dry-run` (`-simulate`)
|
36
|
+
- **Added** ooze case sample `Eco::API::UseCases::OozeSamples::TargetOozesUpdateCase`
|
37
|
+
- Allows to retrieve the target entries based on a `csv`
|
38
|
+
|
39
|
+
### Changed
|
40
|
+
- Moved methods of `#person_ref`, `#get_attr` and `#get_row` as **class methods** of `Eco::API::Session::Batch::Feedback`
|
41
|
+
- `Eco::API::Session::Errors` methods above to use them via `Feedback` class
|
42
|
+
- `Eco::API::Session::Errors::ErrorCache`: **added** new property `response`
|
43
|
+
- `#by_type` added parameter `only_entries` to specify the output type
|
44
|
+
- `#errors` capture the `response` in the generated `ErrorCache` object
|
45
|
+
|
46
|
+
### Fixed
|
47
|
+
- `Eco::API::Session::Config::Workflow#run` to validate **callback** output class
|
48
|
+
- It should be a `Eco::API::UseCases::BaseIO`
|
49
|
+
- Prevent **uncreated people** to be present in queues or people refresh (if the server side worked perfectly, this contingency shouldn't be necessary):
|
50
|
+
- `Eco::API::Session::Batch::Job#processed_queue`
|
51
|
+
- Sanity-check to exclude people that are **new** and do not have `id` when the current `Job` is **not** of type `:create` (meaning that it was supposed to be created but failed and it probably doesn't exist on server-side)
|
52
|
+
- This prevents errors when trying to update/delete a person that most probably does not exist on the server.
|
53
|
+
- `Eco::API::MicroCases#people_refresh`
|
54
|
+
- Remove from people run-time object those that are **new** that are `dirty` (with pending changes)
|
55
|
+
|
56
|
+
## [2.0.41] - 2021-10-06
|
57
|
+
|
58
|
+
### Fixed
|
59
|
+
- `Eco::API::Session::Batch::Job` `backup_update`
|
60
|
+
- Saved `requests` filename was overlapping due to only batch job type being used
|
61
|
+
- Now it uses the name of the batch job as well
|
62
|
+
|
63
|
+
## [2.0.40] - 2021-09-29
|
64
|
+
|
65
|
+
### Added
|
66
|
+
- Unique access point for `validation` via core case `Eco::API::UseCases::OozeSamples::OozeBaseCase#update_ooze`
|
67
|
+
|
68
|
+
## [2.0.39] - 2021-09-28
|
69
|
+
|
7
70
|
### Changed
|
8
71
|
- `Eco::API::UseCases::OozeSamples::OozeBaseCase`
|
9
72
|
- Moved helpers from `Eco::API::UseCases::OozeSamples::OozeUpdateCase`
|
data/eco-helpers.gemspec
CHANGED
@@ -31,7 +31,7 @@ Gem::Specification.new do |spec|
|
|
31
31
|
spec.add_development_dependency "redcarpet", ">= 3.5.1", "< 3.6"
|
32
32
|
|
33
33
|
spec.add_dependency 'ecoportal-api', '>= 0.8.3', '< 0.9'
|
34
|
-
spec.add_dependency 'ecoportal-api-v2', '>= 0.8.
|
34
|
+
spec.add_dependency 'ecoportal-api-v2', '>= 0.8.19', '< 0.9'
|
35
35
|
spec.add_dependency 'aws-sdk-s3', '>= 1.83.0', '< 2'
|
36
36
|
spec.add_dependency 'aws-sdk-ses', '>= 1.36.0', '< 2'
|
37
37
|
spec.add_dependency 'dotenv', '>= 2.7.6', '< 2.8'
|
@@ -166,7 +166,7 @@ module Eco
|
|
166
166
|
run = true
|
167
167
|
if Eco::API::Common::Session::FileManager.file_exists?(file)
|
168
168
|
prompt_user("Do you want to overwrite it? (Y/n):", explanation: "The file '#{file}' already exists.", default: "Y") do |response|
|
169
|
-
run = (response == "") ||
|
169
|
+
run = (response == "") || response.upcase.start_with?("Y")
|
170
170
|
end
|
171
171
|
end
|
172
172
|
|
data/lib/eco/api/error.rb
CHANGED
@@ -19,10 +19,18 @@ module Eco
|
|
19
19
|
@match = /.*/
|
20
20
|
end
|
21
21
|
|
22
|
+
class InternalServerError < Eco::API::Error
|
23
|
+
@str_err = "Internal Server Error"
|
24
|
+
@match = /#{@str_err}/
|
25
|
+
end
|
22
26
|
class UnknownPersonId < Eco::API::Error
|
23
27
|
@str_err = "Unknown person id"
|
24
28
|
@match = /Cannot find person with id (.*)/
|
25
29
|
end
|
30
|
+
class ExternalIdTaken < Eco::API::Error
|
31
|
+
@str_err = "external ID already taken"
|
32
|
+
@match = /#{@str_err}/
|
33
|
+
end
|
26
34
|
class EmailMissing < Eco::API::Error
|
27
35
|
@str_err = "missing email for account creation"
|
28
36
|
@match = /#{@str_err}/
|
@@ -2,15 +2,22 @@ module Eco
|
|
2
2
|
module API
|
3
3
|
class MicroCases
|
4
4
|
# Helper to obtain all the elements of `people` anew from the _People Manager_.
|
5
|
-
# @note
|
5
|
+
# @note
|
6
|
+
# 1. This helper is normally used to run consecutive usecases, where data needs refresh.
|
7
|
+
# 2. It only includes new people if they are not dirty (they do not have pending updates)
|
8
|
+
# - This contingency wouldn't be necessary if the server worked perfectly.
|
6
9
|
# @param people [Eco::API::Organization::People] the people that needs refresh.
|
7
10
|
# @param include_created [Boolean] include people created during this session? (will check `:create` batch jobs).
|
8
11
|
# @return [Eco::API::Organization::People] the `People` object with the data.
|
9
12
|
def people_refresh(people:, include_created: true)
|
13
|
+
people = people.newFrom people.select do |person|
|
14
|
+
!person.new? || !person.dirty?
|
15
|
+
end
|
10
16
|
ini = people.length
|
11
17
|
if include_created
|
12
18
|
session.job_groups.find_jobs(type: :create).map do |job|
|
13
|
-
|
19
|
+
to_add = job.people.select {|person| !person.dirty?}
|
20
|
+
people = people.merge(to_add)
|
14
21
|
end
|
15
22
|
end
|
16
23
|
|
@@ -12,5 +12,8 @@
|
|
12
12
|
"person_core_edit": [null, "edit"],
|
13
13
|
"person_details": [null, "view", "edit_public", "view_private", "edit_private"],
|
14
14
|
"person_account": [null, "view", "create", "edit"],
|
15
|
-
"person_abilities": [null, "view", "edit"]
|
15
|
+
"person_abilities": [null, "view", "edit"],
|
16
|
+
"visitor_management": [null, "view", "edit", "administrate"],
|
17
|
+
"broadcast_notifications": [null, "view", "administrate"],
|
18
|
+
"cross_register_reporting": [null, "view"]
|
16
19
|
}
|
@@ -22,7 +22,7 @@ class Eco::API::Policies::DefaultPolicies::UserAccess < Eco::API::Common::Loader
|
|
22
22
|
def warn_account_removal!
|
23
23
|
if account_removed_count > 0
|
24
24
|
msg = "(DefaultPolicy on job '#{job.name}') Removed account to #{account_removed_count} people"
|
25
|
-
session.logger.
|
25
|
+
session.logger.info(msg)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
@@ -8,7 +8,7 @@ module Eco
|
|
8
8
|
# @attr_reader status [Eco::API::Session::Batch::Status] `batch status` this `Errors` object is associated to.
|
9
9
|
attr_reader :status
|
10
10
|
|
11
|
-
ErrorCache = Struct.new(:type, :err, :entry)
|
11
|
+
ErrorCache = Struct.new(:type, :err, :entry, :response)
|
12
12
|
|
13
13
|
# @param status [Eco::API::Session::Batch::Status] `batch status` this `Errors` object is associated to.
|
14
14
|
def initialize(status:)
|
@@ -46,31 +46,52 @@ module Eco
|
|
46
46
|
|
47
47
|
# @!group Pure errors helper methods
|
48
48
|
|
49
|
+
# @return [Integer] the number of `entries` that got error.
|
50
|
+
def count
|
51
|
+
entries.length
|
52
|
+
end
|
53
|
+
|
49
54
|
# Was there any _Sever_ (reply) **error** as a result of this batch?
|
50
55
|
# @return [Boolean] `true` if any of the queried _entries_ got an unsuccessful `Ecoportal::API::Common::BatchResponse`
|
51
56
|
def any?
|
52
57
|
queue.any? {|query| !status[query].success?}
|
53
58
|
end
|
54
59
|
|
55
|
-
#
|
56
|
-
|
57
|
-
|
60
|
+
# Groups `entries` with error `type`
|
61
|
+
# @return [Hash] where each `key` is a `type` **error** and each value is an `Array` of:
|
62
|
+
# 1. `entries` that got that error, if `only_entries` is `true`
|
63
|
+
# 2. `ErrorCache` objects, if `only_entries` is `false`
|
64
|
+
def by_type(only_entries: true)
|
65
|
+
errors.group_by do |e|
|
66
|
+
e.type
|
67
|
+
end.transform_values do |arr|
|
68
|
+
if only_entries
|
69
|
+
arr.map {|e| e.entry}
|
70
|
+
else
|
71
|
+
arr
|
72
|
+
end
|
73
|
+
end
|
58
74
|
end
|
75
|
+
# @!endgroup
|
59
76
|
|
60
|
-
# For all the `entries` with errors generates
|
61
|
-
# @return [Array<
|
62
|
-
# 1.
|
63
|
-
# 2.
|
64
|
-
# 3.
|
77
|
+
# For all the `entries` with errors generates an `Array` of `ErrorCache` objects
|
78
|
+
# @return [Array<Eco::API::Session::Batch::Errors::ErrorCache>] where each `object` has
|
79
|
+
# 1. `type` -> the error type `Class`
|
80
|
+
# 2. `err` -> an instance object of that error `class` type
|
81
|
+
# 3. `entry` -> the entry that generated the error
|
82
|
+
# 4. `response` -> the original response from the server that carries the error
|
65
83
|
def errors
|
66
84
|
entries.each_with_object([]) do |entry, arr|
|
67
|
-
|
68
|
-
|
85
|
+
response = status[entry]
|
86
|
+
if body = response.body
|
87
|
+
if errs = body["errors"] || body["error"]
|
88
|
+
errs = [errs].flatten(1).compact
|
69
89
|
errs.each do |msg|
|
70
90
|
arr.push(ErrorCache.new(
|
71
91
|
klass = Eco::API::Error.get_type(msg),
|
72
92
|
klass.new(err_msg: msg, entry: entry, session: session),
|
73
|
-
entry
|
93
|
+
entry,
|
94
|
+
response
|
74
95
|
))
|
75
96
|
end
|
76
97
|
end
|
@@ -78,18 +99,6 @@ module Eco
|
|
78
99
|
end
|
79
100
|
end
|
80
101
|
|
81
|
-
# Groups `entries` with error `type`
|
82
|
-
# @return [Hash] where each `key` is a `type` **error** and each value is
|
83
|
-
# an `Array` of `entries` that got that error
|
84
|
-
def by_type
|
85
|
-
errors.group_by do |e|
|
86
|
-
e.type
|
87
|
-
end.transform_values do |arr|
|
88
|
-
arr.map {|e| e.entry}
|
89
|
-
end
|
90
|
-
end
|
91
|
-
# @!endgroup
|
92
|
-
|
93
102
|
# @!group Messaging methods
|
94
103
|
|
95
104
|
def message
|
@@ -112,8 +121,7 @@ module Eco
|
|
112
121
|
# @!endgroup
|
113
122
|
|
114
123
|
def person_ref(entry)
|
115
|
-
|
116
|
-
"#{row_str}(id: '#{get_attr(entry, :id)}') '#{get_attr(entry, :name)}' ('#{get_attr(entry, :external_id)}': '#{get_attr(entry, :email)}')"
|
124
|
+
Eco::API::Session::Batch::Feedback.person_ref(entry)
|
117
125
|
end
|
118
126
|
|
119
127
|
private
|
@@ -142,20 +150,11 @@ module Eco
|
|
142
150
|
end
|
143
151
|
|
144
152
|
def get_attr(entry, attr)
|
145
|
-
|
146
|
-
entry.public_send(attr.to_sym)
|
147
|
-
elsif entry.is_a?(Hash)
|
148
|
-
entry["#{attr}"]
|
149
|
-
end
|
153
|
+
Eco::API::Session::Batch::Feedback.get_attr(entry, attr)
|
150
154
|
end
|
151
155
|
|
152
156
|
def get_row(value)
|
153
|
-
|
154
|
-
when Eco::API::Common::People::PersonEntry
|
155
|
-
value.idx
|
156
|
-
when Ecoportal::API::V1::Person
|
157
|
-
get_row(value.entry)
|
158
|
-
end
|
157
|
+
Eco::API::Session::Batch::Feedback.get_row(value)
|
159
158
|
end
|
160
159
|
|
161
160
|
# Sorts the entries that got server error by error `type` and generates the error messages.
|
@@ -5,6 +5,30 @@ module Eco
|
|
5
5
|
# @attr_reader job [Eco::API::Session::Batch::Job] `batch job` the feedback is associated with
|
6
6
|
class Feedback
|
7
7
|
|
8
|
+
class << self
|
9
|
+
def person_ref(entry)
|
10
|
+
row_str = (row = get_row(entry)) ? "(row: #{row}) " : nil
|
11
|
+
"#{row_str}(id: '#{get_attr(entry, :id)}') '#{get_attr(entry, :name)}' ('#{get_attr(entry, :external_id)}': '#{get_attr(entry, :email)}')"
|
12
|
+
end
|
13
|
+
|
14
|
+
def get_attr(entry, attr)
|
15
|
+
if entry.respond_to?(attr.to_sym)
|
16
|
+
entry.public_send(attr.to_sym)
|
17
|
+
elsif entry.is_a?(Hash)
|
18
|
+
entry["#{attr}"]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_row(value)
|
23
|
+
case value
|
24
|
+
when Eco::API::Common::People::PersonEntry
|
25
|
+
value.idx
|
26
|
+
when Ecoportal::API::V1::Person
|
27
|
+
get_row(value.entry)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
8
32
|
attr_reader :job
|
9
33
|
|
10
34
|
# @param job [Eco::API::Session::Batch::Job] `batch job` the feedback is associated with
|
@@ -176,6 +176,7 @@ module Eco
|
|
176
176
|
if pqueue.length > 0
|
177
177
|
req_backup = as_update(pqueue, add_feedback: false)
|
178
178
|
backup_update(req_backup)
|
179
|
+
logger.debug("Job ('#{name}':#{type}): going to launch batch against #{pqueue.count} entries")
|
179
180
|
session.batch.launch(pqueue, method: type).tap do |job_status|
|
180
181
|
@status = job_status
|
181
182
|
status.root = self
|
@@ -235,9 +236,23 @@ module Eco
|
|
235
236
|
end
|
236
237
|
end
|
237
238
|
|
239
|
+
# Method to generate the base of people that will be present in the queue
|
240
|
+
# @note
|
241
|
+
# - If the entry is a new person, we are not in a creation job and the person doesn't have `id`
|
242
|
+
# it means that it failed to be created (it doesn't exist on server-side).
|
243
|
+
# The entry won't be included.
|
244
|
+
# - The contingency above wouldn't be necessary if the server worked perfectly.
|
238
245
|
def processed_queue
|
239
|
-
@queue.
|
240
|
-
|
246
|
+
pre_filtered = @queue.select do |entry|
|
247
|
+
if unexisting = entry.new? && !entry.id && type != :create
|
248
|
+
ref = Eco::API::Session::Batch::Feedback.person_ref(entry)
|
249
|
+
msg = "Job ('#{name}':#{type}): excluded unexisting entry (failed creation): #{ref}"
|
250
|
+
session.logger.warn(msg)
|
251
|
+
end
|
252
|
+
!unexisting
|
253
|
+
end
|
254
|
+
pre_filtered.each {|e| @callbacks[e].call(e) if @callbacks.key?(e) }
|
255
|
+
apply_policies(api_included(pre_filtered)).select do |e|
|
241
256
|
!as_update(e).empty?
|
242
257
|
end.select do |e|
|
243
258
|
next true unless e.is_a?(Ecoportal::API::V1::Person)
|
@@ -320,7 +335,7 @@ module Eco
|
|
320
335
|
handlers.each do |handler|
|
321
336
|
if entries = err_types[handler.name]
|
322
337
|
handler_job = subjobs_add("#{self.name} => #{handler.name}", usecase: handler)
|
323
|
-
logger.debug("Running error handler #{handler.name}")
|
338
|
+
logger.debug("Running error handler #{handler.name} (against #{entries.count} entries)")
|
324
339
|
handler.launch(people: people(entries), session: session, options: options, job: handler_job)
|
325
340
|
logger.debug("Launching job of error handler: #{handler_job.name}")
|
326
341
|
handler_job.launch(simulate: simulate)
|
@@ -343,7 +358,8 @@ module Eco
|
|
343
358
|
def backup_update(requests, simulate: false)
|
344
359
|
dry_run = simulate ? "_dry_run" : ""
|
345
360
|
dir = config.people.requests_folder
|
346
|
-
|
361
|
+
filename = name.split(" ").join("-").gsub(/[=\\\/><,"-]+/,"_")
|
362
|
+
file = File.join(dir, "#{type}_data_#{filename}#{dry_run}.json")
|
347
363
|
file_manager.save_json(requests, file, :timestamp)
|
348
364
|
end
|
349
365
|
|
@@ -92,6 +92,7 @@ module Eco
|
|
92
92
|
return people_api.get_all(params: params, silent: silent)
|
93
93
|
end
|
94
94
|
|
95
|
+
|
95
96
|
def batch_from(data, method:, params: {}, silent: false)
|
96
97
|
fatal "Invalid batch method: #{method}." if !self.class.valid_method?(method)
|
97
98
|
return nil if !data || !data.is_a?(Enumerable)
|
@@ -101,12 +102,23 @@ module Eco
|
|
101
102
|
params = {per_page: DEFAULT_BATCH_BLOCK}.merge(params)
|
102
103
|
per_page = params[:per_page] || DEFAULT_BATCH_BLOCK
|
103
104
|
|
105
|
+
launch_batch(data,
|
106
|
+
method: method,
|
107
|
+
per_page: per_page,
|
108
|
+
people_api: people_api,
|
109
|
+
silent: silent
|
110
|
+
)
|
111
|
+
end
|
112
|
+
|
113
|
+
def launch_batch(data, method:, status: nil, job_mode: true, per_page: DEFAULT_BATCH_BLOCK, people_api: api&.people, silent: false)
|
104
114
|
iteration = 1; done = 0
|
105
115
|
iterations = (data.length.to_f / per_page).ceil
|
106
116
|
|
107
|
-
Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method)
|
117
|
+
status ||= Eco::API::Session::Batch::Status.new(enviro, queue: data, method: method)
|
118
|
+
status.tap do |status|
|
108
119
|
start_time = Time.now
|
109
120
|
start_slice = Time.now; slice = []
|
121
|
+
pending_for_server_error = data.to_a[0..-1]
|
110
122
|
data.each_slice(per_page) do |slice|
|
111
123
|
msg = "starting batch '#{method}' iteration #{iteration}/#{iterations},"
|
112
124
|
msg += " with #{slice.length} entries of #{data.length} -- #{done} done"
|
@@ -115,11 +127,14 @@ module Eco
|
|
115
127
|
|
116
128
|
start_slice = Time.now
|
117
129
|
offer_retry_on(Ecoportal::API::Errors::TimeOut) do
|
118
|
-
people_api.batch do |batch|
|
130
|
+
people_api.batch(job_mode: false) do |batch|
|
119
131
|
slice.each do |person|
|
120
132
|
batch.public_send(method, person) do |response|
|
121
133
|
faltal("Request with no response") unless !!response
|
122
|
-
|
134
|
+
unless server_error?(response)
|
135
|
+
pending_for_server_error.delete(person)
|
136
|
+
status[person] = response
|
137
|
+
end
|
123
138
|
end
|
124
139
|
end
|
125
140
|
end # end batch
|
@@ -128,9 +143,31 @@ module Eco
|
|
128
143
|
iteration += 1
|
129
144
|
done += slice.length
|
130
145
|
end # next slice
|
146
|
+
|
147
|
+
# temporary working around (due to back-end problems with batch/jobs)
|
148
|
+
unless pending_for_server_error.empty?
|
149
|
+
msg = "Going to re-try #{pending_for_server_error.count} due to server errors"
|
150
|
+
logger.info(msg) unless silent
|
151
|
+
launch_batch(pending_for_server_error,
|
152
|
+
status: status,
|
153
|
+
method: method,
|
154
|
+
job_mode: false,
|
155
|
+
per_page: per_page,
|
156
|
+
people_api: people_api,
|
157
|
+
silent: silent
|
158
|
+
)
|
159
|
+
end
|
131
160
|
end
|
132
161
|
end
|
133
162
|
|
163
|
+
def server_error?(response)
|
164
|
+
res_status = response.status
|
165
|
+
server_error = !res_status || res_status.server_error?
|
166
|
+
other_error = !server_error && (!res_status.code || res_status.code < 100)
|
167
|
+
no_body = !server_error && !other_error && !response.body
|
168
|
+
server_error || other_error || no_body
|
169
|
+
end
|
170
|
+
|
134
171
|
def offer_retry_on(error_type, retries_left = 3, &block)
|
135
172
|
begin
|
136
173
|
block.call
|
@@ -185,6 +185,7 @@ module Eco
|
|
185
185
|
# - it will **not** run the `callback` for `on` defined during the configuration time
|
186
186
|
# - it will rather `yield` the target stage after all the `before` _callbacks_ have been run
|
187
187
|
# - aside of this, the rest will be the same as when the _block_ is provided (see previous note)
|
188
|
+
# @raise [ArgumentError] if the object returned by `before` and `after` callbacks is not an `Eco::API::UseCases::BaseIO`.
|
188
189
|
# @param key [Symbol, nil] cases:
|
189
190
|
# - if `key` is not provided, it targets the _current stage_
|
190
191
|
# - if `key` is provided, it targets the specific _sub-stage_
|
@@ -200,7 +201,16 @@ module Eco
|
|
200
201
|
if key
|
201
202
|
io = stage(key).run(io: io, &block)
|
202
203
|
elsif pending?
|
203
|
-
@before.each
|
204
|
+
@before.each do |c|
|
205
|
+
io = c.call(self, io).tap do |i_o|
|
206
|
+
unless i_o.is_a?(Eco::API::UseCases::BaseIO)
|
207
|
+
msg = "Workflow callaback before('#{name}') should return Eco::API::UseCases::BaseIO object."
|
208
|
+
msg += " Given #{i_o.class}"
|
209
|
+
msg += " • Callback source location: '#{c.source_location}'"
|
210
|
+
raise ArgumentError.new(msg)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
204
214
|
|
205
215
|
unless skip?
|
206
216
|
io.session.logger.debug("(Workflow: #{path}) running now")
|
@@ -218,7 +228,16 @@ module Eco
|
|
218
228
|
@pending = false
|
219
229
|
end
|
220
230
|
|
221
|
-
@after.each
|
231
|
+
@after.each do |c|
|
232
|
+
io = c.call(self, io).tap do |i_o|
|
233
|
+
unless i_o.is_a?(Eco::API::UseCases::BaseIO)
|
234
|
+
msg = "Workflow callaback after('#{name}') should return Eco::API::UseCases::BaseIO object."
|
235
|
+
msg += " Given #{i_o.class}"
|
236
|
+
msg += " • Callback source location: '#{c.source_location}'"
|
237
|
+
raise ArgumentError.new(msg)
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
222
241
|
end
|
223
242
|
rescue SystemExit
|
224
243
|
exit
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Eco::API::UseCases::DefaultCases::EntriesToCsv < Eco::API::Common::Loaders::UseCase
|
2
|
+
name "entries-to-csv"
|
3
|
+
type :import
|
4
|
+
|
5
|
+
attr_reader :session, :options
|
6
|
+
|
7
|
+
def main(entries, session, options, usecase)
|
8
|
+
@options = options
|
9
|
+
@session = session
|
10
|
+
entries.export(filename)
|
11
|
+
end
|
12
|
+
|
13
|
+
private
|
14
|
+
|
15
|
+
def filename
|
16
|
+
options.dig(:export, :file) || "entries.csv"
|
17
|
+
end
|
18
|
+
end
|
@@ -24,6 +24,7 @@ require_relative 'default_cases/email_as_id_case'
|
|
24
24
|
require_relative 'default_cases/hris_case'
|
25
25
|
require_relative 'default_cases/new_id_case'
|
26
26
|
require_relative 'default_cases/new_email_case'
|
27
|
+
require_relative 'default_cases/entries_to_csv_case'
|
27
28
|
require_relative 'default_cases/org_data_convert_case'
|
28
29
|
require_relative 'default_cases/refresh_case'
|
29
30
|
require_relative 'default_cases/reinvite_trans_case'
|
@@ -27,7 +27,7 @@ class Eco::API::UseCases::OozeSamples::OozeBaseCase < Eco::API::Common::Loaders:
|
|
27
27
|
end
|
28
28
|
|
29
29
|
protected
|
30
|
-
|
30
|
+
|
31
31
|
def add_field(name, type, section, after: nil, before: nil, side: :left)
|
32
32
|
unless section.is_a?(Ecoportal::API::V2::Page::Section)
|
33
33
|
raise "You need to specify a section for a new field. Given: #{section.class}"
|
@@ -112,6 +112,11 @@ class Eco::API::UseCases::OozeSamples::OozeBaseCase < Eco::API::Common::Loaders:
|
|
112
112
|
def update_ooze(ooze = target)
|
113
113
|
if !options[:simulate]
|
114
114
|
return unless dirty?(ooze)
|
115
|
+
|
116
|
+
ooze.validate.tap do |validation|
|
117
|
+
raise validation if validation.is_a?(String)
|
118
|
+
end
|
119
|
+
|
115
120
|
apiv2.pages.update(ooze).tap do |response|
|
116
121
|
if response.success?
|
117
122
|
ooze.consolidate!
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# Use case to update a target oozes
|
2
|
+
# @note
|
3
|
+
# - `target_ids` => Expects options[:source][:file] where at least the 1st column should be the target entry `ids`
|
4
|
+
class Eco::API::UseCases::OozeSamples::TargetOozesUpdateCase < Eco::API::UseCases::OozeSamples::RegisterUpdateCase
|
5
|
+
name "target-oozes-update-case"
|
6
|
+
type :other
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def with_each_entry
|
11
|
+
batched_target_ids do |ids|
|
12
|
+
ids.each do |id|
|
13
|
+
if pending = queue_shift(id)
|
14
|
+
if dirty?(pending)
|
15
|
+
msg = "Same entry 'id' appears more than once. "
|
16
|
+
msg << "Launching update on '#{object_reference(pending)}' to be able to queue it back"
|
17
|
+
console.warn msg
|
18
|
+
update_ooze(pending)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
if ooz = ooze(id)
|
22
|
+
yield(ooz)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
update_oozes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def batched_target_ids
|
30
|
+
raise "Missing block. It yields in slices of #{self.class.batch_size} ids" unless block_given?
|
31
|
+
target_ids_preview
|
32
|
+
pool = []
|
33
|
+
target_ids.each do |id|
|
34
|
+
pool << id
|
35
|
+
if pool.length >= self.class.batch_size
|
36
|
+
yield(pool)
|
37
|
+
pool = []
|
38
|
+
end
|
39
|
+
end
|
40
|
+
yield(pool) unless pool.empty?
|
41
|
+
end
|
42
|
+
|
43
|
+
def target_ids_preview
|
44
|
+
dups = target_ids.select {|id| target_ids.count(id) > 1}
|
45
|
+
dups_str = dups.count > 0 ? "There are #{dups.count} duplicated ids" : "No duplicates detected"
|
46
|
+
msg = "Total target entries: #{target_ids.count} (#{dups_str})"
|
47
|
+
session.prompt_user("Do you want to proceed (y/N):", explanation: msg, default: "N", timeout: 10) do |res|
|
48
|
+
unless res.upcase.start_with?("Y")
|
49
|
+
puts "..."
|
50
|
+
logger.info "Aborting script..."
|
51
|
+
exit(0)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def target_ids
|
57
|
+
@target_ids ||= input_csv.columns.first[1..-1]
|
58
|
+
end
|
59
|
+
|
60
|
+
def input_csv
|
61
|
+
@input_csv ||= Eco::CSV.read(options.dig(:source, :file))
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
@@ -14,3 +14,4 @@ require_relative 'ooze_samples/ooze_run_base_case'
|
|
14
14
|
require_relative 'ooze_samples/ooze_update_case'
|
15
15
|
require_relative 'ooze_samples/ooze_from_doc_case'
|
16
16
|
require_relative 'ooze_samples/register_update_case'
|
17
|
+
require_relative 'ooze_samples/target_oozes_update_case'
|
@@ -96,6 +96,13 @@ ASSETS.cli.config do |cnf|
|
|
96
96
|
})
|
97
97
|
end
|
98
98
|
|
99
|
+
desc = "Used to export to a csv the final people (after processing). "
|
100
|
+
desc += "It is useful analyse the data after a -dry-run (-simulate)."
|
101
|
+
options_set.add("-processed-people-to-csv", desc) do |options, session|
|
102
|
+
file = SCR.get_file("-processed-people-to-csv", required: true, should_exist: false)
|
103
|
+
options.deep_merge!(report: {people: {csv: file}})
|
104
|
+
end
|
105
|
+
|
99
106
|
desc = "Runs in dry-run (no requests sent to server)"
|
100
107
|
options_set.add(["-dry-run", "-simulate"], desc) do |options, session|
|
101
108
|
options[:dry_run] = true
|
@@ -137,6 +137,13 @@ ASSETS.cli.config do |cnf|
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
desc = "Input file dump into a CSV as is."
|
141
|
+
cases.add("-entries-to-csv", :import, desc, case_name: "entries-to-csv")
|
142
|
+
.add_option("-out") do |options|
|
143
|
+
file = SCR.get_file("-out")
|
144
|
+
options.deep_merge(export: {file: file})
|
145
|
+
end
|
146
|
+
|
140
147
|
desc = "Usage '-org-data-convert backup.json -restore-db-from'."
|
141
148
|
desc += " Transforms an input .json file to the values of the destination environment "
|
142
149
|
desc += " (names missmatch won't solve: i.e. usergroups)"
|
@@ -196,7 +203,7 @@ ASSETS.cli.config do |cnf|
|
|
196
203
|
.add_option("-append-starters", as1) do |options|
|
197
204
|
options.deep_merge!(people: {append_created: true})
|
198
205
|
end
|
199
|
-
|
206
|
+
|
200
207
|
desc = "Creates people with only details"
|
201
208
|
cases.add("-create-details-from", :sync, desc, case_name: "create-details")
|
202
209
|
.add_option("-append-starters", as1) do |options|
|
@@ -119,9 +119,7 @@ ASSETS.cli.config do |config|
|
|
119
119
|
else
|
120
120
|
wf_post.skip!
|
121
121
|
msg = "Although there are post_launch cases, they will NOT be RUN"
|
122
|
-
if
|
123
|
-
msg+= ", because it is not a partial update (-get-partial)"
|
124
|
-
elsif io.options[:dry_run]
|
122
|
+
if io.options[:dry_run]
|
125
123
|
msg+= ", because we are in dry-run (simulate)."
|
126
124
|
end
|
127
125
|
io.session.logger.info(msg)
|
@@ -134,7 +132,15 @@ ASSETS.cli.config do |config|
|
|
134
132
|
|
135
133
|
wf_post.on(:usecases) do |wf_postcases, io|
|
136
134
|
io.session.post_launch.each do |use|
|
137
|
-
|
135
|
+
begin
|
136
|
+
io = use.launch(io: io).base
|
137
|
+
rescue Eco::API::UseCases::BaseIO::MissingParameter => e
|
138
|
+
if e.required == :people
|
139
|
+
io.session.logger.debug("Skipping use case '#{use.name}' -- no base people detected for the current run")
|
140
|
+
else
|
141
|
+
raise
|
142
|
+
end
|
143
|
+
end
|
138
144
|
end
|
139
145
|
io
|
140
146
|
end
|
@@ -146,8 +152,13 @@ ASSETS.cli.config do |config|
|
|
146
152
|
end
|
147
153
|
|
148
154
|
wf.on(:report) do |wf_report, io|
|
149
|
-
|
150
|
-
|
155
|
+
if file = io.options.dig(:report, :people, :csv)
|
156
|
+
io.options.deep_merge!(export: {
|
157
|
+
options: {internal_names: true, nice_header: true, split_schemas: true},
|
158
|
+
file: {name: file, format: :csv}
|
159
|
+
})
|
160
|
+
io = io.session.process_case("to-csv", io: io, type: :export)
|
161
|
+
end
|
151
162
|
io
|
152
163
|
end
|
153
164
|
|
data/lib/eco/csv/table.rb
CHANGED
@@ -15,6 +15,7 @@ module Eco
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
# It allows to rename the header names
|
18
19
|
# @return [Eco::CSV::Table]
|
19
20
|
def transform_headers
|
20
21
|
header = self.headers
|
@@ -25,6 +26,8 @@ module Eco
|
|
25
26
|
columns_to_table(cols)
|
26
27
|
end
|
27
28
|
|
29
|
+
# When there are headers with the same name, it merges those columns
|
30
|
+
# @note it also offers a way to resolve merge conflicts
|
28
31
|
# @return [Eco::CSV::Table]
|
29
32
|
def merge_same_header_names
|
30
33
|
dups = self.duplicated_header_names
|
data/lib/eco/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: eco-helpers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.
|
4
|
+
version: 2.0.43
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Oscar Segura
|
@@ -136,7 +136,7 @@ dependencies:
|
|
136
136
|
requirements:
|
137
137
|
- - ">="
|
138
138
|
- !ruby/object:Gem::Version
|
139
|
-
version: 0.8.
|
139
|
+
version: 0.8.19
|
140
140
|
- - "<"
|
141
141
|
- !ruby/object:Gem::Version
|
142
142
|
version: '0.9'
|
@@ -146,7 +146,7 @@ dependencies:
|
|
146
146
|
requirements:
|
147
147
|
- - ">="
|
148
148
|
- !ruby/object:Gem::Version
|
149
|
-
version: 0.8.
|
149
|
+
version: 0.8.19
|
150
150
|
- - "<"
|
151
151
|
- !ruby/object:Gem::Version
|
152
152
|
version: '0.9'
|
@@ -533,6 +533,7 @@ files:
|
|
533
533
|
- lib/eco/api/usecases/default_cases/delete_sync_case.rb
|
534
534
|
- lib/eco/api/usecases/default_cases/delete_trans_case.rb
|
535
535
|
- lib/eco/api/usecases/default_cases/email_as_id_case.rb
|
536
|
+
- lib/eco/api/usecases/default_cases/entries_to_csv_case.rb
|
536
537
|
- lib/eco/api/usecases/default_cases/hris_case.rb
|
537
538
|
- lib/eco/api/usecases/default_cases/new_email_case.rb
|
538
539
|
- lib/eco/api/usecases/default_cases/new_id_case.rb
|
@@ -564,6 +565,7 @@ files:
|
|
564
565
|
- lib/eco/api/usecases/ooze_samples/ooze_run_base_case.rb
|
565
566
|
- lib/eco/api/usecases/ooze_samples/ooze_update_case.rb
|
566
567
|
- lib/eco/api/usecases/ooze_samples/register_update_case.rb
|
568
|
+
- lib/eco/api/usecases/ooze_samples/target_oozes_update_case.rb
|
567
569
|
- lib/eco/api/usecases/use_case.rb
|
568
570
|
- lib/eco/api/usecases/use_case_chain.rb
|
569
571
|
- lib/eco/api/usecases/use_case_io.rb
|