onering-client 0.0.41 → 0.0.42

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.
Files changed (3) hide show
  1. data/bin/onering +218 -199
  2. data/lib/onering/api.rb +123 -44
  3. metadata +26 -34
data/bin/onering CHANGED
@@ -11,6 +11,7 @@ require 'rubygems'
11
11
  require 'subcommander'
12
12
  require 'onering'
13
13
  require 'pp'
14
+ require 'rainbow'
14
15
 
15
16
  include Subcommander
16
17
 
@@ -22,10 +23,14 @@ def print_format(data, format=nil)
22
23
  when :text
23
24
  if data.is_a?(Hash)
24
25
  pp data
25
- elsif data.is_a?(Array)
26
- puts data.join("\n")
27
26
  else
28
- puts data.to_s
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
29
34
  end
30
35
 
31
36
  when :yaml
@@ -41,262 +46,276 @@ def print_format(data, format=nil)
41
46
  end
42
47
  end
43
48
 
44
- subcommander.version = ::Gem.loaded_specs['onering-client'].version.to_s
45
- subcommander.desc = ::Gem.loaded_specs['onering-client'].description
49
+ begin
50
+ subcommander.version = ::Gem.loaded_specs['onering-client'].version.to_s
51
+ subcommander.desc = ::Gem.loaded_specs['onering-client'].description
46
52
 
47
53
 
48
- subcommand :devices, "Operations related to Onering's assets database" do |devices|
49
- api = Onering::API::Devices
50
- api.connect({
51
- :host => ENV['ONERING_URL'],
52
- :pemfile => ENV['ONERING_PEM']
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
+ })
54
60
 
55
- def _field(action, field, value, opts={})
56
- rv = []
57
- ids = []
61
+ def _field(action, field, value, opts={})
62
+ rv = []
63
+ ids = []
58
64
 
59
- # append IDs from filter
60
- ids += Onering::API::Devices.list('id', {
61
- :filter => opts[:filter]
62
- }) if opts[:filter]
65
+ # append IDs from filter
66
+ ids += Onering::API::Devices.list('id', {
67
+ :filter => opts[:filter]
68
+ }) if opts[:filter]
63
69
 
64
- # add specific ID
65
- ids << opts[:id] if opts[:id]
70
+ # add specific ID
71
+ ids << opts[:id] if opts[:id]
66
72
 
67
- ids.each do |id|
68
- case action
69
- when :get
70
- rv << Onering::API::Devices.get_field(id, field)
71
- when :set
72
- rv << Onering::API::Devices.set_field(id, field, value)
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
73
80
  end
74
- end
75
81
 
76
- rv
77
- end
82
+ rv
83
+ end
78
84
 
79
- # SHOW
80
- devices.subcommand :show, "Print out a single node by ID" do |sc|
81
- sc.usage = "onering devices show ID"
82
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
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"
83
89
 
84
- sc.exec do
85
- id = sc[:args].first
86
- print_format(api.get(id), sc[:format])
90
+ sc.exec do
91
+ id = sc[:args].first
92
+ print_format(api.get(id), sc[:format])
93
+ end
87
94
  end
88
- end
89
95
 
90
- # GET [FIELD]
91
- devices.subcommand :get, "Get a named field from one or more devices" do |sc|
92
- sc.usage = "onering devices get FIELD"
93
- sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
94
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
95
- sc.opt :id, '-i', '--id ID', "A specific node ID"
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"
96
102
 
97
103
 
98
- sc.exec do
99
- rv = _field(:get, sc[:args].first, nil, sc)
100
- print_format(rv, sc[:format])
104
+ sc.exec do
105
+ rv = _field(:get, sc[:args].first, nil, sc)
106
+ print_format(rv, sc[:format])
107
+ end
101
108
  end
102
- end
103
109
 
104
- # SET [FIELD]
105
- devices.subcommand :set, "Set a named field for one or more devices" do |sc|
106
- sc.usage = "onering devices set FIELD VALUE"
107
- sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
108
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
109
- sc.opt :id, '-i', '--id ID', "A specific node ID"
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"
110
116
 
111
- sc.exec do
112
- rv = _field(:set, sc[:args].first, sc[:args][1], sc)
113
- print_format(rv, sc[:format])
117
+ sc.exec do
118
+ rv = _field(:set, sc[:args].first, sc[:args][1], sc)
119
+ print_format(rv, sc[:format])
120
+ end
114
121
  end
115
- end
116
122
 
