choria-colt 0.6.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4e76e667917bf1958b48d45148712fa5e0d6f2c15280bbbda0d4899b0537e9f8
4
- data.tar.gz: 17637d3bf6738bef6c28a282aabb1c4ac7680e4b2e8a6f0fe873a27b59079cc1
3
+ metadata.gz: 5791ce130daf3f0d0300f6ca56fa07f88c6a94e08ff4979d84282526220a3eb4
4
+ data.tar.gz: d4ce31439d50ba72bff357e13901c4621a1a8f79ce0a8458ed1b0c948e22f7e0
5
5
  SHA512:
6
- metadata.gz: bacccbdfd46669936f1271d05e4fdceae1864e07ae7f14b260f6de3ec2ed1e90d0c3270f57ea3faaa424b267eab59e1460abcdf4262feec421c6ea510bc811d5
7
- data.tar.gz: ad8aaf32f6f71f349d04955cb795c0439c4ecd30103f290da82b3ce7037c6dce330b7e89123a416c120b61bc194c754debfb97412e6e200af8d53264aaba169c
6
+ metadata.gz: 427751ad2b8a07a0426c74aad97c2f67c2fa27b151f63db96e63d8116c15f39615ae40dd76d6aa3c1f6ad92c95c27219eb312bdb0f43f281b05ab8bd3cd07c12
7
+ data.tar.gz: bd056cdb49de93481735ba4ece34ed40c48ac7d728c31ec8d0066aa300ecb7bed055f5d541c6973e3459b292475497ce4ef5357ae5cb8e3ec681a66e29b4684f
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## [v0.8.0](https://github.com/opus-codium/choria-colt/tree/v0.8.0) (2022-11-25)
4
+
5
+ [Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.7.0...v0.8.0)
6
+
7
+ **Merged pull requests:**
8
+
9
+ - CLI: Summarize task status results by default [\#33](https://github.com/opus-codium/choria-colt/pull/33) ([neomilium](https://github.com/neomilium))
10
+ - CLI: Always display stderr if available [\#32](https://github.com/opus-codium/choria-colt/pull/32) ([neomilium](https://github.com/neomilium))
11
+
12
+ ## [v0.7.0](https://github.com/opus-codium/choria-colt/tree/v0.7.0) (2022-09-26)
13
+
14
+ [Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.6.0...v0.7.0)
15
+
16
+ **Fixed bugs:**
17
+
18
+ - Task: Fix IDs array processing [\#30](https://github.com/opus-codium/choria-colt/pull/30) ([neomilium](https://github.com/neomilium))
19
+
20
+ **Merged pull requests:**
21
+
22
+ - Use ActiveSuport::Cache instead our own Cache mecanism for tasks metadata [\#31](https://github.com/opus-codium/choria-colt/pull/31) ([neomilium](https://github.com/neomilium))
23
+ - Improve robustness when nodes are unhealthy [\#29](https://github.com/opus-codium/choria-colt/pull/29) ([neomilium](https://github.com/neomilium))
24
+
3
25
  ## [v0.6.0](https://github.com/opus-codium/choria-colt/tree/v0.6.0) (2022-05-16)
4
26
 
5
27
  [Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.5.1...v0.6.0)
data/choria-colt.gemspec CHANGED
@@ -35,6 +35,7 @@ Gem::Specification.new do |spec|
35
35
  spec.add_dependency 'puppet'
36
36
  spec.add_dependency 'thor'
37
37
  spec.add_dependency 'tty-logger'
38
+ spec.add_dependency 'tty-progressbar'
38
39
 
39
40
  # spec.add_development_dependency 'byebug'
40
41
  spec.add_development_dependency 'github_changelog_generator'
@@ -22,6 +22,10 @@ module Choria
22
22
  dig(:data, :runtime)
23
23
  end
24
24
 
25
+ def statuscode
26
+ self[:statuscode]
27
+ end
28
+
25
29
  # CLI
26
30
  def output
27
31
  if dig(:result, :_output).nil?
@@ -30,92 +34,131 @@ module Choria
30
34
  dig(:result, :_output)
31
35
  end
32
36
  end
37
+
38
+ def stderr
39
+ dig(:result, :_stderr)
40
+ end
33
41
  end
34
42
 
35
- attr_reader :pastel
43
+ module FormattedResult
44
+ attr_accessor :pastel
36
45
 
37
- def initialize(colored:)
38
- @pastel = Pastel.new(enabled: colored)
39
- pastel.alias_color(:host, :cyan)
40
- end
46
+ def host
47
+ if statuscode.zero?
48
+ format_host pastel.bright_green('√ ').to_s
49
+ else
50
+ format_host pastel.bright_red('⨯ ').to_s
51
+ end
52
+ end
41
53
 
42
- def process_result(result)
43
- result.extend Formatter::Result
54
+ def content
55
+ case statuscode
56
+ when 0
57
+ # 0 OK
58
+ format_success
59
+ when 1
60
+ # 1 OK, failed. All the data parsed ok, we have a action matching the request but the requested action could not be completed. RPCAborted
61
+ format_error
62
+ else
63
+ # 2 Unknown action UnknownRPCAction
64
+ # 3 Missing data MissingRPCData
65
+ # 4 Invalid data InvalidRPCData
66
+ # 5 Other error
67
+ format_rpc_error
68
+ end
69
+ end
44
70
 
45
- case result[:statuscode]
46
- when 0
47
- # 0 OK
48
- process_success(result)
49
- when 1
50
- # 1 OK, failed. All the data parsed ok, we have a action matching the request but the requested action could not be completed. RPCAborted
51
- process_error(result) # unless result.ok?
52
- else
53
- # 2 Unknown action UnknownRPCAction
54
- # 3 Missing data MissingRPCData
55
- # 4 Invalid data InvalidRPCData
56
- # 5 Other error
57
- process_rpc_error(result)
71
+ def to_s
72
+ [
73
+ host,
74
+ content,
75
+ ].join("\n")
58
76
  end
59
- end
60
77
 
61
- def process_success(result)
62
- host = format_host(result, "#{pastel.bright_green '√'} ")
63
- headline = "#{pastel.on_green ' '} "
78
+ private
64
79
 
65
- [
66
- host,
67
- result.output.map { |line| "#{headline}#{line}" },
68
- ].flatten.join("\n")
69
- end
80
+ def stderr_description
81
+ if stderr.nil? || stderr.empty?
82
+ []
83
+ else
84
+ [
85
+ nil,
86
+ pastel.bright_red('stderr:'),
87
+ stderr,
88
+ ]
89
+ end
90
+ end
91
+
92
+ def output_description
93
+ if output.nil? || output.empty?
94
+ []
95
+ else
96
+ [
97
+ nil,
98
+ pastel.bright_red('output:'),
99
+ output,
100
+ ]
101
+ end
102
+ end
103
+
104
+ def format_duration
105
+ runtime.nil? ? '' : "duration: #{pastel.bright_white format('%.2fs', runtime)}"
106
+ end
107
+
108
+ def format_host(headline)
109
+ "#{headline}#{pastel.host(sender).ljust(60, ' ')}#{format_duration}".strip
110
+ end
111
+
112
+ def format_success
113
+ headline = "#{pastel.on_green ' '} "
114
+ warning_headline = "#{pastel.on_yellow ' '} "
70
115
 
71
- def process_error(result) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
72
- host = format_host(result, "#{pastel.bright_red '⨯'} ")
73
- output = result.dig(:result, '_output')
74
- error_details = JSON.pretty_generate(result.dig(:result, :_error, :details)).split "\n"
75
- error_description = [
76
- "#{pastel.bright_red result.dig(:result, :_error, :kind)}: #{pastel.bright_white result.dig(:result, :_error, :msg)}",
77
- " details: #{error_details.shift}",
78
- error_details.map { |line| " #{line}" },
79
- ]
80
- output_description = if output.nil? || output.empty?
81
- []
82
- else
83
- [
84
- nil,
85
- pastel.bright_red('output:'),
86
- output,
87
- ]
88
- end
89
-
90
- headline = "#{pastel.on_red ' '} "
91
-
92
- [
93
- host,
94
116
  [
95
- error_description,
96
- output_description,
97
- ].flatten.map { |line| "#{headline}#{line}" },
98
- ].flatten.join("\n")
99
- end
117
+ output.map { |line| "#{headline}#{line}" },
118
+ stderr_description.flatten.map { |line| "#{warning_headline}#{line}" },
119
+ ].flatten.join("\n")
120
+ end
121
+
122
+ def format_error
123
+ error_details = JSON.pretty_generate(dig(:result, :_error, :details)).split "\n"
124
+ error_description = [
125
+ "#{pastel.bright_red dig(:result, :_error, :kind)}: #{pastel.bright_white dig(:result, :_error, :msg)}",
126
+ " details: #{error_details.shift}",
127
+ error_details.map { |line| " #{line}" },
128
+ ]
100
129
 
101
- def process_rpc_error(result)
102
- host = "#{pastel.bright_red '⨯'} #{pastel.host(result.sender)}"
103
- headline = "#{pastel.on_red ' '} "
130
+ headline = "#{pastel.on_red ' '} "
104
131
 
105
- [
106
- host,
107
- "#{headline}#{pastel.bright_red "RPC error (#{result[:statuscode]})"}: #{pastel.bright_white result[:statusmsg]}",
108
- ].join("\n")
132
+ [
133
+ [
134
+ error_description,
135
+ output_description,
136
+ stderr_description,
137
+ ].flatten.map { |line| "#{headline}#{line}" },
138
+ ].flatten.join("\n")
139
+ end
140
+
141
+ def format_rpc_error
142
+ headline = "#{pastel.on_red ' '} "
143
+
144
+ [
145
+ "#{headline}#{pastel.bright_red "RPC error (#{statuscode})"}: #{pastel.bright_white self[:statusmsg]}",
146
+ ].join("\n")
147
+ end
109
148
  end
110
149
 
111
- private
150
+ attr_reader :pastel
112
151
 
113
- def format_duration(result)
114
- result.runtime.nil? ? '' : "duration: #{pastel.bright_white format('%.2fs', result.runtime)}"
152
+ def initialize(colored:)
153
+ @pastel = Pastel.new(enabled: colored)
154
+ pastel.alias_color(:host, :cyan)
115
155
  end
116
156
 
117
- def format_host(result, headline)
118
- "#{headline}#{pastel.host(result.sender).ljust(60, ' ')}#{format_duration(result)}"
157
+ def format(result)
158
+ result.extend Formatter::Result
159
+ result.extend Formatter::FormattedResult
160
+ result.pastel = pastel
161
+ result
119
162
  end
120
163
  end
121
164
  end
@@ -44,7 +44,7 @@ module Choria
44
44
 
45
45
  environment = options['environment']
46
46
  results = colt.run_bolt_task task_name, input: input, targets: targets, targets_with_classes: targets_with_classes, environment: environment do |result|
47
- $stdout.puts formatter.process_result(result)
47
+ $stdout.puts formatter.format(result)
48
48
  end
49
49
 
50
50
  File.write 'last_run.json', JSON.pretty_generate(results)
@@ -68,10 +68,9 @@ module Choria
68
68
  default: 'production'
69
69
  def show(*tasks_names)
70
70
  environment = options['environment']
71
- cache_directory = File.expand_path('.cache/colt/tasks')
72
- FileUtils.mkdir_p cache_directory
73
- cache = Cache.new(path: File.join(cache_directory, "#{environment}.yaml"))
74
71
 
72
+ require 'active_support/cache/file_store'
73
+ cache = ActiveSupport::Cache::FileStore.new File.expand_path('~/.cache/colt/tasks')
75
74
  tasks = colt.tasks(environment: environment, cache: cache)
76
75
 
77
76
  if tasks_names.empty?
@@ -87,12 +86,24 @@ module Choria
87
86
 
88
87
  A task ID is required to request Choria services and retrieve results.
89
88
  DESC
89
+ option :style,
90
+ aliases: ['-S'],
91
+ desc: "Output style; can be 'continuous' or 'summary'",
92
+ default: 'summary'
90
93
  define_targets_and_filters_options
91
94
  def status(task_id)
95
+ supported_styles = %i[summary continous]
96
+ raise Thor::Error, "Invalid style: '#{options['style']}' (available: #{supported_styles})" unless supported_styles.include? options['style'].to_sym
97
+
92
98
  targets, targets_with_classes = extract_targets_and_filters_from_options
93
99
 
94
- results = colt.wait_bolt_task(task_id, targets: targets, targets_with_classes: targets_with_classes) do |result|
95
- $stdout.puts formatter.process_result(result)
100
+ case options['style']
101
+ when 'continous'
102
+ results = colt.wait_bolt_task(task_id, targets: targets, targets_with_classes: targets_with_classes) do |result|
103
+ $stdout.puts formatter.format(result)
104
+ end
105
+ when 'summary'
106
+ show_summarized_status(task_id, targets: targets, targets_with_classes: targets_with_classes)
96
107
  end
97
108
 
98
109
  File.write 'last_run.json', JSON.pretty_generate(results)
@@ -112,6 +123,7 @@ module Choria
112
123
  [:stream, { output: File.open('colt-debug.log', 'a'), level: :debug }],
113
124
  ]
114
125
  config.metadata = %i[date time]
126
+ Choria::Colt::Debugger.enabled = true
115
127
  end
116
128
  end
117
129
 
@@ -186,6 +198,33 @@ module Choria
186
198
  end.join "\n"
187
199
  end
188
200
 
201
+ def summarize(results)
202
+ results_grouped_by_result_content = results.group_by { |result| result[:result] }
203
+ results_grouped_by_result_content.each do |_content, grouped_results|
204
+ # Display each host
205
+ grouped_results.each do |result|
206
+ $stdout.puts formatter.format(result).host
207
+ end
208
+ # Display the result content
209
+ content = formatter.format(grouped_results.first).content
210
+ content = pastel.bright_white '(no output)' if content.nil? || content.empty?
211
+ $stdout.puts content
212
+ end
213
+ end
214
+
215
+ def show_summarized_status(task_id, targets:, targets_with_classes:)
216
+ require 'tty-progressbar'
217
+
218
+ bar = TTY::ProgressBar.new('[:bar] :current/:total ET::elapsed ETA::eta :rate/s')
219
+ results = colt.wait_bolt_task(task_id, targets: targets, targets_with_classes: targets_with_classes) do |_result, count, total_count|
220
+ bar.update total: total_count
221
+ bar.current = count
222
+ end
223
+
224
+ puts "\nSummary:"
225
+ summarize(results)
226
+ end
227
+
189
228
  def pastel
190
229
  @pastel ||= _pastel
191
230
  end
@@ -4,22 +4,29 @@ module Choria
4
4
  def self.structure(res) # rubocop:disable Metrics/AbcSize
5
5
  return res unless [0, 1].include? res[:statuscode]
6
6
 
7
+ # If data is empty, status message is an RPC error
8
+ if res[:data].empty?
9
+ res[:result] = {
10
+ _error: {
11
+ kind: 'choria/rpc',
12
+ msg: res[:statusmsg],
13
+ },
14
+ }
15
+ return res
16
+ end
17
+
7
18
  # data.stdout seems to always be JSON, so parse it once.
8
- res[:result] = JSON.parse res[:data][:stdout]
19
+ res[:result] = JSON.parse res[:data][:stdout] unless res.dig(:data, :stdout).nil?
9
20
  res[:data].delete :stdout
10
21
 
11
22
  # On one side, data.stderr is filled by the remote execution stderr.
12
23
  # On the other side, error description is in JSON (ie. '_error')
13
24
  # So merge data.stderr in '_error'.'details'
14
- unless res[:data][:stderr].empty?
15
- raise NotImplementedError, 'What to do when res[:data][:stderr] contains something?' if res[:result]['_error'].empty?
16
-
17
- res[:result]['_error']['details'].merge!({ 'stderr' => res[:data][:stderr].split("\n") })
18
- end
25
+ res[:result]['_stderr'] = res[:data][:stderr].split("\n") unless res.dig(:data, :stderr).nil? || res[:data][:stderr].empty?
19
26
  res[:data].delete :stderr
20
27
 
21
28
  # Convert '_output' (ie. stdout) lines into array
22
- res[:result]['_output'] = res[:result]['_output'].split("\n") unless res[:result]['_output'].nil?
29
+ res[:result]['_output'] = res[:result]['_output'].split("\n") unless res.dig(:result, '_output').nil?
23
30
 
24
31
  res
25
32
  end
@@ -0,0 +1,28 @@
1
+ module Choria
2
+ class Colt
3
+ module Debugger
4
+ class << self
5
+ attr_writer :enabled
6
+
7
+ def enabled
8
+ @enabled ||= false
9
+ end
10
+
11
+ def root_directory
12
+ 'colt-debug'
13
+ end
14
+
15
+ # This method is helpful to grab raw content to be used as test fixture
16
+ # To do so, copy the generated result set (ie. directory) in relevant fixture directory (e.g. `spec/fixtures/orchestrator/task/result_sets`)
17
+ def save_file(result_set:, filename:, content:)
18
+ directory = File.join Colt::Debugger.root_directory, result_set
19
+ FileUtils.mkdir_p directory
20
+ path = File.join directory, filename
21
+ File.write(path, content)
22
+
23
+ path
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Choria
4
4
  class Colt
5
- VERSION = '0.6.0'
5
+ VERSION = '0.8.0'
6
6
  end
7
7
  end
data/lib/choria/colt.rb CHANGED
@@ -1,12 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'choria/colt/cache'
4
3
  require 'choria/colt/version'
5
4
  require 'choria/orchestrator'
6
5
  require 'choria/orchestrator/task'
7
6
 
8
7
  require 'logger'
9
8
 
9
+ require 'active_support/cache/memory_store'
10
+
10
11
  module Choria
11
12
  class Colt
12
13
  class Error < StandardError; end
@@ -45,32 +46,30 @@ module Choria
45
46
  raise
46
47
  end
47
48
 
48
- def tasks(environment:, cache: nil)
49
+ def tasks(environment:, cache: nil, force_cache_refresh: false)
50
+ cache ||= ActiveSupport::Cache::MemoryStore.new
51
+
49
52
  tasks_names = orchestrator.tasks_support.tasks(environment).map do |task|
50
53
  task['name']
51
54
  end
52
55
 
53
- return tasks_metadata(tasks_names, environment) if cache.nil?
54
-
55
- cached_tasks = cache.load
56
- return cached_tasks if cache.clean? && cached_tasks.keys.sort == tasks_names.sort
57
-
58
- updated_tasks = tasks_metadata(tasks_names, environment)
59
- cache.save updated_tasks
60
-
61
- updated_tasks
56
+ tasks_names.map do |task_name|
57
+ metadata = cache.fetch(task_name, force: force_cache_refresh) do
58
+ task_metadata(task_name, environment)
59
+ end
60
+ [task_name, metadata]
61
+ end.to_h
62
62
  end
63
63
 
64
64
  private
65
65
 
66
- def tasks_metadata(tasks, environment)
67
- logger.info "Fetching metadata for tasks (environment: '#{environment}')"
66
+ def task_metadata(name, environment)
67
+ logger.debug "Fetching metadata for task '#{name}' (environment: '#{environment}')"
68
68
 
69
- tasks.map do |task|
70
- logger.debug "Fetching metadata for task '#{task}' (environment: '#{environment}')"
71
- metadata = orchestrator.tasks_support.task_metadata(task, environment)
72
- [task, metadata]
73
- end.to_h
69
+ # FIXME: Remove this workaround when the Puppet bug is fixed
70
+ return { 'metadata' => { 'private' => true } } if ['application::utils'].include? name
71
+
72
+ orchestrator.tasks_support.task_metadata(name, environment)
74
73
  end
75
74
  end
76
75
  end
@@ -6,9 +6,12 @@ module Choria
6
6
  class ResultSet
7
7
  attr_reader :results
8
8
 
9
+ attr_accessor :pending_count
10
+
9
11
  def initialize(on_result:)
10
12
  @results = []
11
13
  @on_result = on_result
14
+ @pending_count = 0
12
15
  end
13
16
 
14
17
  def integrate_rpc_error(rpc_error)
@@ -20,7 +23,7 @@ module Choria
20
23
  def integrate_result(result)
21
24
  structured_result = Choria::Colt::DataStructurer.structure(result).with_indifferent_access
22
25
  @results << structured_result
23
- @on_result&.call(structured_result)
26
+ @on_result&.call(structured_result, @results.count, pending_count + @results.count)
24
27
  end
25
28
  end
26
29
  end
@@ -3,6 +3,8 @@ require_relative 'task/result_set'
3
3
  require 'active_support'
4
4
  require 'active_support/core_ext/hash/indifferent_access'
5
5
 
6
+ require 'choria/colt/debugger'
7
+
6
8
  module Choria
7
9
  class Orchestrator
8
10
  class Task
@@ -55,7 +57,7 @@ module Choria
55
57
  end
56
58
 
57
59
  def on_result(&block)
58
- @on_result = ->(result) { block.call(result) }
60
+ @on_result = ->(result, count, total_count) { block.call(result, count, total_count) }
59
61
  end
60
62
 
61
63
  private
@@ -64,15 +66,26 @@ module Choria
64
66
  @result_set ||= ResultSet.new(on_result: @on_result)
65
67
  end
66
68
 
69
+ def log_new_result(res)
70
+ if Colt::Debugger.enabled
71
+ debug_file = Colt::Debugger.save_file(result_set: @id, filename: "#{Time.now.iso8601}-#{res[:sender]}.json", content: JSON.pretty_generate(res))
72
+ logger.debug "New result for task ##{@id} saved in '#{debug_file}'"
73
+ else
74
+ logger.debug "New result for task ##{@id} from '#{res[:sender]}'"
75
+ end
76
+ end
77
+
67
78
  def rpc_results=(results)
68
79
  completed_results = results.reject { |res| res[:data][:exitcode] == -1 }
69
80
  @pending_targets ||= results.map { |res| res[:sender] }
70
81
 
71
82
  new_results = completed_results.select { |res| @pending_targets.include? res[:sender] }
72
83
  new_results.each do |res|
73
- logger.debug "New result for task ##{@id}: #{res}"
74
- result_set.integrate_result(res)
84
+ log_new_result res
85
+
75
86
  @pending_targets.delete res[:sender]
87
+ result_set.pending_count = @pending_targets.count
88
+ result_set.integrate_result res
76
89
  end
77
90
  end
78
91
 
@@ -103,6 +116,7 @@ module Choria
103
116
  end
104
117
  raise NoNodesLeftError, "No nodes left to continue after 'run_no_wait' action" if @pending_targets.empty?
105
118
 
119
+ task_ids.compact!
106
120
  task_ids.uniq!
107
121
  raise NotImplementedError, "Multiple task IDs: #{task_ids}" unless task_ids.count == 1
108
122
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: choria-colt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.8.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Romuald Conty
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-05-16 00:00:00.000000000 Z
11
+ date: 2022-11-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -108,6 +108,20 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: tty-progressbar
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
111
125
  - !ruby/object:Gem::Dependency
112
126
  name: github_changelog_generator
113
127
  requirement: !ruby/object:Gem::Requirement
@@ -210,11 +224,11 @@ files:
210
224
  - choria-colt.gemspec
211
225
  - exe/colt
212
226
  - lib/choria/colt.rb
213
- - lib/choria/colt/cache.rb
214
227
  - lib/choria/colt/cli.rb
215
228
  - lib/choria/colt/cli/formatter.rb
216
229
  - lib/choria/colt/cli/thor.rb
217
230
  - lib/choria/colt/data_structurer.rb
231
+ - lib/choria/colt/debugger.rb
218
232
  - lib/choria/colt/version.rb
219
233
  - lib/choria/orchestrator.rb
220
234
  - lib/choria/orchestrator/task.rb
@@ -1,33 +0,0 @@
1
- require 'yaml'
2
-
3
- module Choria
4
- class Colt
5
- class Cache
6
- def initialize(path:, force_refresh: false)
7
- @path = path
8
- @data = YAML.safe_load File.read(@path)
9
- @clean = true unless force_refresh
10
- rescue Errno::ENOENT
11
- @clean = false
12
- end
13
-
14
- def dirty?
15
- !clean?
16
- end
17
-
18
- def clean?
19
- @clean
20
- end
21
-
22
- def load
23
- @data
24
- end
25
-
26
- def save(data)
27
- @data = data
28
- File.write @path, data.to_yaml
29
- @clean = true
30
- end
31
- end
32
- end
33
- end