1
1
require 'pp'
2
+ require 'tty-prompt'
2
3
3
4
module Chronicle
4
5
module ETL
5
6
module CLI
6
7
# CLI commands for working with ETL jobs
7
8
class Jobs < SubcommandBase
8
9
default_task "start"
9
- namespace :jobs
10
+ namespace :jobs
10
11
11
12
class_option :name , aliases : '-j' , desc : 'Job configuration name'
12
13
@@ -26,15 +27,9 @@ class Jobs < SubcommandBase
26
27
class_option :output , aliases : '-o' , desc : 'Output filename' , type : 'string'
27
28
class_option :fields , desc : 'Output only these fields' , type : 'array' , banner : 'field1 field2 ...'
28
29
29
- class_option :log_level , desc : 'Log level (debug, info, warn, error, fatal)' , default : 'info'
30
- class_option :verbose , aliases : '-v' , desc : 'Set log level to verbose' , type : :boolean
31
- class_option :silent , desc : 'Silence all output' , type : :boolean
32
-
33
30
# Thor doesn't like `run` as a command name
34
31
map run : :start
35
32
desc "run" , "Start a job"
36
- option :log_level , desc : 'Log level (debug, info, warn, error, fatal)' , default : 'info'
37
- option :verbose , aliases : '-v' , desc : 'Set log level to verbose' , type : :boolean
38
33
option :dry_run , desc : 'Only run the extraction and transform steps, not the loading' , type : :boolean
39
34
long_desc <<-LONG_DESC
40
35
This will run an ETL job. Each job needs three parts:
@@ -49,11 +44,14 @@ class Jobs < SubcommandBase
49
44
LONG_DESC
50
45
# Run an ETL job
51
46
def start
52
- setup_log_level
53
- job_definition = build_job_definition ( options )
54
- job = Chronicle ::ETL ::Job . new ( job_definition )
55
- runner = Chronicle ::ETL ::Runner . new ( job )
56
- runner . run!
47
+ run_job ( options )
48
+ rescue Chronicle ::ETL ::JobDefinitionError => e
49
+ missing_plugins = e . job_definition . errors
50
+ . select { |error | error . is_a? ( Chronicle ::ETL ::PluginLoadError ) }
51
+ . map ( &:name )
52
+ . uniq
53
+ return unless install_missing_plugins ( missing_plugins )
54
+ run_job ( options )
57
55
end
58
56
59
57
desc "create" , "Create a job"
@@ -87,21 +85,39 @@ def list
87
85
88
86
headers = [ 'name' , 'extractor' , 'transformer' , 'loader' ] . map { |h | h . upcase . bold }
89
87
88
+ puts "Available jobs:"
90
89
table = TTY ::Table . new ( headers , job_details )
91
90
puts table . render ( indent : 0 , padding : [ 0 , 2 ] )
92
91
end
93
92
94
93
private
95
94
96
- def setup_log_level
97
- if options [ :silent ]
98
- Chronicle ::ETL ::Logger . log_level = Chronicle ::ETL ::Logger ::SILENT
99
- elsif options [ :verbose ]
100
- Chronicle ::ETL ::Logger . log_level = Chronicle ::ETL ::Logger ::DEBUG
101
- elsif options [ :log_level ]
102
- level = Chronicle ::ETL ::Logger . const_get ( options [ :log_level ] . upcase )
103
- Chronicle ::ETL ::Logger . log_level = level
95
+ def run_job ( options )
96
+ job_definition = build_job_definition ( options )
97
+ job = Chronicle ::ETL ::Job . new ( job_definition )
98
+ runner = Chronicle ::ETL ::Runner . new ( job )
99
+ runner . run!
100
+ end
101
+
102
+ def install_missing_plugins ( missing_plugins )
103
+ prompt = TTY ::Prompt . new
104
+ message = "Plugin#{ 's' if missing_plugins . count > 1 } specified by job not installed.\n "
105
+ message += "Do you want to install "
106
+ message += missing_plugins . map { |name | "chronicle-#{ name } " . bold } . join ( ", " )
107
+ message += " and start the job?"
108
+ install = prompt . yes? ( message )
109
+ return unless install
110
+
111
+ spinner = TTY ::Spinner . new ( "[:spinner] Installing plugins..." , format : :dots_2 )
112
+ spinner . auto_spin
113
+ missing_plugins . each do |plugin |
114
+ Chronicle ::ETL ::Registry ::PluginRegistry . install ( plugin )
104
115
end
116
+ spinner . success ( "(#{ 'successful' . green } )" )
117
+ true
118
+ rescue Chronicle ::ETL ::PluginNotAvailableError => e
119
+ spinner . error ( "Plugin #{ e . name } could not be installed" )
120
+ false
105
121
end
106
122
107
123
# Create job definition by reading config file and then overwriting with flag options
0 commit comments