117
- # LIST
118
- devices.subcommand :list, "List field values" do |sc|
119
- sc.usage = "onering devices list [-f FILTER] FIELD"
120
- sc.opt :filter, '-f', '--filter FILTER', "A urlquery filter string"
121
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
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"
122
128
 
123
- sc.exec do
124
- field = sc[:args].first
125
- filter = sc[:filter]
129
+ sc.exec do
130
+ field = sc[:args].first
131
+ filter = sc[:filter]
126
132
 
127
- print_format(api.list(field, {
128
- :filter => filter
129
- }), sc[:format])
133
+ print_format(api.list(field, {
134
+ :filter => filter
135
+ }), sc[:format])
136
+ end
130
137
  end
131
- end
132
138
 
133
- # FIND
134
- devices.subcommand :find, "Finds all nodes that match a urlquery filter string" do |sc|
135
- sc.arity = 1
136
- sc.usage = "onering devices find FILTER"
137
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
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"
138
144
 
139
- sc.exec do
140
- print_format(api.find(sc[:args].first), sc[:format])
145
+ sc.exec do
146
+ print_format(api.find(sc[:args].first), sc[:format])
147
+ end
141
148
  end
142
- end
143
149
 
144
- # SAVE
145
- devices.subcommand :save, "Creates or updates a new device in Onering, reading a JSON document from standard input" do |sc|
146
- sc.usage = "onering report | onering devices save [ID]"
147
-
148
- sc.exec do
149
- unless STDIN.tty?
150
- begin
151
- json = ::MultiJson.load(STDIN.read)
152
- raise "Input document must specify an ID" if sc[:args].empty? and not json['id']
153
-
154
- rv = api.save((sc[:args].first || json['id']), json)
155
- print_format(rv, :json) if rv
156
- rescue Exception => e
157
- STDERR.puts "#{e.class.name}: #{e.message}"
158
- exit 1
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
159
166
  end
160
167
  end
161
168
  end
162
169
  end
163
- end
164
170
 
165
171
 
166
- subcommand :users, "Manage Onering users" do |users|
167
- api = Onering::API::Auth
168
- api.connect({
169
- :host => ENV['ONERING_URL'],
170
- :pemfile => ENV['ONERING_PEM']
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
+ })
172
178
 
173
- # SHOW
174
- users.subcommand :show, "Print out a single user by ID" do |sc|
175
- sc.usage = "onering users show ID"
179
+ # SHOW
180
+ users.subcommand :show, "Print out a single user by ID" do |sc|
181
+ sc.usage = "onering users show ID"
176
182
 
177
- sc.exec do
178
- id = sc[:args].first
179
- print_format(api.get(:users, id))
183
+ sc.exec do
184
+ id = sc[:args].first
185
+ print_format(api.get(:users, id))
186
+ end
180
187
  end
181
- end
182
188
 
183
- # LIST
184
- users.subcommand :list, "List users" do |sc|
185
- sc.usage = "onering users list FIELD"
186
- sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
189
+ # LIST
190
+ users.subcommand :list, "List users" do |sc|
191
+ sc.usage = "onering users list FIELD"
192
+ sc.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
187
193
 
188
- sc.exec do
189
- field = sc[:args].first
190
- filter = sc[:filter]
194
+ sc.exec do
195
+ field = sc[:args].first
196
+ filter = sc[:filter]
191
197
 
192
- print_format(api.list(:users, field, {
193
- :filter => filter
194
- }), sc[:format])
198
+ print_format(api.list(:users, field, {
199
+ :filter => filter
200
+ }), sc[:format])
201
+ end
195
202
  end
196
- end
197
-
198
- # SAVE
199
- users.subcommand :save, "Creates or updates a new device in Onering, reading a JSON document from standard input" do |sc|
200
- sc.usage = "cat user.json | onering users save [ID]"
201
203
 
202
- sc.exec do
203
- unless STDIN.tty?
204
- begin
205
- json = ::MultiJson.load(STDIN.read)
206
- raise "Input document must specify an ID" if sc[:args].empty? and not json['id']
207
-
208
- print_format(api.save((sc[:args].first || json['id']), json))
209
- rescue Exception => e
210
- STDERR.puts "#{e.class.name}: #{e.message}"
211
- exit 1
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
212
219
  end
213
220
  end
214
221
  end
215
222
  end
216
- end
217
223
 
