eco-helpers 3.0.37 → 3.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -0
  3. data/CHANGELOG.md +116 -1
  4. data/lib/eco/api/common/loaders/base.rb +2 -2
  5. data/lib/eco/api/common/loaders/case_base.rb +2 -0
  6. data/lib/eco/api/common/loaders/config/block.rb +78 -0
  7. data/lib/eco/api/common/loaders/config/workflow/mailer.rb +39 -7
  8. data/lib/eco/api/common/loaders/config.rb +3 -26
  9. data/lib/eco/api/common/loaders/error_handler.rb +2 -0
  10. data/lib/eco/api/common/loaders/parser.rb +1 -4
  11. data/lib/eco/api/common/people/entries.rb +23 -6
  12. data/lib/eco/api/common/people/entry_factory.rb +1 -1
  13. data/lib/eco/api/common/people/person_entry.rb +104 -27
  14. data/lib/eco/api/common/people/person_parser.rb +50 -16
  15. data/lib/eco/api/common/people/supervisor_helpers.rb +12 -6
  16. data/lib/eco/api/common/session/base_session.rb +75 -81
  17. data/lib/eco/api/common/session/environment.rb +49 -55
  18. data/lib/eco/api/common/session/file_manager.rb +132 -135
  19. data/lib/eco/api/common/session/helpers/prompt_user.rb +23 -30
  20. data/lib/eco/api/common/session/helpers.rb +10 -15
  21. data/lib/eco/api/common/session/logger/cache.rb +89 -96
  22. data/lib/eco/api/common/session/logger/channels.rb +24 -32
  23. data/lib/eco/api/common/session/logger/log.rb +38 -46
  24. data/lib/eco/api/common/session/logger.rb +50 -54
  25. data/lib/eco/api/common/session/mailer/aws_provider.rb +63 -71
  26. data/lib/eco/api/common/session/mailer/provider_base.rb +43 -48
  27. data/lib/eco/api/common/session/mailer/sendgrid_provider.rb +101 -109
  28. data/lib/eco/api/common/session/mailer.rb +78 -83
  29. data/lib/eco/api/common/session/s3_uploader.rb +132 -138
  30. data/lib/eco/api/common/session/sftp.rb +202 -208
  31. data/lib/eco/api/common.rb +0 -3
  32. data/lib/eco/api/custom/mailer.rb +4 -2
  33. data/lib/eco/api/error/handlers.rb +1 -1
  34. data/lib/eco/api/microcases/people/apply_changes/set_core/core_excluded.rb +8 -2
  35. data/lib/eco/api/microcases/people/manage/search.rb +1 -1
  36. data/lib/eco/api/organization/people/similarity.rb +3 -3
  37. data/lib/eco/api/session/batch/base_policy.rb +42 -27
  38. data/lib/eco/api/session/batch/launcher/mode_size.rb +6 -1
  39. data/lib/eco/api/session/batch/launcher.rb +16 -3
  40. data/lib/eco/api/session/config/api.rb +4 -3
  41. data/lib/eco/api/session/config/apis/one_off.rb +1 -1
  42. data/lib/eco/api/session/config/files.rb +13 -12
  43. data/lib/eco/api/session/config/workflow.rb +1 -373
  44. data/lib/eco/api/session/config.rb +30 -9
  45. data/lib/eco/api/usecases/base_case/model.rb +6 -6
  46. data/lib/eco/api/usecases/base_case.rb +1 -1
  47. data/lib/eco/api/usecases/cli.rb +1 -1
  48. data/lib/eco/api/usecases/default/locations/tagtree_extract_case.rb +8 -9
  49. data/lib/eco/api/usecases/default_cases/to_csv_case.rb +4 -1
  50. data/lib/eco/api/usecases/graphql/samples/location/command/dsl.rb +2 -2
  51. data/lib/eco/api/usecases/lib/base/env.rb +21 -23
  52. data/lib/eco/api/usecases/lib/files/file_pattern.rb +41 -14
  53. data/lib/eco/api/usecases/lib/files/input_file.rb +110 -0
  54. data/lib/eco/api/usecases/lib/files/sftp.rb +5 -2
  55. data/lib/eco/api/usecases/lib/files.rb +1 -0
  56. data/lib/eco/api/usecases/lib/locations/base.rb +23 -0
  57. data/lib/eco/api/usecases/lib/locations/mapping.rb +94 -0
  58. data/lib/eco/api/usecases/lib/locations.rb +7 -0
  59. data/lib/eco/api/usecases/lib/people/base.rb +20 -0
  60. data/lib/eco/api/usecases/lib/people.rb +6 -0
  61. data/lib/eco/api/usecases/lib.rb +2 -0
  62. data/lib/eco/api/usecases/ooze_cases.rb +1 -1
  63. data/lib/eco/api/usecases/ooze_samples/register_export_case.rb +1 -0
  64. data/lib/eco/api/usecases/ooze_samples/register_update_case.rb +1 -0
  65. data/lib/eco/api/usecases/samples/drivers/sftp_sample.rb +2 -0
  66. data/lib/eco/api/usecases/samples/drivers/url_pull_sample.rb +8 -2
  67. data/lib/eco/api/usecases/service/sftp/with_target_config.rb +0 -33
  68. data/lib/eco/api/usecases/service/sftp.rb +7 -1
  69. data/lib/eco/api/usecases/use_case.rb +3 -2
  70. data/lib/eco/api/usecases/workflow.rb +5 -0
  71. data/lib/eco/api/usecases.rb +12 -5
  72. data/lib/eco/cli/scripting/args_helpers.rb +1 -9
  73. data/lib/eco/cli_default/options.rb +98 -68
  74. data/lib/eco/cli_default/workflow/end.rb +22 -0
  75. data/lib/eco/cli_default/workflow/launch_jobs.rb +14 -0
  76. data/lib/eco/cli_default/workflow/load/data.rb +27 -0
  77. data/lib/eco/cli_default/workflow/load/input.rb +28 -0
  78. data/lib/eco/cli_default/workflow/load.rb +13 -0
  79. data/lib/eco/cli_default/workflow/options.rb +10 -0
  80. data/lib/eco/cli_default/workflow/post_launch.rb +65 -0
  81. data/lib/eco/cli_default/workflow/report.rb +17 -0
  82. data/lib/eco/cli_default/workflow/rescued_exception.rb +21 -0
  83. data/lib/eco/cli_default/workflow/usecases.rb +23 -0
  84. data/lib/eco/cli_default/workflow.rb +24 -180
  85. data/lib/eco/data/count_trace.rb +51 -0
  86. data/lib/eco/data/files/content.rb +39 -0
  87. data/lib/eco/data/files/directory.rb +78 -45
  88. data/lib/eco/data/files/encoding.rb +12 -21
  89. data/lib/eco/data/files/file_pattern.rb +15 -8
  90. data/lib/eco/data/files/folder.rb +196 -0
  91. data/lib/eco/data/files/relative_path.rb +54 -0
  92. data/lib/eco/data/files/timestamp.rb +18 -0
  93. data/lib/eco/data/files.rb +46 -5
  94. data/lib/eco/data/fuzzy_match.rb +1 -1
  95. data/lib/eco/data/hashes/array_diff.rb +11 -5
  96. data/lib/eco/data/hashes/diff_result/meta.rb +12 -4
  97. data/lib/eco/data/locations/node_diff/accessors.rb +1 -1
  98. data/lib/eco/data/mapper.rb +5 -1
  99. data/lib/eco/data.rb +1 -0
  100. data/lib/eco/language/delegation/delegating_missing.rb +1 -1
  101. data/lib/eco/language/delegation/delegating_missing_const.rb +1 -1
  102. data/lib/eco/language/delegation/delegating_missing_on_class.rb +1 -1
  103. data/lib/eco/language/delegation/for_delegator/delegated_class.rb +1 -1
  104. data/lib/eco/language/klass/auto_loader.rb +129 -0
  105. data/lib/eco/language/klass/builder.rb +6 -6
  106. data/lib/eco/language/klass/const.rb +19 -0
  107. data/lib/eco/language/klass/helpers_built.rb +3 -1
  108. data/lib/eco/language/klass/hierarchy.rb +5 -1
  109. data/lib/eco/language/klass/naming.rb +5 -2
  110. data/lib/eco/language/klass/resolver.rb +21 -6
  111. data/lib/eco/language/klass/uid.rb +12 -0
  112. data/lib/eco/language/klass/when_inherited.rb +30 -6
  113. data/lib/eco/language/klass.rb +5 -2
  114. data/lib/eco/language/methods/access_modifier.rb +23 -0
  115. data/lib/eco/language/methods/instance_method_helpers.rb +6 -1
  116. data/lib/eco/language/methods.rb +1 -0
  117. data/lib/eco/language/models/hierarchy.rb +41 -0
  118. data/lib/eco/language/models/workflow.rb +385 -0
  119. data/lib/eco/language/models.rb +2 -1
  120. data/lib/eco/version.rb +1 -1
  121. metadata +31 -7
  122. data/lib/eco/api/common/class_auto_loader.rb +0 -114
  123. data/lib/eco/api/common/class_helpers.rb +0 -9
  124. data/lib/eco/api/common/class_hierarchy.rb +0 -45
  125. data/lib/eco/data/files/helpers.rb +0 -152
  126. data/lib/eco/language/models/class_helpers.rb +0 -136
