Skip to content

Commit df2a6f2

Browse files
committed
Improve handling of conflict/missing plugins
1 parent cc3209b commit df2a6f2

File tree

5 files changed

+52
-35
lines changed

5 files changed

+52
-35
lines changed

lib/chronicle/etl/cli/jobs.rb

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,19 @@ class Jobs < SubcommandBase
4545
LONG_DESC
4646
# Run an ETL job
4747
def start
48-
run_job(options)
49-
rescue Chronicle::ETL::JobDefinitionError => e
50-
missing_plugins = e.job_definition.errors
51-
.select { |error| error.is_a?(Chronicle::ETL::PluginLoadError) }
52-
.map(&:name)
53-
.uniq
48+
job_definition = build_job_definition(options)
49+
50+
if job_definition.plugins_missing?
51+
missing_plugins = job_definition.errors[:plugins]
52+
.select { |error| error.is_a?(Chronicle::ETL::PluginLoadError) }
53+
.map(&:name)
54+
.uniq
55+
install_missing_plugins(missing_plugins)
56+
end
5457

55-
install_missing_plugins(missing_plugins)
56-
run_job(options)
58+
run_job(job_definition)
59+
rescue Chronicle::ETL::JobDefinitionError => e
60+
cli_fail(message: "Error running job.\n#{job_definition.errors}", exception: e)
5761
end
5862

5963
desc "create", "Create a job"
@@ -104,8 +108,7 @@ def list
104108

105109
private
106110

107-
def run_job(options)
108-
job_definition = build_job_definition(options)
111+
def run_job(job_definition)
109112
job = Chronicle::ETL::Job.new(job_definition)
110113
runner = Chronicle::ETL::Runner.new(job)
111114
runner.run!
@@ -118,18 +121,10 @@ def install_missing_plugins(missing_plugins)
118121
message += "Do you want to install "
119122
message += missing_plugins.map { |name| "chronicle-#{name}".bold}.join(", ")
120123
message += " and start the job?"
121-
install = prompt.yes?(message)
122-
return unless install
124+
will_install = prompt.yes?(message)
125+
cli_fail(message: "Must install #{missing_plugins.join(", ")} plugin to run job") unless will_install
123126

124-
spinner = TTY::Spinner.new("[:spinner] Installing plugins...", format: :dots_2)
125-
spinner.auto_spin
126-
missing_plugins.each do |plugin|
127-
Chronicle::ETL::Registry::PluginRegistry.install(plugin)
128-
end
129-
spinner.success("(#{'successful'.green})")
130-
rescue Chronicle::ETL::PluginNotAvailableError => e
131-
spinner.error("Error".red)
132-
Chronicle::ETL::Logger.fatal("Plugin '#{e.name}' could not be installed".red)
127+
Chronicle::ETL::CLI::Plugins.new.install(*missing_plugins)
133128
end
134129

135130
# Create job definition by reading config file and then overwriting with flag options

lib/chronicle/etl/cli/plugins.rb

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,19 @@ class Plugins < SubcommandBase
1313
namespace :plugins
1414

1515
desc "install", "Install a plugin"
16-
def install(name)
17-
spinner = TTY::Spinner.new("[:spinner] Installing plugin #{name}...", format: :dots_2)
16+
def install(*plugins)
17+
cli_fail(message: "Please specify a plugin to install") unless plugins.any?
18+
19+
spinner = TTY::Spinner.new("[:spinner] Installing #{plugins.join(", ")}...", format: :dots_2)
1820
spinner.auto_spin
19-
Chronicle::ETL::Registry::PluginRegistry.install(name)
21+
plugins.each do |plugin|
22+
spinner.update(title: "Installing #{plugin}")
23+
Chronicle::ETL::Registry::PluginRegistry.install(plugin)
24+
rescue Chronicle::ETL::PluginError => e
25+
spinner.error("Error".red)
26+
cli_fail(message: "Plugin '#{plugin}' could not be installed", exception: e)
27+
end
2028
spinner.success("(#{'successful'.green})")
21-
rescue Chronicle::ETL::PluginError => e
22-
spinner.error("Error".red)
23-
cli_fail(message: "Plugin '#{name}' could not be installed", exception: e)
2429
end
2530

2631
desc "uninstall", "Unintall a plugin"

lib/chronicle/etl/exceptions.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ def initialize(name)
2323
end
2424
end
2525

26+
class PluginConflictError < PluginError; end
2627
class PluginNotAvailableError < PluginError; end
2728
class PluginLoadError < PluginError; end
2829

lib/chronicle/etl/job_definition.rb

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,32 @@ def initialize()
2626
@definition = SKELETON_DEFINITION
2727
end
2828

29+
def valid?
30+
validate
31+
@errors.empty?
32+
end
33+
2934
def validate
30-
@errors = []
35+
@errors = {}
3136

3237
Chronicle::ETL::Registry::PHASES.each do |phase|
3338
__send__("#{phase}_klass".to_sym)
3439
rescue Chronicle::ETL::PluginError => e
35-
@errors << e
40+
@errors[:plugins] ||= []
41+
@errors[:plugins] << e
3642
end
43+
end
3744

38-
@errors.empty?
45+
def plugins_missing?
46+
validate
47+
48+
@errors[:plugins] || []
49+
.filter { |e| e.instance_of?(Chronicle::ETL::PluginLoadError) }
50+
.any?
3951
end
4052

4153
def validate!
42-
raise(Chronicle::ETL::JobDefinitionError.new(self), "Job definition is invalid") unless validate
54+
raise(Chronicle::ETL::JobDefinitionError.new(self), "Job definition is invalid") unless valid?
4355

4456
true
4557
end
@@ -48,7 +60,6 @@ def validate!
4860
def add_config(config = {})
4961
@definition = @definition.deep_merge(config)
5062
load_credentials
51-
validate
5263
end
5364

5465
# Is this job continuing from a previous run?

lib/chronicle/etl/registry/plugin_registry.rb

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ def self.activate(name)
3636
# By default, activates the latest available version of a gem
3737
# so don't have to run Kernel#gem separately
3838
require "chronicle/#{name}"
39-
rescue LoadError
40-
raise Chronicle::ETL::PluginLoadError.new(name), "Plugin #{name} couldn't be loaded" if exists?(name)
39+
rescue Gem::ConflictError => e
40+
# TODO: figure out if there's more we can do here
41+
raise Chronicle::ETL::PluginConflictError.new(name), "Plugin '#{name}' couldn't be loaded. #{e.message}"
42+
rescue LoadError => e
43+
raise Chronicle::ETL::PluginLoadError.new(name), "Plugin '#{name}' couldn't be loaded" if exists?(name)
4144

4245
raise Chronicle::ETL::PluginNotAvailableError.new(name), "Plugin #{name} doesn't exist"
4346
end
@@ -49,9 +52,11 @@ def self.install(name)
4952

5053
Gem::DefaultUserInteraction.ui = Gem::SilentUI.new
5154
Gem.install(gem_name)
55+
56+
activate(name)
5257
rescue Gem::UnsatisfiableDependencyError
5358
# TODO: we need to catch a lot more than this here
54-
raise Chronicle::ETL::PluginNotAvailableError.new(name), "Plugin #{name} doesn't exist"
59+
raise Chronicle::ETL::PluginNotAvailableError.new(name), "Plugin #{name} could not be installed."
5560
end
5661

5762
# Uninstall a plugin

0 commit comments

Comments
 (0)