onering-client 0.0.46 → 0.0.50
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/bin/onering +31 -314
- data/lib/onering/api.rb +235 -180
- data/lib/onering/cli/automation.rb +59 -0
- data/lib/onering/cli/call.rb +36 -0
- data/lib/onering/cli/devices.rb +93 -0
- data/lib/onering/cli/fact.rb +23 -0
- data/lib/onering/cli/reporter.rb +61 -0
- data/lib/onering/cli.rb +56 -0
- data/lib/onering/plugins/authentication.rb +27 -31
- data/lib/onering/plugins/automation.rb +66 -0
- data/lib/onering/plugins/devices.rb +36 -36
- data/lib/onering/plugins/reporter.rb +6 -13
- data/lib/onering/util.rb +91 -1
- data/lib/onering.rb +7 -0
- metadata +31 -24
data/bin/onering
CHANGED
@@ -1,328 +1,45 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
|
3
|
-
#onering
|
4
|
-
# list [options] field [key:value ..]
|
5
|
-
# search [options] [key:value .. ]
|
6
|
-
# provision [options] [key:value .. ] [pxe profile | ]
|
7
|
-
|
8
|
-
|
9
|
-
require 'multi_json'
|
10
|
-
require 'rubygems'
|
11
|
-
require 'subcommander'
|
2
|
+
require 'trollop'
|
12
3
|
require 'onering'
|
13
|
-
require '
|
4
|
+
require 'hashlib'
|
14
5
|
require 'rainbow'
|
6
|
+
require 'pp'
|
15
7
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
format = :text unless format
|
8
|
+
plugins = Onering::CLI.submodules.collect{|i| i.name.split('::').last.downcase }
|
9
|
+
global = Trollop::options do
|
10
|
+
banner <<-EOS
|
11
|
+
onering command line client utility
|
21
12
|
|
22
|
-
|
23
|
-
|
24
|
-
if data.is_a?(Hash)
|
25
|
-
pp data
|
26
|
-
else
|
27
|
-
unless data.empty?
|
28
|
-
if data.is_a?(Array)
|
29
|
-
puts data.join("\n")
|
30
|
-
else
|
31
|
-
puts data.to_s
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
13
|
+
Usage:
|
14
|
+
onering [global] [plugin] [subcommand] [options]
|
35
15
|
|
36
|
-
|
37
|
-
|
38
|
-
puts YAML.dump(data)
|
16
|
+
where [global] options are:
|
17
|
+
EOS
|
39
18
|
|
40
|
-
|
41
|
-
|
42
|
-
|
19
|
+
opt :url, "The URL of the Onering server to connect to", :short => "-s", :type => :string
|
20
|
+
opt :path, "The base path to prepend to all requests (default: /api)", :type => :string
|
21
|
+
opt :format, "The output format for return values (i.e.: json, yaml, text)", :default => 'text', :short => "-t", :type => :string
|
22
|
+
opt :sslkey, "Location of the SSL client key to use for authentication", :short => "-c", :type => :string
|
23
|
+
opt :apikey, "The API token to use for authentication", :short => "-k", :type => :string
|
24
|
+
opt :quiet, "Suppress standard output", :short => '-q'
|
43
25
|
|
44
|
-
|
45
|
-
raise "Unknown output format #{format}"
|
46
|
-
end
|
26
|
+
stop_on plugins
|
47
27
|
end
|
48
28
|
|
49
|
-
begin
|
50
|
-
subcommander.version = ::Gem.loaded_specs['onering-client'].version.to_s
|
51
|
-
subcommander.desc = ::Gem.loaded_specs['onering-client'].description
|
52
|
-
|
53
|
-
|
54
|
-
subcommand :devices, "Operations related to Onering's assets database" do |devices|
|
55
|
-
api = Onering::API::Devices
|
56
|
-
api.connect({
|
57
|
-
:host => ENV['ONERING_URL'],
|
58
|
-
:pemfile => ENV['ONERING_PEM']
|
59
|
-
})
|
60
|
-
|
61
|
-
def _field(action, field, value, opts={})
|
62
|
-
rv = []
|
63
|
-
ids = []
|
64
|
-
|
65
|
-
# append IDs from filter
|
66
|
-
ids += Onering::API::Devices.list('id', {
|
67
|
-
:filter => opts[:filter]
|
68
|
-
}) if opts[:filter]
|
69
|
-
|
70
|
-
# add specific ID
|
71
|
-
ids << opts[:id] if opts[:id]
|
72
|
-
|
73
|
-
ids.each do |id|
|
74
|
-
case action
|
75
|
-
when :get
|
76
|
-
rv << Onering::API::Devices.get_field(id, field)
|
77
|
-
when :set
|
78
|
-
rv << Onering::API::Devices.set_field(id, field, value)
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
|
-
rv
|
83
|
-
end
|
84
|
-
|
85
|
-
# SHOW
|
86
|
-
devices.subcommand :show, "Print out a single node by ID" do |sc|
|
87
|
-
sc.usage = "onering devices show ID"
|
88
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
89
|
-
|
90
|
-
sc.exec do
|
91
|
-
id = sc[:args].first
|
92
|
-
print_format(api.get(id), sc[:format])
|
93
|
-
end
|
94
|
-
end
|
95
|
-
|
96
|
-
# GET [FIELD]
|
97
|
-
devices.subcommand :get, "Get a named field from one or more devices" do |sc|
|
98
|
-
sc.usage = "onering devices get FIELD"
|
99
|
-
sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
|
100
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
101
|
-
sc.opt :id, '-i', '--id ID', "A specific node ID"
|
102
|
-
|
103
|
-
|
104
|
-
sc.exec do
|
105
|
-
rv = _field(:get, sc[:args].first, nil, sc)
|
106
|
-
print_format(rv, sc[:format])
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
|
-
# SET [FIELD]
|
111
|
-
devices.subcommand :set, "Set a named field for one or more devices" do |sc|
|
112
|
-
sc.usage = "onering devices set FIELD VALUE"
|
113
|
-
sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
|
114
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
115
|
-
sc.opt :id, '-i', '--id ID', "A specific node ID"
|
116
|
-
|
117
|
-
sc.exec do
|
118
|
-
rv = _field(:set, sc[:args].first, sc[:args][1], sc)
|
119
|
-
print_format(rv, sc[:format])
|
120
|
-
end
|
121
|
-
end
|
122
|
-
|
123
|
-
# LIST
|
124
|
-
devices.subcommand :list, "List field values" do |sc|
|
125
|
-
sc.usage = "onering devices list [-f FILTER] FIELD"
|
126
|
-
sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
|
127
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
128
|
-
|
129
|
-
sc.exec do
|
130
|
-
field = sc[:args].first
|
131
|
-
filter = sc[:filter]
|
132
|
-
|
133
|
-
print_format(api.list(field, {
|
134
|
-
:filter => filter
|
135
|
-
}), sc[:format])
|
136
|
-
end
|
137
|
-
end
|
138
|
-
|
139
|
-
# FIND
|
140
|
-
devices.subcommand :find, "Finds all nodes that match a urlquery filter string" do |sc|
|
141
|
-
sc.arity = 1
|
142
|
-
sc.usage = "onering devices find FILTER"
|
143
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
144
|
-
|
145
|
-
sc.exec do
|
146
|
-
print_format(api.find(sc[:args].first), sc[:format])
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
# SAVE
|
151
|
-
devices.subcommand :save, "Creates or updates a new device in Onering, reading a JSON document from standard input" do |sc|
|
152
|
-
sc.usage = "onering report | onering devices save [ID]"
|
153
|
-
|
154
|
-
sc.exec do
|
155
|
-
unless STDIN.tty?
|
156
|
-
begin
|
157
|
-
json = ::MultiJson.load(STDIN.read)
|
158
|
-
raise "Input document must specify an ID" if sc[:args].empty? and not json['id']
|
159
|
-
|
160
|
-
rv = api.save((sc[:args].first || json['id']), json)
|
161
|
-
print_format(rv, :json) if rv
|
162
|
-
rescue Exception => e
|
163
|
-
STDERR.puts "#{e.class.name}: #{e.message}"
|
164
|
-
exit 1
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
|
172
|
-
subcommand :users, "Manage Onering users" do |users|
|
173
|
-
api = Onering::API::Auth
|
174
|
-
api.connect({
|
175
|
-
:host => ENV['ONERING_URL'],
|
176
|
-
:pemfile => ENV['ONERING_PEM']
|
177
|
-
})
|
178
29
|
|
179
|
-
|
180
|
-
|
181
|
-
sc.usage = "onering users show ID"
|
30
|
+
plugin = ARGV.shift
|
31
|
+
Trollop::die("plugin argument is requried") if plugin.nil?
|
182
32
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
193
|
-
|
194
|
-
sc.exec do
|
195
|
-
field = sc[:args].first
|
196
|
-
filter = sc[:filter]
|
197
|
-
|
198
|
-
print_format(api.list(:users, field, {
|
199
|
-
:filter => filter
|
200
|
-
}), sc[:format])
|
201
|
-
end
|
202
|
-
end
|
203
|
-
|
204
|
-
# SAVE
|
205
|
-
users.subcommand :save, "Creates or updates a new device in Onering, reading a JSON document from standard input" do |sc|
|
206
|
-
sc.usage = "cat user.json | onering users save [ID]"
|
207
|
-
|
208
|
-
sc.exec do
|
209
|
-
unless STDIN.tty?
|
210
|
-
begin
|
211
|
-
json = ::MultiJson.load(STDIN.read)
|
212
|
-
raise "Input document must specify an ID" if sc[:args].empty? and not json['id']
|
213
|
-
|
214
|
-
print_format(api.save((sc[:args].first || json['id']), json))
|
215
|
-
rescue Exception => e
|
216
|
-
STDERR.puts "#{e.class.name}: #{e.message}"
|
217
|
-
exit 1
|
218
|
-
end
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
33
|
+
if plugins.include?(plugin)
|
34
|
+
begin
|
35
|
+
plugin = Onering::CLI.const_get(plugin.capitalize)
|
36
|
+
plugin.configure(global)
|
37
|
+
rv = plugin.run(ARGV)
|
38
|
+
Onering::CLI.output(rv, global[:format])
|
39
|
+
rescue Onering::API::Errors::Exception => e
|
40
|
+
STDERR.puts("[#{e.class.name.split('::').last}]".foreground(:red) + " #{e.message}")
|
41
|
+
exit 1
|
222
42
|
end
|
223
|
-
|
224
|
-
|
225
|
-
api = Onering::API::Base
|
226
|
-
api.connect({
|
227
|
-
:host => ENV['ONERING_URL'],
|
228
|
-
:pemfile => ENV['ONERING_PEM']
|
229
|
-
})
|
230
|
-
|
231
|
-
call.usage = "onering call path/to/endpoint"
|
232
|
-
call.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
233
|
-
call.opt :method, '-m', '--method VERB', "The HTTP method to use for the call (default: GET)"
|
234
|
-
call.opt :opts, '-o', '--option KEY:VALUE', Array, "A comma-separated list of key:value querystrings to pass with the request"
|
235
|
-
|
236
|
-
call.exec do
|
237
|
-
rv = api.request(call[:args].first.to_sym, {
|
238
|
-
:method => (call[:method] || :get),
|
239
|
-
:data => (STDIN.tty? ? {} : ::MultiJson.load(STDIN.read) rescue {}),
|
240
|
-
:fields => (Hash[call[:opts].collect{|i| i.split(':',2) }] rescue {})
|
241
|
-
})
|
242
|
-
|
243
|
-
print_format(rv, call[:format] || :json) unless rv.nil? or rv.to_s.strip.chomp.empty?
|
244
|
-
end
|
245
|
-
end
|
246
|
-
|
247
|
-
subcommand :fact, "Retrieve a system fact" do |fact|
|
248
|
-
fact.usage = "onering fact NAME [DEFAULT] [NAME2 [DEFAULT2] ..]"
|
249
|
-
fact.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
|
250
|
-
|
251
|
-
fact.exec do
|
252
|
-
Onering::Reporter.setup()
|
253
|
-
rv = []
|
254
|
-
|
255
|
-
fact[:args].each_index do |i|
|
256
|
-
if i.even?
|
257
|
-
name = fact[:args][i]
|
258
|
-
else
|
259
|
-
default = fact[:args][i]
|
260
|
-
end
|
261
|
-
|
262
|
-
rv << Onering::Reporter.fact(name, default)
|
263
|
-
end
|
264
|
-
|
265
|
-
rv.compact!
|
266
|
-
rv = rv.first if rv.length == 1
|
267
|
-
|
268
|
-
print_format(rv, fact[:format]) unless rv.nil? or rv.to_s.empty?
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
|
273
|
-
subcommand :report, "Collect and output system information" do |report|
|
274
|
-
report.usage = "onering report"
|
275
|
-
report.opt :plugin_path, '-p', '--plugin PATH', 'Add the named path to the plugin search path'
|
276
|
-
report.opt :status, '-S', '--status STATUS', 'Set the status to report'
|
277
|
-
report.opt :tags, '-T', '--tag TAG[,...]', 'Add a tag to the report output'
|
278
|
-
report.opt :aliases, '-A', '--alias ALIAS[,...]', 'Add a alias to the report output'
|
279
|
-
report.opt :id, '-I', '--id ID', 'Override the auto-detected hardware ID'
|
280
|
-
report.opt :format, '-t', '--format FORMAT', 'Format the output'
|
281
|
-
|
282
|
-
report.exec do
|
283
|
-
config = {}
|
284
|
-
%w{
|
285
|
-
plugin_path
|
286
|
-
status
|
287
|
-
tags
|
288
|
-
aliases
|
289
|
-
id
|
290
|
-
}.each do |a|
|
291
|
-
a = a.to_sym
|
292
|
-
next if report[a].nil?
|
293
|
-
|
294
|
-
if [:tags, :aliases].include?(a)
|
295
|
-
config[a] = report[a].split(',')
|
296
|
-
else
|
297
|
-
config[a] = report[a]
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
Onering::Reporter.setup(config)
|
302
|
-
|
303
|
-
rv = Onering::Reporter.report()
|
304
|
-
print_format(rv, report[:format] || :json) unless rv.nil?
|
305
|
-
end
|
306
|
-
end
|
307
|
-
|
308
|
-
|
309
|
-
subcommander.go!
|
310
|
-
|
311
|
-
rescue SystemExit
|
312
|
-
exit 0
|
313
|
-
|
314
|
-
rescue Interrupt
|
315
|
-
exit 127
|
316
|
-
|
317
|
-
rescue Onering::API::Errors::ClientError => e
|
318
|
-
STDERR.puts("#{e.message}".foreground(:red))
|
319
|
-
exit 1
|
320
|
-
|
321
|
-
rescue Exception => e
|
322
|
-
STDERR.puts("#{e.class.name}: #{e.message}".foreground(:red))
|
323
|
-
e.backtrace.each do |b|
|
324
|
-
STDERR.puts(" #{b}")
|
325
|
-
end
|
326
|
-
|
327
|
-
exit 1
|
43
|
+
else
|
44
|
+
Trollop::die("unknown plugin #{plugin}")
|
328
45
|
end
|