@@ -1,116 +1,108 @@
1
1
  # rubocop:disable Naming/MethodParameterName
2
- module Eco
3
- module API
4
- module Common
5
- module Session
6
- class Mailer
7
- class SendgridProvider < ProviderBase
8
- def send_mail(subject:, body:, to: nil, cc: nil, bcc: nil)
9
- return false unless sendgrid
10
-
11
- data = to_data(
12
- subject: subject,
13
- body: body,
14
- to: to,
15
- cc: cc,
16
- bcc: bcc
17
- )
18
-
19
- mailer._('send').post(request_body: data)
20
- end
21
-
22
- def fetch_to(value = nil)
23
- emails = [super].flatten.compact
24
- to_email_model(emails)
25
- end
26
-
27
- # @return [Boolean] whether or not the mailer is configured for usage.
28
- def configured?
29
- fetch_secret_access_key
30
- end
31
-
32
- private
33
-
34
- def credentials
35
- @credentials ||= {
36
- id: 'SENDGRID_ACCESS_ID',
37
- key: 'SENDGRID_ACCESS_KEY'
38
- }
39
- end
40
-
41
- def to_data(subject:, body:, to: nil, cc: nil, bcc: nil)
42
- {
43
- 'personalizations' => [
44
- {
45
- 'to' => fetch_to(to).flatten,
46
- 'subject' => subject
47
- }.tap do |pers|
48
- merge_if('cc', cc, target: pers)
49
- merge_if('bcc', bcc, target: pers)
50
- end
51
- ],
52
- 'from' => fetch_from,
53
- 'content' => [
54
- {
55
- 'type' => 'text/plain',
56
- 'value' => body
57
- }
58
- ]
59
- }
60
- end
61
-
62
- def mailer
63
- @mailer ||= sendgrid&.client&.mail
64
- end
65
-
66
- def sendgrid
67
- require 'sendgrid-ruby'
68
- extend(::SendGrid) unless is_a?(SendGrid)
69
-
70
- @sendgrid ||= SendGrid::API.new(
71
- api_key: fetch_secret_access_key
72
- )
73
- rescue StandardError => err
74
- log(:error) {
75
- "Trying to send an email with wrong email configuration: #{err}"
76
- }
77
- nil
78
- end
79
-
80
- def to_email_model(value)
81
- case value
82
- when Array
83
- value.map do |val|
84
- to_email_model(val)
85
- end.compact
86
- else
87
- return if value.to_s.strip.empty?
88
-
89
- {
90
- 'email' => value
91
- }
92
- end
93
- end
94
-
95
- def merge_if(key, data, target: {})
96
- return if data.to_s.strip.empty?
97
-
98
- key_data = to_email_model(data)
99
-
100
- return if key_data.nil?
101
- return if key_data.empty?
102
-
103
- target.merge!({key.to_s => key_data})
104
- end
105
-
106
- def fetch_from(value = nil)
107
- email = [super].flatten.compact.first
108
- to_email_model(email)
109
- end
2
+ class Eco::API::Common::Session::Mailer
3
+ class SendgridProvider < ProviderBase
4
+ def send_mail(subject:, body:, to: nil, cc: nil, bcc: nil)
5
+ return false unless sendgrid
6
+
7
+ data = to_data(
8
+ subject: subject,
9
+ body: body,
10
+ to: to,
11
+ cc: cc,
12
+ bcc: bcc
13
+ )
14
+
15
+ mailer._('send').post(request_body: data)
16
+ end
17
+
18
+ def fetch_to(value = nil)
19
+ emails = [super].flatten.compact
20
+ to_email_model(emails)
21
+ end
22
+
23
+ # @return [Boolean] whether or not the mailer is configured for usage.
24
+ def configured?
25
+ fetch_secret_access_key
26
+ end
27
+
28
+ private
29
+
30
+ def credentials
31
+ @credentials ||= super.merge({
32
+ id: 'SENDGRID_ACCESS_ID',
33
+ key: 'SENDGRID_ACCESS_KEY'
34
+ })
35
+ end
36
+
37
+ def to_data(subject:, body:, to: nil, cc: nil, bcc: nil)
38
+ {
39
+ 'personalizations' => [
40
+ {
41
+ 'to' => fetch_to(to).flatten,
42
+ 'subject' => subject
43
+ }.tap do |pers|
44
+ merge_if('cc', cc, target: pers)
45
+ merge_if('bcc', bcc, target: pers)
110
46
  end
111
- end
47
+ ],
48
+ 'from' => fetch_from,
49
+ 'content' => [
50
+ {
51
+ 'type' => 'text/plain',
52
+ 'value' => body
53
+ }
54
+ ]
55
+ }
56
+ end
57
+
58
+ def mailer
59
+ @mailer ||= sendgrid&.client&.mail
60
+ end
61
+
62
+ def sendgrid
63
+ require 'sendgrid-ruby'
64
+ extend(::SendGrid) unless is_a?(SendGrid)
65
+
66
+ @sendgrid ||= SendGrid::API.new(
67
+ api_key: fetch_secret_access_key
68
+ )
69
+ rescue StandardError => err
70
+ log(:error) {
71
+ "Trying to send an email with wrong email configuration: #{err}"
72
+ }
73
+ nil
74
+ end
75
+
76
+ def to_email_model(value)
77
+ case value
78
+ when Array
79
+ value.map do |val|
80
+ to_email_model(val)
81
+ end.compact
82
+ else
83
+ return if value.to_s.strip.empty?
84
+
85
+ {
86
+ 'email' => value
87
+ }
112
88
  end