218
- subcommand :call, "Call generic Onering API endpoints" do |call|
219
- api = Onering::API::Base
220
- api.connect({
221
- :host => ENV['ONERING_URL'],
222
- :pemfile => ENV['ONERING_PEM']
223
- })
224
-
225
- call.usage = "onering call path/to/endpoint"
226
- call.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
227
- call.opt :method, '-m', '--method VERB', "The HTTP method to use for the call (default: GET)"
228
- call.opt :opts, '-o', '--option KEY:VALUE', Array, "A comma-separated list of key:value querystrings to pass with the request"
229
-
230
- call.exec do
231
- rv = api.request(call[:args].first.to_sym, {
232
- :method => (call[:method] || :get),
233
- :data => (STDIN.tty? ? {} : ::MultiJson.load(STDIN.read)),
234
- :fields => (Hash[call[:opts].collect{|i| i.split(':',2) }] rescue {})
224
+ subcommand :call, "Call generic Onering API endpoints" do |call|
225
+ api = Onering::API::Base
226
+ api.connect({
227
+ :host => ENV['ONERING_URL'],
228
+ :pemfile => ENV['ONERING_PEM']
235
229
  })
236
230
 
237
- print_format(rv, call[:format] || :json) unless rv.nil? or rv.to_s.strip.chomp.empty?
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)),
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
238
245
  end
239
- end
240
246
 
241
- subcommand :fact, "Retrieve a system fact" do |fact|
242
- fact.usage = "onering fact NAME [DEFAULT] [NAME2 [DEFAULT2] ..]"
243
- fact.opt :format, '-t', '--format FORMAT', "Return the results as FORMAT"
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"
244
250
 
245
- fact.exec do
246
- Onering::Reporter.setup()
247
- rv = []
251
+ fact.exec do
252
+ Onering::Reporter.setup()
253
+ rv = []
248
254
 
249
- fact[:args].each_index do |i|
250
- if i.even?
251
- name = fact[:args][i]
252
- else
253
- default = fact[:args][i]
254
- end
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
255
261
 
256
- rv << Onering::Reporter.fact(name, default)
257
- end
262
+ rv << Onering::Reporter.fact(name, default)
263
+ end
258
264
 
259
- rv.compact!
260
- rv = rv.first if rv.length == 1
265
+ rv.compact!
266
+ rv = rv.first if rv.length == 1
261
267
 
262
- print_format(rv, fact[:format]) unless rv.nil? or rv.to_s.empty?
268
+ print_format(rv, fact[:format]) unless rv.nil? or rv.to_s.empty?
269
+ end
263
270
  end
264
- end
265
271
 
266
272
 
267
- subcommand :report, "Collect and output system information" do |report|
268
- report.usage = "onering report"
269
- report.opt :plugin_path, '-p', '--plugin PATH', 'Add the named path to the plugin search path'
270
- report.opt :status, '-S', '--status STATUS', 'Set the status to report'
271
- report.opt :tags, '-T', '--tag TAG[,...]', 'Add a tag to the report output'
272
- report.opt :aliases, '-A', '--alias ALIAS[,...]', 'Add a alias to the report output'
273
- report.opt :id, '-I', '--id ID', 'Override the auto-detected hardware ID'
274
- report.opt :format, '-t', '--format FORMAT', 'Format the output'
275
-
276
- report.exec do
277
- config = {}
278
- %w{
279
- plugin_path
280
- status
281
- tags
282
- aliases
283
- id
284
- }.each do |a|
285
- a = a.to_sym
286
- next if report[a].nil?
287
-
288
- if [:tags, :aliases].include?(a)
289
- config[a] = report[a].split(',')
290
- else
291
- config[a] = report[a]
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
292
299
  end
300
+
301
+ Onering::Reporter.setup(config)
302
+
303
+ rv = Onering::Reporter.report()
304
+ print_format(rv, report[:format] || :json) unless rv.nil?
293
305
  end
306
+ end
294
307
 
295
- Onering::Reporter.setup(config)
296
308
 
297
- rv = Onering::Reporter.report()
298
- print_format(rv, report[:format] || :json) unless rv.nil?
309
+ subcommander.go!
310
+ rescue Onering::API::Errors::ClientError => e
311
+ STDERR.puts("#{e.message}".foreground(:red))
312
+ exit 1
313
+
314
+ rescue Exception => e
315
+ STDERR.puts("#{e.class.name}: #{e.message}".foreground(:red))
316
+ e.backtrace.each do |b|
317
+ STDERR.puts(" #{b}")
299
318
  end
300
- end
301
319
 
