choria-colt 0.5.1 → 0.7.0
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/.rubocop_todo.yml +1 -6
- data/CHANGELOG.md +28 -0
- data/README.md +2 -2
- data/lib/choria/colt/cli.rb +36 -22
- data/lib/choria/colt/data_structurer.rb +14 -3
- data/lib/choria/colt/version.rb +1 -1
- data/lib/choria/colt.rb +22 -23
- data/lib/choria/orchestrator/task.rb +3 -2
- data/lib/choria/orchestrator.rb +9 -5
- metadata +2 -3
- data/lib/choria/colt/cache.rb +0 -33
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e86ae8b9274433cf146d571d2a7466a2c7c131e826ec5e4a8df9540d37f7994d
|
4
|
+
data.tar.gz: 9e4717f11b4f1f3f93c555818b9281e0118ac59a4bbf7b2573d6a85ed6e74fd9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3754982bc70a01d44fc4115c76693f67201d5a618d2f61b229d9b3408bea3ff2c2ac187ea5c0bd55fdbf8ca391c668f09086339ab366a85f93100c0ac1bd8973
|
7
|
+
data.tar.gz: c1a1dd4eaf6287d28d09baa7f45ff7ab297ffff5a8bd78d519d9a814dfcab74512d6f300fe6696789d1687e1a9f04aa021f90531a98143e263fae4d3a8d53688
|
data/.rubocop_todo.yml
CHANGED
@@ -1,16 +1,11 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2022-
|
3
|
+
# on 2022-05-03 07:08:32 UTC using RuboCop version 1.26.0.
|
4
4
|
# The point is for the user to remove these configuration records
|
5
5
|
# one by one as the offenses are removed from the code base.
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
7
7
|
# versions of RuboCop, may require this file to be generated again.
|
8
8
|
|
9
|
-
# Offense count: 1
|
10
|
-
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
|
11
|
-
Metrics/AbcSize:
|
12
|
-
Max: 22
|
13
|
-
|
14
9
|
# Offense count: 1
|
15
10
|
# Configuration parameters: IgnoredMethods.
|
16
11
|
Metrics/CyclomaticComplexity:
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,33 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [v0.7.0](https://github.com/opus-codium/choria-colt/tree/v0.7.0) (2022-09-26)
|
4
|
+
|
5
|
+
[Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.6.0...v0.7.0)
|
6
|
+
|
7
|
+
**Fixed bugs:**
|
8
|
+
|
9
|
+
- Task: Fix IDs array processing [\#30](https://github.com/opus-codium/choria-colt/pull/30) ([neomilium](https://github.com/neomilium))
|
10
|
+
|
11
|
+
**Merged pull requests:**
|
12
|
+
|
13
|
+
- 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))
|
14
|
+
- Improve robustness when nodes are unhealthy [\#29](https://github.com/opus-codium/choria-colt/pull/29) ([neomilium](https://github.com/neomilium))
|
15
|
+
|
16
|
+
## [v0.6.0](https://github.com/opus-codium/choria-colt/tree/v0.6.0) (2022-05-16)
|
17
|
+
|
18
|
+
[Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.5.1...v0.6.0)
|
19
|
+
|
20
|
+
**Merged pull requests:**
|
21
|
+
|
22
|
+
- Allow to run a task from any puppet environment [\#28](https://github.com/opus-codium/choria-colt/pull/28) ([neomilium](https://github.com/neomilium))
|
23
|
+
- CLI: Use symbol notation to target `:all` nodes [\#27](https://github.com/opus-codium/choria-colt/pull/27) ([neomilium](https://github.com/neomilium))
|
24
|
+
- CLI: Allow targeting on task status requests [\#26](https://github.com/opus-codium/choria-colt/pull/26) ([neomilium](https://github.com/neomilium))
|
25
|
+
- Fix `task status` command [\#25](https://github.com/opus-codium/choria-colt/pull/25) ([neomilium](https://github.com/neomilium))
|
26
|
+
|
27
|
+
## [v0.5.1](https://github.com/opus-codium/choria-colt/tree/v0.5.1) (2022-05-02)
|
28
|
+
|
29
|
+
[Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.5.0...v0.5.1)
|
30
|
+
|
3
31
|
## [v0.5.0](https://github.com/opus-codium/choria-colt/tree/v0.5.0) (2022-05-02)
|
4
32
|
|
5
33
|
[Full Changelog](https://github.com/opus-codium/choria-colt/compare/v0.4.0...v0.5.0)
|
data/README.md
CHANGED
@@ -51,8 +51,8 @@ To install this gem onto your local machine, run `bundle exec rake install`.
|
|
51
51
|
|
52
52
|
|
53
53
|
To release a new version:
|
54
|
-
1. update the version number in `version.rb`
|
55
|
-
1. generate CHANGELOG.md with `bundle exec rake changelog`
|
54
|
+
1. update the version number in `lib/choria/colt/version.rb`
|
55
|
+
1. generate `CHANGELOG.md` with `bundle exec rake changelog`
|
56
56
|
1. commit changes
|
57
57
|
1. run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
58
58
|
|
data/lib/choria/colt/cli.rb
CHANGED
@@ -9,6 +9,15 @@ module Choria
|
|
9
9
|
class Colt
|
10
10
|
class CLI < Thor
|
11
11
|
class Tasks < Thor
|
12
|
+
def self.define_targets_and_filters_options
|
13
|
+
option :targets,
|
14
|
+
aliases: ['--target', '-t'],
|
15
|
+
desc: 'Identifies the targets of the command.'
|
16
|
+
option :targets_with_classes,
|
17
|
+
aliases: ['--targets-with-class', '-C'],
|
18
|
+
desc: 'Select the targets which have the specified Puppet classes.'
|
19
|
+
end
|
20
|
+
|
12
21
|
class_option :log_level,
|
13
22
|
desc: 'Set log level for CLI',
|
14
23
|
default: 'info'
|
@@ -19,28 +28,22 @@ module Choria
|
|
19
28
|
|
20
29
|
Parameters take the form parameter=value.
|
21
30
|
DESC
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
def run(*args) # rubocop:disable Metrics/AbcSize
|
29
|
-
input = extract_task_parameters_from_args(args)
|
30
|
-
targets = extract_targets_from_options
|
31
|
-
|
31
|
+
define_targets_and_filters_options
|
32
|
+
option :environment,
|
33
|
+
aliases: ['-E'],
|
34
|
+
desc: 'Puppet environment to grab tasks from',
|
35
|
+
default: 'production'
|
36
|
+
def run(*args)
|
32
37
|
raise Thor::Error, 'Task name is required' if args.empty?
|
33
|
-
raise Thor::Error, "Too many arguments: #{args}" unless args.count == 1
|
34
38
|
|
35
|
-
|
39
|
+
input = extract_task_parameters_from_args(args)
|
40
|
+
raise Thor::Error, "Too many arguments: #{args}" unless args.count == 1
|
36
41
|
|
37
42
|
task_name = args.shift
|
43
|
+
targets, targets_with_classes = extract_targets_and_filters_from_options
|
38
44
|
|
39
|
-
|
40
|
-
|
41
|
-
targets_with_classes = options['targets_with_classes']&.split(',')
|
42
|
-
|
43
|
-
results = colt.run_bolt_task task_name, input: input, targets: targets, targets_with_classes: targets_with_classes do |result|
|
45
|
+
environment = options['environment']
|
46
|
+
results = colt.run_bolt_task task_name, input: input, targets: targets, targets_with_classes: targets_with_classes, environment: environment do |result|
|
44
47
|
$stdout.puts formatter.process_result(result)
|
45
48
|
end
|
46
49
|
|
@@ -65,10 +68,9 @@ module Choria
|
|
65
68
|
default: 'production'
|
66
69
|
def show(*tasks_names)
|
67
70
|
environment = options['environment']
|
68
|
-
cache_directory = File.expand_path('.cache/colt/tasks')
|
69
|
-
FileUtils.mkdir_p cache_directory
|
70
|
-
cache = Cache.new(path: File.join(cache_directory, "#{environment}.yaml"))
|
71
71
|
|
72
|
+
require 'active_support/cache/file_store'
|
73
|
+
cache = ActiveSupport::Cache::FileStore.new File.expand_path('~/.cache/colt/tasks')
|
72
74
|
tasks = colt.tasks(environment: environment, cache: cache)
|
73
75
|
|
74
76
|
if tasks_names.empty?
|
@@ -84,8 +86,11 @@ module Choria
|
|
84
86
|
|
85
87
|
A task ID is required to request Choria services and retrieve results.
|
86
88
|
DESC
|
89
|
+
define_targets_and_filters_options
|
87
90
|
def status(task_id)
|
88
|
-
|
91
|
+
targets, targets_with_classes = extract_targets_and_filters_from_options
|
92
|
+
|
93
|
+
results = colt.wait_bolt_task(task_id, targets: targets, targets_with_classes: targets_with_classes) do |result|
|
89
94
|
$stdout.puts formatter.process_result(result)
|
90
95
|
end
|
91
96
|
|
@@ -130,8 +135,17 @@ module Choria
|
|
130
135
|
end.to_h
|
131
136
|
end
|
132
137
|
|
138
|
+
def extract_targets_and_filters_from_options
|
139
|
+
raise Thor::Error, 'Flag --targets or --targets-with-class is required' if options['targets'].nil? && options['targets_with_classes'].nil?
|
140
|
+
|
141
|
+
targets = extract_targets_from_options
|
142
|
+
targets_with_classes = options['targets_with_classes']&.split(',')
|
143
|
+
|
144
|
+
[targets, targets_with_classes]
|
145
|
+
end
|
146
|
+
|
133
147
|
def extract_targets_from_options
|
134
|
-
return nil if options['targets'] == 'all'
|
148
|
+
return nil if options['targets'] == ':all'
|
135
149
|
|
136
150
|
targets = options['targets']&.split(',')
|
137
151
|
targets&.map do |t|
|
@@ -4,14 +4,25 @@ 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?
|
25
|
+
unless res.dig(:data, :stderr).nil? || res[:data][:stderr].empty?
|
15
26
|
raise NotImplementedError, 'What to do when res[:data][:stderr] contains something?' if res[:result]['_error'].empty?
|
16
27
|
|
17
28
|
res[:result]['_error']['details'].merge!({ 'stderr' => res[:data][:stderr].split("\n") })
|
@@ -19,7 +30,7 @@ module Choria
|
|
19
30
|
res[:data].delete :stderr
|
20
31
|
|
21
32
|
# Convert '_output' (ie. stdout) lines into array
|
22
|
-
res[:result]['_output'] = res[:result]['_output'].split("\n") unless res
|
33
|
+
res[:result]['_output'] = res[:result]['_output'].split("\n") unless res.dig(:result, '_output').nil?
|
23
34
|
|
24
35
|
res
|
25
36
|
end
|
data/lib/choria/colt/version.rb
CHANGED
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
|
@@ -19,9 +20,9 @@ module Choria
|
|
19
20
|
@orchestrator = Choria::Orchestrator.new logger: @logger
|
20
21
|
end
|
21
22
|
|
22
|
-
def run_bolt_task(task_name, input: {}, targets: nil, targets_with_classes: nil, &block)
|
23
|
+
def run_bolt_task(task_name, input: {}, targets: nil, targets_with_classes: nil, environment: 'production', &block)
|
23
24
|
logger.debug "Instantiate task '#{task_name}' and validate input"
|
24
|
-
task = Choria::Orchestrator::Task.new(name: task_name, input: input, orchestrator: orchestrator)
|
25
|
+
task = Choria::Orchestrator::Task.new(name: task_name, input: input, environment: environment, orchestrator: orchestrator)
|
25
26
|
|
26
27
|
task.on_result(&block) if block_given?
|
27
28
|
|
@@ -33,11 +34,11 @@ module Choria
|
|
33
34
|
raise
|
34
35
|
end
|
35
36
|
|
36
|
-
def wait_bolt_task(task_id, &block)
|
37
|
-
|
37
|
+
def wait_bolt_task(task_id, targets: nil, targets_with_classes: nil, &block)
|
38
|
+
orchestrator.discover(targets: targets, targets_with_classes: targets_with_classes)
|
38
39
|
|
40
|
+
task = Choria::Orchestrator::Task.new(id: task_id, orchestrator: orchestrator)
|
39
41
|
task.on_result(&block) if block_given?
|
40
|
-
|
41
42
|
task.wait
|
42
43
|
task.results
|
43
44
|
rescue Choria::Orchestrator::Error => e
|
@@ -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
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
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
|
67
|
-
logger.
|
66
|
+
def task_metadata(name, environment)
|
67
|
+
logger.debug "Fetching metadata for task '#{name}' (environment: '#{environment}')"
|
68
68
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
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
|
@@ -65,8 +65,8 @@ module Choria
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def rpc_results=(results)
|
68
|
-
|
69
|
-
@pending_targets ||=
|
68
|
+
completed_results = results.reject { |res| res[:data][:exitcode] == -1 }
|
69
|
+
@pending_targets ||= results.map { |res| res[:sender] }
|
70
70
|
|
71
71
|
new_results = completed_results.select { |res| @pending_targets.include? res[:sender] }
|
72
72
|
new_results.each do |res|
|
@@ -103,6 +103,7 @@ module Choria
|
|
103
103
|
end
|
104
104
|
raise NoNodesLeftError, "No nodes left to continue after 'run_no_wait' action" if @pending_targets.empty?
|
105
105
|
|
106
|
+
task_ids.compact!
|
106
107
|
task_ids.uniq!
|
107
108
|
raise NotImplementedError, "Multiple task IDs: #{task_ids}" unless task_ids.count == 1
|
108
109
|
|
data/lib/choria/orchestrator.rb
CHANGED
@@ -39,10 +39,16 @@ module Choria
|
|
39
39
|
@tasks_support ||= MCollective::Util::Choria.new.tasks_support
|
40
40
|
end
|
41
41
|
|
42
|
-
def run(task, targets: nil, targets_with_classes: nil, verbose: false)
|
42
|
+
def run(task, targets: nil, targets_with_classes: nil, verbose: false)
|
43
43
|
rpc_client.progress = verbose
|
44
|
+
discover(targets: targets, targets_with_classes: targets_with_classes)
|
45
|
+
raise DiscoverError, 'No requests sent, no nodes discovered' if rpc_client.discover.size.zero?
|
46
|
+
|
47
|
+
task.run
|
48
|
+
end
|
44
49
|
|
45
|
-
|
50
|
+
def discover(targets: nil, targets_with_classes: nil)
|
51
|
+
logger.debug "Targets: #{targets.nil? ? 'all' : targets})"
|
46
52
|
targets&.each { |target| rpc_client.identity_filter target }
|
47
53
|
|
48
54
|
unless targets_with_classes.nil?
|
@@ -51,9 +57,7 @@ module Choria
|
|
51
57
|
end
|
52
58
|
|
53
59
|
logger.info 'Discovering targets…'
|
54
|
-
|
55
|
-
|
56
|
-
task.run
|
60
|
+
rpc_client.discover
|
57
61
|
end
|
58
62
|
|
59
63
|
def rpc_client
|
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.
|
4
|
+
version: 0.7.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-
|
11
|
+
date: 2022-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -210,7 +210,6 @@ files:
|
|
210
210
|
- choria-colt.gemspec
|
211
211
|
- exe/colt
|
212
212
|
- lib/choria/colt.rb
|
213
|
-
- lib/choria/colt/cache.rb
|
214
213
|
- lib/choria/colt/cli.rb
|
215
214
|
- lib/choria/colt/cli/formatter.rb
|
216
215
|
- lib/choria/colt/cli/thor.rb
|
data/lib/choria/colt/cache.rb
DELETED
@@ -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
|