collins_shell 0.2.17 → 0.2.18
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.
- data/VERSION +1 -1
- data/collins_shell.gemspec +2 -2
- data/lib/collins_shell/asset.rb +8 -3
- data/lib/collins_shell/console/commands/cat.rb +1 -0
- data/lib/collins_shell/thor.rb +10 -2
- data/lib/collins_shell/util.rb +55 -2
- metadata +3 -3
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.2.
|
1
|
+
0.2.18
|
data/collins_shell.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "collins_shell"
|
8
|
-
s.version = "0.2.
|
8
|
+
s.version = "0.2.18"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Blake Matheny"]
|
12
|
-
s.date = "
|
12
|
+
s.date = "2013-03-19"
|
13
13
|
s.description = "Provides basic CLI for interacting with Collins API"
|
14
14
|
s.email = "bmatheny@tumblr.com"
|
15
15
|
s.executables = ["collins-shell"]
|
data/lib/collins_shell/asset.rb
CHANGED
@@ -49,8 +49,8 @@ module CollinsShell
|
|
49
49
|
method_option :exec, :type => :string, :desc => 'Execute a command using the data from this asset. Use {{hostname}}, {{ipmi.password}}, etc for substitution'
|
50
50
|
method_option :header, :type => :boolean, :default => true, :desc => 'Display a tag header. Defaults to true'
|
51
51
|
method_option :logs, :type => :boolean, :default => false, :desc => 'Also display asset logs, only used with details (SLOW)'
|
52
|
-
method_option :size, :type => :numeric, :default => 50, :desc => 'Number of results to find. Defaults to 50'
|
53
52
|
method_option :tags, :type => :array, :desc => 'Tags to display of form: tag1 tag2 tag3. e.g. --tags=hostname tag backend_ip_address'
|
53
|
+
method_option :threads, :type => :numeric, :default => 1, :desc => 'Number of threads to use for --exec. Defaults to 1.'
|
54
54
|
method_option :url, :type => :boolean, :default => true, :desc => 'Display a URL along with tags or the default listing'
|
55
55
|
def find
|
56
56
|
client = get_collins_client
|
@@ -69,14 +69,15 @@ module CollinsShell
|
|
69
69
|
:detailed => !options.exec?
|
70
70
|
puts printer
|
71
71
|
end
|
72
|
-
asset_exec asset, options.exec, options.confirm
|
72
|
+
asset_exec asset, options.exec, options.confirm, options.threads
|
73
73
|
end
|
74
74
|
else
|
75
75
|
if not options.quiet then
|
76
76
|
print_find_results assets, options.tags, :header => options.header, :url => options.url
|
77
77
|
end
|
78
|
-
assets.each {|asset| asset_exec(asset, options.exec, options.confirm)}
|
78
|
+
assets.each {|asset| asset_exec(asset, options.exec, options.confirm, options.threads)}
|
79
79
|
end
|
80
|
+
finalize_exec
|
80
81
|
end
|
81
82
|
|
82
83
|
desc 'find_similar TAG', 'get similar unallocated assets for a gven asset'
|
@@ -136,6 +137,7 @@ module CollinsShell
|
|
136
137
|
batch_selector_operation Hash[
|
137
138
|
:remote => options.remote,
|
138
139
|
:operation => "set_attribute",
|
140
|
+
:size => options["size"],
|
139
141
|
:success_message => proc {|asset| "Set attribute on #{asset.tag}"},
|
140
142
|
:error_message => proc{|asset| "Setting attribute on #{asset.tag}"},
|
141
143
|
:confirmation_message => proc do |assets|
|
@@ -172,6 +174,7 @@ module CollinsShell
|
|
172
174
|
batch_selector_operation Hash[
|
173
175
|
:remote => options.remote,
|
174
176
|
:operation => "set_attributes",
|
177
|
+
:size => options["size"],
|
175
178
|
:success_message => proc {|asset| "Set attributes on #{asset.tag}"},
|
176
179
|
:error_message => proc{|asset| "Setting attributes on #{asset.tag}"},
|
177
180
|
:confirmation_message => proc do |assets|
|
@@ -190,6 +193,7 @@ module CollinsShell
|
|
190
193
|
batch_selector_operation Hash[
|
191
194
|
:remote => options.remote,
|
192
195
|
:operation => "delete_attribute",
|
196
|
+
:size => options["size"],
|
193
197
|
:success_message => proc {|asset| "Delete attribute on #{asset.tag}"},
|
194
198
|
:error_message => proc{|asset| "Delete attribute on #{asset.tag}"},
|
195
199
|
:confirmation_message => proc do |assets|
|
@@ -217,6 +221,7 @@ module CollinsShell
|
|
217
221
|
batch_selector_operation Hash[
|
218
222
|
:remote => options.remote,
|
219
223
|
:operation => "set_status",
|
224
|
+
:size => options["size"],
|
220
225
|
:success_message => proc {|asset| "Set status to #{status} on #{asset.tag}"},
|
221
226
|
:error_message => proc{|asset| "Setting status on #{asset.tag}"},
|
222
227
|
:confirmation_message => proc do |assets|
|
data/lib/collins_shell/thor.rb
CHANGED
@@ -48,6 +48,7 @@ module CollinsShell
|
|
48
48
|
def use_selector_option required = false
|
49
49
|
method_option :selector, :type => :hash, :required => required, :desc => 'Selector to query collins. Takes the form of --selector=key1:val1 key2:val2 etc'
|
50
50
|
method_option :remote, :type => :boolean, :default => false, :desc => 'Search all collins instances, including remote ones'
|
51
|
+
method_option :size, :type => :numeric, :default => 50, :desc => 'Number of results to find. Defaults to 50'
|
51
52
|
end
|
52
53
|
|
53
54
|
def selector_or_tag
|
@@ -61,9 +62,16 @@ module CollinsShell
|
|
61
62
|
end
|
62
63
|
|
63
64
|
def require_yes message, color = nil, should_exit = true
|
65
|
+
def appropriate_answer?(a); na = a.to_s.downcase.strip; na == 'yes' || na == 'no'; end
|
64
66
|
highline = HighLine.new
|
65
67
|
colored_message = set_color(message, color)
|
66
|
-
answer =
|
68
|
+
answer = nil
|
69
|
+
while !appropriate_answer?(answer) do
|
70
|
+
unless answer.nil? then
|
71
|
+
say_status "error", "Please type 'yes' or 'no'.", :red
|
72
|
+
end
|
73
|
+
answer = ask(colored_message)
|
74
|
+
end
|
67
75
|
if answer.downcase.strip !~ /^yes$/ then
|
68
76
|
if should_exit then
|
69
77
|
exit(0)
|
@@ -84,7 +92,7 @@ module CollinsShell
|
|
84
92
|
require_non_empty(success_message, "success_message not set")
|
85
93
|
require_non_empty(error_message, "error_message not set")
|
86
94
|
require_non_empty(operation, "operation not set")
|
87
|
-
selector = get_selector selector_or_tag, [],
|
95
|
+
selector = get_selector selector_or_tag, [], options[:size], options[:remote]
|
88
96
|
call_collins get_collins_client, operation do |client|
|
89
97
|
assets = client.find selector
|
90
98
|
if assets.length > 1 then
|
data/lib/collins_shell/util.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
require 'collins_shell/monkeypatch'
|
2
2
|
require 'collins_shell/util/asset_stache'
|
3
|
+
require 'open3'
|
3
4
|
|
4
5
|
module CollinsShell
|
5
6
|
module Util
|
@@ -50,13 +51,65 @@ module CollinsShell
|
|
50
51
|
selector
|
51
52
|
end
|
52
53
|
|
53
|
-
def asset_exec asset, execs, confirm = true
|
54
|
+
def asset_exec asset, execs, confirm = true, threads = 1
|
54
55
|
return unless execs
|
55
56
|
mustache = CollinsShell::Util::AssetStache.new asset
|
56
57
|
rendered = mustache.render "/bin/bash -c '#{execs}'"
|
57
58
|
say_status("exec", rendered, :red)
|
58
59
|
require_yes("Running on #{asset.tag}. ARE YOU SURE?", :red) if confirm
|
59
|
-
|
60
|
+
if threads < 2 then
|
61
|
+
system(rendered)
|
62
|
+
else
|
63
|
+
run_command_in_thread(rendered, threads)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# Should be called after asset_exec
|
68
|
+
def finalize_exec
|
69
|
+
thread_mgr.threads.each(&:join)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Wraps open threads and provides a synchronized output buffer for concurrently writing output
|
73
|
+
def thread_mgr
|
74
|
+
@_thread_mgr ||= OpenStruct.new({
|
75
|
+
:threads => [],
|
76
|
+
:lock => Mutex.new
|
77
|
+
})
|
78
|
+
end
|
79
|
+
|
80
|
+
def say_status(status, message, log_status=true)
|
81
|
+
thread_mgr.lock.synchronize {
|
82
|
+
super
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
# @param [String] syscmd The system command to execute
|
87
|
+
# @param [Fixnum] thread_count The numbers of threads to allow running at one time
|
88
|
+
def run_command_in_thread syscmd, thread_count
|
89
|
+
if thread_mgr.threads.size > thread_count then
|
90
|
+
thread_mgr.threads.each(&:join)
|
91
|
+
thread_mgr.threads.clear
|
92
|
+
else
|
93
|
+
thread_mgr.threads << Thread.new(syscmd) do |cmd|
|
94
|
+
begin
|
95
|
+
stdin, stdout, stderr, thread = Open3.popen3(cmd)
|
96
|
+
stdin.close
|
97
|
+
o, e = [stdout, stderr].map {|p| begin p.read ensure p.close end}
|
98
|
+
unless o.empty? then
|
99
|
+
say_status("stdout: #{cmd}", o, :green)
|
100
|
+
end
|
101
|
+
unless e.empty? then
|
102
|
+
say_status("stderr: #{cmd}", e, :red)
|
103
|
+
end
|
104
|
+
if thread then
|
105
|
+
Process.kill('TERM', thread.pid) rescue nil
|
106
|
+
thread.kill unless nil
|
107
|
+
end
|
108
|
+
rescue Exception => e
|
109
|
+
say_status("exception: #{cmd}", e.to_s, :red)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
60
113
|
end
|
61
114
|
|
62
115
|
def asset_get tag, options
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: collins_shell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.18
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2013-03-19 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: collins_client
|
@@ -184,7 +184,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
184
184
|
version: '0'
|
185
185
|
segments:
|
186
186
|
- 0
|
187
|
-
hash: -
|
187
|
+
hash: -4494318623502944839
|
188
188
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
189
189
|
none: false
|
190
190
|
requirements:
|