302
- subcommander.go!
320
+ exit 1
321
+ end
data/lib/onering/api.rb CHANGED
@@ -1,4 +1,4 @@
1
- require 'net/https'
1
+ require 'rest_client'
2
2
  require 'uri'
3
3
  require 'multi_json'
4
4
  require 'yaml'
@@ -12,6 +12,7 @@ module Onering
12
12
  class ClientError < Exception; end
13
13
  class ServerError < Exception; end
14
14
  class ConnectionTimeout < Exception; end
15
+ class ClientPemNotFound < Exception; end
15
16
  end
16
17
 
17
18
  class Base
@@ -29,6 +30,10 @@ module Onering
29
30
  "/etc/onering/client.pem"
30
31
  ]
31
32
 
33
+ DEFAULT_VALIDATION_PEM=[
34
+ "/etc/onering/validation.pem"
35
+ ]
36
+
32
37
  class<<self
33
38
  def connect(options={})
34
39
  # list all existing config files from least specific to most
@@ -51,21 +56,100 @@ module Onering
51
56
  @_uri = Addressable::URI.parse("#{@_config['url'] || DEFAULT_BASE}/#{@_config['apiroot'] || DEFAULT_PATH}")
52
57
  end
53
58
 
54
- if @_uri
55
- @_pemfile = ([options[:pemfile], @_config['pemfile']]+DEFAULT_CLIENT_PEM).compact.select{|i|
56
- (File.exists?(File.expand_path(i)) rescue false)
57
- }.first
58
-
59
- if @_pemfile
60
- @_pem = File.read(File.expand_path(@_pemfile))
61
- @_http = Net::HTTP.new(@_uri.host, (@_uri.port || 443))
62
- @_http.open_timeout = 30
63
- @_http.read_timeout = 120
64
- @_http.use_ssl = true
65
- @_http.cert = OpenSSL::X509::Certificate.new(@_pem)
66
- @_http.key = OpenSSL::PKey::RSA.new(@_pem)
67
- @_http.verify_mode = OpenSSL::SSL::VERIFY_NONE
59
+ unless @_uri.nil?
60
+ begin
61
+ @_pemfile = ([options[:pemfile], @_config['pemfile']]+DEFAULT_CLIENT_PEM).compact.select{|i|
62
+ (File.exists?((File.expand_path(i) rescue i)) rescue nil)
63
+ }.compact.first
64
+
65
+ raise Errors::ClientPemNotFound if @_pemfile.nil?
66
+
67
+ @_pem = File.read((File.expand_path(@_pemfile) rescue @_pemfile))
68
+
69
+ @rest = RestClient::Resource.new("#{@_uri.scheme}://#{@_uri.host}:#{@_uri.port || 443}", {
70
+ :timeout => 120,
71
+ :open_timeout => 30,
72
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(@_pem),
73
+ :ssl_client_key => OpenSSL::PKey::RSA.new(@_pem),
74
+ :verify_peer => OpenSSL::SSL::VERIFY_PEER
75
+ })
76
+
77
+ rescue Errors::ClientPemNotFound
78
+ # client PEM not present, attempt autoregistration
79
+ STDERR.puts("Onering client.pem not found, attempting automatic registration...")
80
+
81
+ @_validation = ([options[:validationfile], @_config['validationfile']]+DEFAULT_VALIDATION_PEM).compact.select{|i|
82
+ (File.exists?((File.expand_path(i) rescue i)) rescue nil)
83
+ }.compact.first
84
+
85
+ if @_validation.nil?
86
+ raise Errors::ClientError.new("Cannot automatically register client, cannot find validation.pem")
87
+ end
88
+
89
+ @_validation = File.read(@_validation)
90
+
91
+ @rest = RestClient::Resource.new("#{@_uri.scheme}://#{@_uri.host}:#{@_uri.port || 443}", {
92
+ :timeout => 120,
93
+ :open_timeout => 30,
94
+ :ssl_client_cert => OpenSSL::X509::Certificate.new(@_validation),
95
+ :ssl_client_key => OpenSSL::PKey::RSA.new(@_validation),
96
+ :verify_peer => OpenSSL::SSL::VERIFY_PEER
97
+ })
98
+
99
+
100
+ clients = [{
101
+ :path => "/etc/onering",
102
+ :name => (@_config['id'] || File.read("/etc/hardware.id")).strip.chomp,
103
+ :keyname => 'system',
104
+ :autodelete => true
105
+ },{
106
+ :path => "~/.onering",
107
+ :name => ENV['USER'],
108
+ :keyname => 'cli',
109
+ :autodelete => false
110
+ }]
111
+
112
+ # attempt to autoregister clients from least specific to most (machine account then user account)
113
+ clients.each do |client|
114
+ # determine if we can create this client
115
+ client[:path] = (File.expand_path(client[:path]) rescue client[:path])
116
+ next unless File.writable?(File.dirname(client[:path]))
117
+ File.mkdir(client[:path]) unless File.directory?(client[:path])
118
+ next unless File.writable?(client[:path])
119
+
120
+ begin
121
+ response = @rest["/api/users/#{client[:name]}/keys/#{client[:keyname]}"].get({
122
+ :params => {
123
+ :cert => 'pem',
124
+ :autodelete => client[:autodelete]
125
+ }
126
+ })
127
+
128
+ rescue RestClient::Forbidden
129
+ STDERR.puts("Cannot re-download key '#{client[:keyname]}' for client #{client[:name]}. Please remove the client key from Onering and try again.")
130
+ next
131
+
132
+ rescue RestClient::Exception => e
133
+ raise Errors::ClientError.new("HTTP #{e.http_code}: #{e.message}")
134
+ end
135
+
136
+
137
+ File.open("#{client[:path]}/client.pem", "w") do |file|
138
+ file.puts(response.to_str)
139
+ STDERR.puts("Successfully registered client key #{client[:name]}:#{client[:keyname]}, key is at #{file.path}")
140
+ break
141
+ end
142
+ end
143
+
144
+ if clients.select{|i| p = "#{i[:path]}/client.pem"; File.exists?((File.expand_path(p) rescue p)) }.empty?
145
+ raise Errors::ClientError.new("Unable to register a Onering client.")
146
+ end
147
+
148
+ retry
68
149
  end