113
89
  end
90
+
91
+ def merge_if(key, data, target: {})
92
+ return if data.to_s.strip.empty?
93
+
94
+ key_data = to_email_model(data)
95
+
96
+ return if key_data.nil?
97
+ return if key_data.empty?
98
+
99
+ target.merge!({key.to_s => key_data})
100
+ end
101
+
102
+ def fetch_from(value = nil)
103
+ email = [super].flatten.compact.first
104
+ to_email_model(email)
105
+ end
114
106
  end
115
107
  end
116
108
 
@@ -1,91 +1,86 @@
1
1
  # rubocop:disable Naming/MethodParameterName
2
2
 
3
- require_relative 'mailer/provider_base'
4
- require_relative 'mailer/aws_provider'
5
- require_relative 'mailer/sendgrid_provider'
6
- module Eco
7
- module API
8
- module Common
9
- module Session
10
- class Mailer
11
- include Eco::Language::AuxiliarLogger
12
-
13
- DEFAULT_PROVIDER = :sendgrid
14
-
15
- attr_reader :provider
16
-
17
- # @param enviro [Eco::API::Common::Session::Environment]
18
- def initialize(enviro:, provider: DEFAULT_PROVIDER)
19
- msg = "Required Environment object (enviro:). Given: #{enviro.class}"
20
- raise msg if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
21
-
22
- @enviro = enviro
23
- @provider = provider || DEFAULT_PROVIDER
24
- end
25
-
26
- # Sends an email
27
- # @param to [String] destination email address
28
- # @param subject [String] subject of the email
29
- # @param body [String] `html` or plain text message
30
- def mail(subject:, body:, to: nil, cc: nil, bcc: nil)
31
- return false unless (serv = service)
32
-
33
- unless serv.configured?
34
- msg = 'Mailer: You are missing configuration parameters '
35
- msg << "for '#{provider}'. Review your .env file"
36
- log(:error) { msg }
37
- return false
38
- end
39
-
40
- serv.send_mail(
41
- subject: subject,
42
- body: body,
43
- to: to,
44
- cc: cc,
45
- bcc: bcc
46
- ).tap do |response|
47
- next unless response
48
-
49
- to_addr = serv.fetch_to(to)
50
- msg = "Sent email #{ProviderBase.to_desc(
51
- to: to_addr,
52
- cc: cc,
53
- bcc: bcc
54
- )}"
55
-
56
- puts msg
57
- log(:debug) { msg }
58
- end
59
- end
60
-
61
- private
62
-
63
- def service
64
- case provider
65
- when :aws
66
- AwsProvider.new(config, logger: logger)
67
- when :sendgrid
68
- SendgridProvider.new(config, logger: logger)
69
- else
70
- msg = "Unknown mail provider '#{provider}'"
71
- puts msg
72
- log(:debug) { msg }
73
-
74
- nil
75
- end
76
- end
77
-
78
- def logger
79
- @enviro&.logger || super
80
- end
81
-
82
- def config
83
- @enviro.config || {}
84
- end
85
- end
3
+ module Eco::API::Common::Session
4
+ class Mailer
5
+ include Eco::Language::AuxiliarLogger
6
+
7
+ DEFAULT_PROVIDER = :sendgrid
8
+
9
+ attr_reader :provider
10
+
11
+ # @param enviro [Eco::API::Common::Session::Environment]
12
+ def initialize(enviro:, provider: DEFAULT_PROVIDER)
13
+ msg = "Required Environment object (enviro:). Given: #{enviro.class}"
14
+ raise msg if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
15
+
16
+ @enviro = enviro
17
+ @provider = provider || DEFAULT_PROVIDER
18
+ end
19
+
20
+ # Sends an email
21
+ # @param to [String] destination email address
22
+ # @param subject [String] subject of the email
23
+ # @param body [String] `html` or plain text message
24
+ def mail(subject:, body:, to: nil, cc: nil, bcc: nil)
25
+ return false unless (serv = service)
26
+
27
+ unless serv.configured?
28
+ msg = 'Mailer: You are missing configuration parameters '
29
+ msg << "for '#{provider}'. Review your .env file"
30
+ log(:error) { msg }
31
+ return false
32
+ end
33
+
34
+ serv.send_mail(
35
+ subject: subject,
36
+ body: body,
37
+ to: to,
38
+ cc: cc,
39
+ bcc: bcc
40
+ ).tap do |response|
41
+ next unless response
42
+
43
+ to_addr = serv.fetch_to(to)
44
+ msg = "Sent email #{ProviderBase.to_desc(
45
+ to: to_addr,
46
+ cc: cc,
47
+ bcc: bcc
48
+ )}"
49
+
50
+ puts msg
51
+ log(:debug) { msg }
52
+ end
53
+ end
54
+
55
+ private
56
+
57
+ def service
58
+ case provider
59
+ when :aws
60
+ AwsProvider.new(config, logger: logger)
61
+ when :sendgrid
62
+ SendgridProvider.new(config, logger: logger)
63
+ else
64
+ msg = "Unknown mail provider '#{provider}'"
65
+ puts msg
66
+ log(:debug) { msg }
67
+
68
+ nil
86
69
  end
