chronicle-etl 0.2.1 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/chronicle/etl.rb +1 -0
- data/lib/chronicle/etl/catalog.rb +41 -1
- data/lib/chronicle/etl/cli/jobs.rb +0 -1
- data/lib/chronicle/etl/exceptions.rb +17 -0
- data/lib/chronicle/etl/runner.rb +25 -38
- data/lib/chronicle/etl/transformers/null_transformer.rb +2 -2
- data/lib/chronicle/etl/transformers/transformer.rb +3 -2
- data/lib/chronicle/etl/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e1c08bc4f71c807525090abbf1701be19ab72cce08a99cc3bbec9b0db7150a02
|
4
|
+
data.tar.gz: 172a5d7e7ba7a9424ef7b5ab4da2b8c44defdb4e0a34c833248ff1b63f40407e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0f671c00928b15f9c0f6fa159ac106ff9c4f65a8bd16048e5d0cab82d680945317f7680e7796e98c665bb5cc757e0657f1a36d773d89e3e1587d9eebc12abdd8
|
7
|
+
data.tar.gz: 449d1368e0054f39006c7903218300b9b97ca839d6eff43b6b7bd659e5146d443a31c53325c4769ae7a56db9d42417020ccde17362ae024c01aca2ed63029044
|
data/Gemfile.lock
CHANGED
data/lib/chronicle/etl.rb
CHANGED
@@ -4,6 +4,11 @@ module Chronicle
|
|
4
4
|
# Loader connector classes are available to chronicle-etl
|
5
5
|
module Catalog
|
6
6
|
PLUGINS = ['email', 'bash']
|
7
|
+
BUILTIN = {
|
8
|
+
extractor: ['stdin', 'json', 'csv', 'file'],
|
9
|
+
transformer: ['null'],
|
10
|
+
loader: ['stdout', 'csv', 'table', 'rest']
|
11
|
+
}.freeze
|
7
12
|
|
8
13
|
# Return which ETL connectors are available, both built in and externally-defined
|
9
14
|
def self.available_classes
|
@@ -15,7 +20,7 @@ module Chronicle
|
|
15
20
|
PLUGINS.each do |plugin|
|
16
21
|
require "chronicle/#{plugin}"
|
17
22
|
rescue LoadError
|
18
|
-
# this will happen if the gem isn't available globally
|
23
|
+
# this will happen if the gem isn't available globally
|
19
24
|
end
|
20
25
|
|
21
26
|
parent_klasses = [
|
@@ -38,6 +43,18 @@ module Chronicle
|
|
38
43
|
end
|
39
44
|
end
|
40
45
|
|
46
|
+
# For a given connector identifier, return the class (either builtin, or from a
|
47
|
+
# external chronicle gem)
|
48
|
+
def self.identifier_to_klass(identifier:, phase:)
|
49
|
+
if BUILTIN[phase].include? identifier
|
50
|
+
load_builtin_klass(name: identifier, phase: phase)
|
51
|
+
else
|
52
|
+
provider, name = identifier.split(':')
|
53
|
+
name ||= ''
|
54
|
+
load_provider_klass(provider: provider, name: name, phase: phase)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
41
58
|
# Returns whether a class is an Extractor, Transformer, or Loader
|
42
59
|
def phase
|
43
60
|
ancestors = self.ancestors
|
@@ -57,6 +74,29 @@ module Chronicle
|
|
57
74
|
def built_in?
|
58
75
|
to_s.include? 'Chronicle::ETL'
|
59
76
|
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def self.load_builtin_klass(name:, phase:)
|
81
|
+
klass_str = "Chronicle::ETL::#{name.capitalize}#{phase.capitalize}"
|
82
|
+
begin
|
83
|
+
Object.const_get(klass_str)
|
84
|
+
rescue NameError => e
|
85
|
+
raise ConnectorNotAvailableError.new("Connector not found", name: name)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.load_provider_klass(name: '', phase:, provider:)
|
90
|
+
begin
|
91
|
+
require "chronicle/#{provider}"
|
92
|
+
klass_str = "Chronicle::#{provider.capitalize}::#{name.capitalize}#{phase.capitalize}"
|
93
|
+
Object.const_get(klass_str)
|
94
|
+
rescue LoadError => e
|
95
|
+
raise ProviderNotAvailableError.new("Provider '#{provider.capitalize}' could not be loaded", provider: provider)
|
96
|
+
rescue NameError => e
|
97
|
+
raise ProviderConnectorNotAvailableError.new("Connector '#{name}' in '#{provider}' could not be found", provider: provider, name: name)
|
98
|
+
end
|
99
|
+
end
|
60
100
|
end
|
61
101
|
end
|
62
102
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Chronicle
|
2
|
+
module ETL
|
3
|
+
class Error < StandardError; end;
|
4
|
+
|
5
|
+
class ConnectorNotAvailableError < Error
|
6
|
+
def initialize(message, provider: nil, name: nil)
|
7
|
+
super(message)
|
8
|
+
@provider = provider
|
9
|
+
@name = name
|
10
|
+
end
|
11
|
+
attr_reader :name, :provider
|
12
|
+
end
|
13
|
+
|
14
|
+
class ProviderNotAvailableError < ConnectorNotAvailableError; end
|
15
|
+
class ProviderConnectorNotAvailableError < ConnectorNotAvailableError; end
|
16
|
+
end
|
17
|
+
end
|
data/lib/chronicle/etl/runner.rb
CHANGED
@@ -1,59 +1,46 @@
|
|
1
|
-
|
2
|
-
BUILTIN = {
|
3
|
-
extractor: ['stdin', 'json', 'csv', 'file'],
|
4
|
-
transformer: ['null'],
|
5
|
-
loader: ['stdout', 'csv', 'table']
|
6
|
-
}.freeze
|
1
|
+
require 'colorize'
|
7
2
|
|
8
|
-
|
3
|
+
class Chronicle::ETL::Runner
|
4
|
+
def initialize(options = {})
|
9
5
|
@options = options
|
10
|
-
|
11
|
-
instantiate_etl_classes
|
12
6
|
end
|
13
7
|
|
14
8
|
def run!
|
15
|
-
|
9
|
+
extractor = instantiate_klass(:extractor)
|
10
|
+
loader = instantiate_klass(:loader)
|
11
|
+
|
12
|
+
total = extractor.results_count
|
16
13
|
progress_bar = Chronicle::ETL::Utils::ProgressBar.new(title: 'Running job', total: total)
|
17
|
-
count = 0
|
18
14
|
|
19
|
-
|
15
|
+
loader.start
|
20
16
|
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
extractor.extract do |data, metadata|
|
18
|
+
transformer = instantiate_klass(:transformer, data)
|
19
|
+
transformed_data = transformer.transform
|
24
20
|
|
21
|
+
loader.load(transformed_data)
|
25
22
|
progress_bar.increment
|
26
|
-
count += 1
|
27
23
|
end
|
28
24
|
|
29
25
|
progress_bar.finish
|
30
|
-
|
26
|
+
loader.finish
|
31
27
|
end
|
32
28
|
|
33
29
|
private
|
34
30
|
|
35
|
-
def
|
36
|
-
|
37
|
-
|
38
|
-
@loader = load_etl_class(:loader, @options[:loader][:name]).new(@options[:loader][:options])
|
31
|
+
def instantiate_klass(phase, *args)
|
32
|
+
klass = load_etl_class(phase, @options[phase][:name])
|
33
|
+
klass.new(@options[phase][:options], *args)
|
39
34
|
end
|
40
35
|
|
41
|
-
def load_etl_class(phase,
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
rescue LoadError => e
|
51
|
-
warn("Error loading #{phase} '#{provider}'".red)
|
52
|
-
warn(" Perhaps you haven't installed it yet: `$ gem install chronicle-#{provider}`")
|
53
|
-
exit(false)
|
54
|
-
end
|
55
|
-
klass_name = "Chronicle::#{provider.capitalize}::#{name&.capitalize}#{phase.capitalize}"
|
56
|
-
end
|
57
|
-
Object.const_get(klass_name)
|
36
|
+
def load_etl_class(phase, identifier)
|
37
|
+
Chronicle::ETL::Catalog.identifier_to_klass(phase: phase, identifier: identifier)
|
38
|
+
rescue Chronicle::ETL::ProviderNotAvailableError => e
|
39
|
+
warn(e.message.red)
|
40
|
+
warn(" Perhaps you haven't installed it yet: `$ gem install chronicle-#{e.provider}`")
|
41
|
+
exit(false)
|
42
|
+
rescue Chronicle::ETL::ConnectorNotAvailableError => e
|
43
|
+
warn(e.message.red)
|
44
|
+
exit(false)
|
58
45
|
end
|
59
46
|
end
|
@@ -8,12 +8,13 @@ module Chronicle
|
|
8
8
|
# == Paramters:
|
9
9
|
# options::
|
10
10
|
# Options for configuring this Transformer
|
11
|
-
def initialize(options = {})
|
11
|
+
def initialize(options = {}, data)
|
12
12
|
@options = options
|
13
|
+
@data = data
|
13
14
|
end
|
14
15
|
|
15
16
|
# The main entrypoint for transforming a record. Called by a Runner on each extracted record
|
16
|
-
def transform
|
17
|
+
def transform
|
17
18
|
raise NotImplementedError
|
18
19
|
end
|
19
20
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chronicle-etl
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Andrew Louis
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-08-
|
11
|
+
date: 2020-08-29 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: thor
|
@@ -183,6 +183,7 @@ files:
|
|
183
183
|
- lib/chronicle/etl/cli/main.rb
|
184
184
|
- lib/chronicle/etl/cli/subcommand_base.rb
|
185
185
|
- lib/chronicle/etl/config.rb
|
186
|
+
- lib/chronicle/etl/exceptions.rb
|
186
187
|
- lib/chronicle/etl/extractors/csv_extractor.rb
|
187
188
|
- lib/chronicle/etl/extractors/extractor.rb
|
188
189
|
- lib/chronicle/etl/extractors/file_extractor.rb
|