150
+
151
+ else
152
+ raise Errors::ClientError.new("Could not parse API URL.")
69
153
  end
70
154
  end
71
155
 
@@ -77,42 +161,37 @@ module Onering
77
161
  uri = Addressable::URI.parse("#{@_uri.to_s}/#{endpoint}")
78
162
  uri.query_values = options[:fields] if options[:fields]
79
163
 
80
- raise Errors::NotConnected unless @_http
164
+ raise Errors::NotConnected unless @rest
81
165
 
82
- case options[:method]
83
- when :post
84
- request = Net::HTTP::Post.new(uri.request_uri)
85
- request['Content-Type'] = 'application/json'
86
- request.body = MultiJson.dump(options[:data]) if options[:data]
166
+ begin
167
+ case options[:method]
168
+ when :post
169
+ data = (options[:data].nil? ? nil : MultiJson.dump(options[:data]))
87
170
 
88
- when :delete
89
- request = Net::HTTP::Delete.new(uri.request_uri)
171
+ response = @rest[uri.request_uri].post(data, {
172
+ :content_type => 'application/json'
173
+ })
90
174
 
91
- else
92
- request = Net::HTTP::Get.new(uri.request_uri)
93
-
94
- end
175
+ when :delete
176
+ response = @rest[uri.request_uri].delete()
95
177
 
96
- response = @_http.request(request)
178
+ when :head
179
+ response = @rest[uri.request_uri].head()
180
+ else
181
+ response = @rest[uri.request_uri].get()
182
+ end
97
183
 
98
- if response.code.to_i >= 400
99
- rv = (MultiJson.load(response.body) rescue {}) unless response.body.empty?
184
+ rescue RestClient::Unauthorized => e
185
+ raise Errors::ClientError.new("You are not authorized to perform this request")
100
186
 
101
- if rv['errors']
102
- msg = "#{rv['errors']['type']}: #{rv['errors']['message']}"
103
- end
187
+ rescue RestClient::Exception => e
188
+ raise Errors::ClientError.new("(HTTP #{e.http_code}) #{e.class.name}: #{e.message}")
189
+ end
104
190
 
105
- if response.code.to_i >= 500
106
- raise Errors::ServerError.new("HTTP #{response.code}: #{msg}")
107
- else
108
- raise Errors::ClientError.new("HTTP #{response.code}: #{msg}")
109
- end
110
- else
111
- if response['Content-Type'] == 'application/json'
112
- rv = (response.body.empty? ? nil : MultiJson.load(response.body))
113
- else
114
- rv = response.body
115
- end
191
+ begin
192
+ rv = (response.empty? ? nil : MultiJson.load(response))
193
+ rescue Exception
194
+ rv = response
116
195
  end
