onering-client 0.0.41 → 0.0.42

Sign up to get free protection for your applications and to get access to all the features.
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