knife-node-context-exec 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: d99cf4455cd6c9ec2db19c61067a19e6c2bfca8c
4
+ data.tar.gz: b91ea5849c60d64f125375feaa9a80fdb4403483
5
+ SHA512:
6
+ metadata.gz: f2b39683e071789698cd3d64c8ceb8f8e9f9a01fd5da01d0fbaac5c67b23d8bf0f6335404a77e2acd53b2aad4c74ba8d0e827dc159c81d32fedf3c97181896d7
7
+ data.tar.gz: 8b1edd59577af9ed084edf6f86a0e75514355bfc4c5ec21f9f7b20c8230ea3e59ae2086442bf23625ff4159c36636ea92e145b07ec1a2a4eae86e6df86cc2621
@@ -0,0 +1,52 @@
1
+ # The knife
2
+ class ContextExec < Chef::Knife
3
+ banner 'knife context exec'
4
+
5
+ deps do
6
+ require 'chef/search/query'
7
+ require 'knife-node-context-exec/runner'
8
+ end
9
+
10
+ option :environment,
11
+ short: '-E',
12
+ long: '--environment',
13
+ description: 'The environment to search.'
14
+ option :node_query,
15
+ short: '-Q',
16
+ long: '--query',
17
+ description: 'The node query.'
18
+ option :directory,
19
+ short: '-D',
20
+ long: '--directory',
21
+ description: 'A directory for working files.'
22
+ option :template_filename,
23
+ short: '-T',
24
+ long: '--template',
25
+ description: 'The filename of a template.'
26
+ option :script_filename,
27
+ short: '-S',
28
+ long: '--script',
29
+ description: 'The environment to search.'
30
+ option :command,
31
+ short: '-C',
32
+ long: '--command',
33
+ description: 'The command to run.'
34
+ option :filter_regex,
35
+ short: '-R',
36
+ long: '--regex',
37
+ description: 'A regex used to filter output.'
38
+ option :parallel,
39
+ short: '-P',
40
+ long: '--parallel',
41
+ description: 'Run in parallel?'
42
+
43
+ def run
44
+ environment = config[:environment].to_s
45
+ nodes = Chef::Search::Query.new.search(:node, config[:node_query].to_s).first.select do |node|
46
+ node.environment == environment
47
+ end
48
+ KnifeNodeContextExec.run(nodes, config[:directory].to_s, config[:template_filename].to_s,
49
+ config[:script_filename].to_s, config[:command].to_s, config[:filter_regex].to_s,
50
+ config[:parallel].to_s == 'true', false)
51
+ end
52
+ end
@@ -0,0 +1,65 @@
1
+ require 'open3'
2
+ require 'erb'
3
+
4
+ # Runs commands over a set of nodes
5
+ module KnifeNodeContextExec
6
+ # Runs a command in the context of each node
7
+ class NodeRunner
8
+ attr_reader :node, :working_directory, :template_filename, :script_filename, :command, :output
9
+
10
+ def initialize(node, working_directory, template_filename, script_filename, command)
11
+ @node = node
12
+ @working_directory = working_directory
13
+ @template_filename = template_filename
14
+ @script_filename = script_filename
15
+ @command = command
16
+ end
17
+
18
+ def run
19
+ @thread = Thread.new do
20
+ script_directory = "#{working_directory}/#{node[:name]}"
21
+ FileUtils.makedirs(script_directory)
22
+ template = File.read(template_filename)
23
+ script = ERB.new(template).result(binding)
24
+ full_script_filename =
25
+ File.join(script_directory, script_filename).gsub(File::SEPARATOR, File::ALT_SEPARATOR || File::SEPARATOR)
26
+ File.open(full_script_filename, 'w') { |file| file.puts(script) }
27
+ cooked_command = command.gsub('%script%', full_script_filename)
28
+ @output = []
29
+ Open3.pipeline_r(cooked_command) do |output, _|
30
+ output.each_line do |line|
31
+ line.rstrip!
32
+ @output << line
33
+ yield(line)
34
+ end
35
+ end
36
+ end
37
+ self
38
+ end
39
+
40
+ def wait
41
+ @thread.join
42
+ self
43
+ end
44
+ end
45
+
46
+ def self.run(nodes, working_directory, template_filename, script_filename, command, filter_regex, parallel, clean)
47
+ FileUtils.makedirs(working_directory)
48
+ temporary_directory = Dir.mktmpdir('x', working_directory)
49
+ nodes = nodes.map do |node|
50
+ node = KnifeNodeContextExec::NodeRunner.new(node, temporary_directory,
51
+ template_filename, script_filename, command).run do |line|
52
+ puts line if line =~ /#{filter_regex}/
53
+ end
54
+ node.wait unless parallel
55
+ node
56
+ end
57
+ nodes.each(&:wait)
58
+ nodes.each do |node|
59
+ puts
60
+ puts "===== FULL OUTPUT - #{node.node[:name]} ======================"
61
+ node.output.each { |line| puts line }
62
+ end
63
+ FileUtils.remove_dir(working_directory) if clean
64
+ end
65
+ end
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: knife-node-context-exec
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Andrew Heald
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-07 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: Runs a search against Chef server and executes a command for each returned
14
+ node. See the project home page for more information.
15
+ email: andrew@heald.uk
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/chef/knife/context_exec.rb
21
+ - lib/knife-node-context-exec/runner.rb
22
+ homepage: https://github.com/sappho/knife-node-context-exec
23
+ licenses: []
24
+ metadata: {}
25
+ post_install_message:
26
+ rdoc_options: []
27
+ require_paths:
28
+ - lib
29
+ required_ruby_version: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ required_rubygems_version: !ruby/object:Gem::Requirement
35
+ requirements:
36
+ - - ">="
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 2.4.8
42
+ signing_key:
43
+ specification_version: 4
44
+ summary: Runs a search against Chef server and executes a command for each returned
45
+ node
46
+ test_files: []