117
196
 
118
197
  rv
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: onering-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.41
4
+ version: 0.0.42
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,7 +13,7 @@ date: 2013-01-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: facter
16
- requirement: !ruby/object:Gem::Requirement
16
+ requirement: &13381180 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,15 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ! '>='
28
- - !ruby/object:Gem::Version
29
- version: '0'
24
+ version_requirements: *13381180
30
25
  - !ruby/object:Gem::Dependency
31
26
  name: subcommander
32
- requirement: !ruby/object:Gem::Requirement
27
+ requirement: &13380420 !ruby/object:Gem::Requirement
33
28
  none: false
34
29
  requirements:
35
30
  - - ! '>='
@@ -37,15 +32,10 @@ dependencies:
37
32
  version: '0'
38
33
  type: :runtime
39
34
  prerelease: false
40
- version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ! '>='
44
- - !ruby/object:Gem::Version
45
- version: '0'
35
+ version_requirements: *13380420
46
36
  - !ruby/object:Gem::Dependency
47
37
  name: deep_merge
48
- requirement: !ruby/object:Gem::Requirement
38
+ requirement: &13379480 !ruby/object:Gem::Requirement
49
39
  none: false
50
40
  requirements:
51
41
  - - ! '>='
@@ -53,15 +43,10 @@ dependencies:
53
43
  version: '0'
54
44
  type: :runtime
55
45
  prerelease: false
56
- version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
- requirements:
59
- - - ! '>='
60
- - !ruby/object:Gem::Version
61
- version: '0'
46
+ version_requirements: *13379480
62
47
  - !ruby/object:Gem::Dependency
63
48
  name: addressable
64
- requirement: !ruby/object:Gem::Requirement
49
+ requirement: &13379020 !ruby/object:Gem::Requirement
65
50
  none: false
66
51
  requirements:
67
52
  - - ! '>='
@@ -69,15 +54,21 @@ dependencies:
69
54
  version: '0'
70
55
  type: :runtime
71
56
  prerelease: false
72
- version_requirements: !ruby/object:Gem::Requirement
57
+ version_requirements: *13379020
58
+ - !ruby/object:Gem::Dependency
59
+ name: rest-client
60
+ requirement: &13378480 !ruby/object:Gem::Requirement
73
61
  none: false
74
62
  requirements:
75
63
  - - ! '>='
76
64
  - !ruby/object:Gem::Version
77
65
  version: '0'
66
+ type: :runtime
67
+ prerelease: false
68
+ version_requirements: *13378480
78
69
  - !ruby/object:Gem::Dependency
79
70
  name: hashlib
80
- requirement: !ruby/object:Gem::Requirement
71
+ requirement: &13378080 !ruby/object:Gem::Requirement
81
72
  none: false
82
73
  requirements:
83
74
  - - ! '>='
@@ -85,15 +76,10 @@ dependencies:
85
76
  version: '0'
86
77
  type: :runtime
87
78
  prerelease: false
88
- version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
- requirements:
91
- - - ! '>='
92
- - !ruby/object:Gem::Version
93
- version: '0'
79
+ version_requirements: *13378080
94
80
  - !ruby/object:Gem::Dependency
95
81
  name: multi_json
96
- requirement: !ruby/object:Gem::Requirement
82
+ requirement: &13377540 !ruby/object:Gem::Requirement
97
83
  none: false
98
84
  requirements:
99
85
  - - ! '>='
@@ -101,12 +87,18 @@ dependencies:
101
87
  version: '0'
102
88
  type: :runtime
103
89
  prerelease: false
104
- version_requirements: !ruby/object:Gem::Requirement
90
+ version_requirements: *13377540
91
+ - !ruby/object:Gem::Dependency
92
+ name: rainbow
93
+ requirement: &13377020 !ruby/object:Gem::Requirement
105
94
  none: false
106
95
  requirements:
107
96
  - - ! '>='
108
97
  - !ruby/object:Gem::Version
109
98
  version: '0'
99
+ type: :runtime
100
+ prerelease: false
101
+ version_requirements: *13377020
110
102
  description: A Ruby wrapper for Onering
111
103
  email: ghetzel@outbrain.com
112
104
  executables:
@@ -141,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
141
133
  version: '0'
142
134
  requirements: []
143
135
  rubyforge_project:
144
- rubygems_version: 1.8.23
136
+ rubygems_version: 1.8.11
145
137
  signing_key:
146
138
  specification_version: 3
147
139
  summary: Onering client API and utilities