87
70
  end
71
+
72
+ def logger
73
+ @enviro&.logger || super
74
+ end
75
+
76
+ def config
77
+ @enviro.config || {}
78
+ end
88
79
  end
89
80
  end
90
81
 
82
+ require_relative 'mailer/provider_base'
83
+ require_relative 'mailer/aws_provider'
84
+ require_relative 'mailer/sendgrid_provider'
85
+
91
86
  # rubocop:enable Naming/MethodParameterName
@@ -1,143 +1,137 @@
1
- module Eco
2
- module API
3
- module Common
4
- module Session
5
- class S3Uploader
6
- include Eco::Language::AuxiliarLogger
7
-
8
- attr_reader :prefix
9
-
10
- # @param enviro [Eco::API::Common::Session::Environment]
11
- def initialize(enviro:)
12
- msg = "Required Environment object (enviro:). Given: #{enviro.class}"
13
- raise msg if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
14
-
15
- @enviro = enviro
16
- @prefix = fetch_prefix
17
- @timestamp = Time.now.iso8601
18
- end
19
-
20
- # Uploads `content` to S3 as `filename`
21
- # @param filename [String] the name of the object to be created on S3
22
- # @param content [String] that to be uploaded
23
- # @return [String] S3 path to the uploaded `filename` object
24
- def upload(filename, content)
25
- if (obj = new_s3_object(filename))
26
- log_upload(obj) do
27
- obj.put(body: content)
28
- end
29
- end
30
-
31
- full_path(obj)
32
- end
33
-
34
- # Uploads a single file
35
- # @param path [String] the target file to be uploaded
36
- # @return [String] S3 path to the uploaded `path` file
37
- def upload_file(path)
38
- return unless File.exist?(path)
39
-
40
- File.open(path, "rb") do |f|
41
- upload(File.basename(path), f)
42
- end
43
- end
44
-
45
- # @note it will skip subfolders
46
- # @param path [String] the target directory to be uploaded
47
- # @param recurse [Boolean] deepen in the folder structure? (`false`: default)
48
- # @return [Array<String>] S3 paths to all the uploaded files of `path` directory
49
- def upload_directory(path, recurse: false)
50
- path = File.expand_path(path)
51
- prefix = File.expand_path(File.join(path, ".."))
52
- wildcard = recurse ? "**/*" : "*"
53
-
54
- Dir.glob(File.join(path, wildcard)).sort.map do |file|
55
- next unless File.file?(file) # Skip directories
56
- key = file.sub(prefix, "").gsub(/\\/, "/").sub(/^\/+/, "")
57
-
58
- File.open(file, "rb") do |f|
59
- upload(key, f)
60
- end
61
- end.compact
62
- end
63
-
64
- # @param path [String] a full path to a S3 object
65
- # @return [String] `link` to the S3 object on console
66
- def link(path)
67
- return path.map { |pth| link(pth) } if path.is_a?(Enumerable)
68
- return unless path.is_a?(String)
69
-
70
- s3_path_str = "https://s3.console.aws.amazon.com/s3/object"
71
- s3_params = "region=#{fetch_region}&tab=overview"
72
- "#{s3_path_str}/#{path.sub('s3://', '')}?#{s3_params}"
73
- end
74
-
75
- private
76
-
77
- def full_path(obj)
78
- "s3://#{bucket.name}/#{obj.key}" if obj
79
- end
80
-
81
- def bucket
82
- require 'aws-sdk-s3'
83
- begin
84
- @bucket ||= Aws::S3::Resource.new(
85
- access_key_id: fetch_access_key_id,
86
- secret_access_key: fetch_secret_access_key,
87
- region: fetch_region
88
- ).bucket(fetch_bucket)
89
- rescue StandardError => err
90
- log(:error) {
91
- "Trying to upload to S3 with wrong configuration: #{err}"
92
- }
93
- end
94
- @bucket
95
- end
96
-
97
- def session_path
98
- ["scripts", @prefix, @timestamp].join("/")
99
- end
100
-
101
- def new_s3_object(filename)
102
- file_path = [session_path, filename].join("/")
103
- bucket&.object(file_path)
104
- end
105
-
106
- def log_upload(obj)
107
- yield
108
-
109
- log(:debug) { "Uploaded #{full_path(obj)}" }
110
- end
111
-
112
- def logger
113
- @enviro&.logger || super
114
- end
115
-
116
- def config
117
- @enviro.config || {}
118
- end
119
-
120
- def fetch_bucket
121
- config.s3storage.bucket_name
122
- end
123
-
124
- def fetch_prefix
125
- config.s3storage.prefix
126
- end
127
-
128
- def fetch_access_key_id
129
- config.s3storage.access_key_id || ENV['AWS_ACCESS_KEY_ID']
130
- end
131
-
132
- def fetch_secret_access_key
133
- config.s3storage.secret_access_key || ENV['AWS_SECRET_ACCESS_KEY']
134
- end
135
-
136
- def fetch_region
137
- config.s3storage.region || ENV['AWS_REGION']
138
- end
1
+ module Eco::API::Common::Session
2
+ class S3Uploader
3
+ include Eco::Language::AuxiliarLogger
4
+
5
+ attr_reader :prefix
6
+
7
+ # @param enviro [Eco::API::Common::Session::Environment]
8
+ def initialize(enviro:)
9
+ msg = "Required Environment object (enviro:). Given: #{enviro.class}"
10
+ raise msg if enviro && !enviro.is_a?(Eco::API::Common::Session::Environment)
11
+
12
+ @enviro = enviro
13
+ @prefix = fetch_prefix
14
+ @timestamp = Time.now.iso8601
15
+ end
16
+
17
+ # Uploads `content` to S3 as `filename`
18
+ # @param filename [String] the name of the object to be created on S3
19
+ # @param content [String] that to be uploaded
20
+ # @return [String] S3 path to the uploaded `filename` object
21
+ def upload(filename, content)
22
+ if (obj = new_s3_object(filename))
23
+ log_upload(obj) do
24
+ obj.put(body: content)
25
+ end
26
+ end
27
+
28
+ full_path(obj)
29
+ end
30
+
31
+ # Uploads a single file
32
+ # @param path [String] the target file to be uploaded
33
+ # @return [String] S3 path to the uploaded `path` file
34
+ def upload_file(path)
35
+ return unless File.exist?(path)
36
+
37
+ File.open(path, "rb") do |f|
38
+ upload(File.basename(path), f)
39
+ end
40
+ end
41
+
42
+ # @note it will skip subfolders
43
+ # @param path [String] the target directory to be uploaded
44
+ # @param recurse [Boolean] deepen in the folder structure? (`false`: default)
45
+ # @return [Array<String>] S3 paths to all the uploaded files of `path` directory
46
+ def upload_directory(path, recurse: false)
47
+ path = File.expand_path(path)
48
+ prefix = File.expand_path(File.join(path, ".."))
49
+ wildcard = recurse ? "**/*" : "*"
50
+
51
+ Dir.glob(File.join(path, wildcard)).sort.map do |file|
52
+ next unless File.file?(file) # Skip directories
53
+ key = file.sub(prefix, "").gsub(/\\/, "/").sub(/^\/+/, "")
54
+
55
+ File.open(file, "rb") do |f|
56
+ upload(key, f)
139
57
  end
58
+ end.compact
59
+ end
60
+
61
+ # @param path [String] a full path to a S3 object
62
+ # @return [String] `link` to the S3 object on console
63
+ def link(path)
64
+ return path.map { |pth| link(pth) } if path.is_a?(Enumerable)
65
+ return unless path.is_a?(String)
66
+
67
+ s3_path_str = "https://s3.console.aws.amazon.com/s3/object"
68
+ s3_params = "region=#{fetch_region}&tab=overview"
69
+ "#{s3_path_str}/#{path.sub('s3://', '')}?#{s3_params}"
70
+ end
71
+
72
+ private
73
+
74
+ def full_path(obj)
75
+ "s3://#{bucket.name}/#{obj.key}" if obj
76
+ end
77
+
78
+ def bucket
79
+ require 'aws-sdk-s3'
80
+ begin
81
+ @bucket ||= Aws::S3::Resource.new(
82
+ access_key_id: fetch_access_key_id,
83
+ secret_access_key: fetch_secret_access_key,
84
+ region: fetch_region
85
+ ).bucket(fetch_bucket)
86
+ rescue StandardError => err
87
+ log(:error) {
88
+ "Trying to upload to S3 with wrong configuration: #{err}"
89
+ }
140
90
  end
91
+ @bucket
92
+ end
93
+
94
+ def session_path
95
+ ["scripts", @prefix, @timestamp].join("/")
96
+ end
97
+
98
+ def new_s3_object(filename)
99
+ file_path = [session_path, filename].join("/")
100
+ bucket&.object(file_path)
101
+ end
102
+
103
+ def log_upload(obj)
104
+ yield
105
+
106
+ log(:debug) { "Uploaded #{full_path(obj)}" }
107
+ end
108
+
109
+ def logger
110
+ @enviro&.logger || super
111
+ end
112
+
113
+ def config
114
+ @enviro.config || {}
115
+ end
116
+
117
+ def fetch_bucket
118
+ config.s3storage.bucket_name
119
+ end
120
+
121
+ def fetch_prefix
122
+ config.s3storage.prefix
123
+ end
124
+
125
+ def fetch_access_key_id
126
+ config.s3storage.access_key_id || ENV['AWS_ACCESS_KEY_ID']
127
+ end
128
+
129
+ def fetch_secret_access_key
130
+ config.s3storage.secret_access_key || ENV['AWS_SECRET_ACCESS_KEY']
131
+ end
132
+
133
+ def fetch_region
134
+ config.s3storage.region || ENV['AWS_REGION']
141
135
  end
142
136
  end
143
137
  end