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.
@@ -0,0 +1,61 @@
1
+ module Onering
2
+ module CLI
3
+ module Report
4
+ def self.configure(global={})
5
+ @api = (Onering::CLI.connect(global.merge({
6
+ :autoconnect => false
7
+ })) rescue nil)
8
+ @opts = ::Trollop::options do
9
+ banner <<-EOS
10
+ Generate a system report that can be saved or submitted to a Onering server
11
+
12
+ Usage:
13
+ onering [global] report [options]
14
+
15
+ Options:
16
+ EOS
17
+ opt :id, "Override the autodetected Hardware ID for this node", :short => '-I', :type => :string
18
+ opt :fields, "Set the named FIELD to equal VALUE in the format FIELD=VALUE. Can be specified multiple times", :short => '-o', :type => :string, :multi => true
19
+ opt :save, "Save the report output to the configured Onering server"
20
+ end
21
+
22
+ # initialize report generator with user options
23
+ Onering::Reporter.setup({
24
+ :id => @opts[:id]
25
+ }.compact)
26
+ end
27
+
28
+ def self.run(args)
29
+ report = Onering::Reporter.report().stringify_keys()
30
+
31
+ # pull report overrides from the config file
32
+ @api.opt('reporter.fields',{}).each do |field, value|
33
+ if value.is_a?(Hash)
34
+ value.coalesce(field, nil, '.').each do |k,v|
35
+ report = report.set(k, v)
36
+ end
37
+ else
38
+ report = report.set(field, value)
39
+ end
40
+ end
41
+
42
+ # pull overrides from CLI arguments
43
+ @opts[:fields].each do |field|
44
+ key, value = field.split('=', 2)
45
+ report = report.set(key, value)
46
+ end
47
+
48
+
49
+ # save if specified
50
+ if @opts[:save] === true
51
+ @api.connect()
52
+ @api.devices.save(report['id']) do
53
+ MultiJson.dump(report)
54
+ end
55
+ end
56
+
57
+ return report
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,56 @@
1
+ module Onering
2
+ module CLI
3
+ require 'yaml'
4
+ require 'multi_json'
5
+
6
+ def self.connect(cliargs)
7
+ @_args = cliargs
8
+
9
+ return Onering::API.new({
10
+ 'autoconnect' => cliargs[:autoconnect],
11
+ 'config' => {
12
+ 'url' => cliargs[:url],
13
+ 'path' => cliargs[:path],
14
+ 'authentication' => {
15
+ 'type' => (cliargs[:apikey_given] ? :token : nil),
16
+ 'keyfile' => (cliargs[:apikey] || cliargs[:sslkey])
17
+ }.compact
18
+ }.compact
19
+ }.compact)
20
+ end
21
+
22
+ def self.output(data, format)
23
+ return nil if @_args[:quiet]
24
+
25
+ case format
26
+ when 'text'
27
+ if data.is_a?(Hash)
28
+ data.coalesce.each do |k,v|
29
+ puts k.to_s+': '+v.to_s
30
+ end
31
+ else
32
+ [*data].each do |d|
33
+ if d.is_a?(Hash)
34
+ d.coalesce.each do |k,v|
35
+ puts k.to_s+': '+v.to_s
36
+ end
37
+ else
38
+ puts d unless d.empty?
39
+ end
40
+ end
41
+ end
42
+
43
+ when 'json'
44
+ puts MultiJson.dump(data)
45
+
46
+ when 'yaml'
47
+ puts YAML.dump(data)
48
+
49
+ else
50
+ raise "Unknown output format #{format.inspect}"
51
+ end
52
+
53
+ nil
54
+ end
55
+ end
56
+ end
@@ -1,38 +1,34 @@
1
-
2
1
  module Onering
3
- module API
4
- class Auth < Base
5
- class<<self
6
- def _check_type(type)
7
- raise "Invalid authentication module object '#{type}'" unless %w{
8
- users groups capabilities
9
- }.include?(type.to_s)
10
- end
2
+ class API
3
+ class Auth < API
4
+ def _check_type(type)
5
+ raise "Invalid authentication module object '#{type}'" unless %w{
6
+ users groups capabilities
7
+ }.include?(type.to_s)
8
+ end
11
9
 
12
- def get(type, id='current')
13
- _check_type(type)
14
- request("#{type}/#{id}")
15
- end
10
+ def show(type, id='current')
11
+ _check_type(type)
12
+ get("#{type}/#{id}").parsed_response
13
+ end
16
14
 
17
- def list(type, field='id', options={
18
- :unique => true,
19
- :sort => true,
20
- :filter => nil
21
- })
22
- _check_type(type)
23
- rv = request("#{type}/list").collect{|i| i[field.to_s] }
24
- rv = rv.uniq if options[:unique]
25
- rv = rv.sort if options[:sort]
26
- rv
27
- end
15
+ def list(type, field='id', options={
16
+ :unique => true,
17
+ :sort => true,
18
+ :filter => nil
19
+ })
20
+ _check_type(type)
21
+ rv = get("#{type}/list").parsed_response.collect{|i| i[field.to_s] }
22
+ rv = rv.uniq if options[:unique]
23
+ rv = rv.sort if options[:sort]
24
+ rv
25
+ end
28
26
 
29
- def save(type, id, data)
30
- _check_type(type)
31
- request("#{type}/#{id}", {
32
- :method => :post,
33
- :data => data
34
- })
35
- end
27
+ def save(type, id, data)
28
+ _check_type(type)
29
+ post("#{type}/#{id}", {
30
+ :body => data
31
+ }).parsed_response
36
32
  end
37
33
  end
38
34
  end
@@ -0,0 +1,66 @@
1
+ module Onering
2
+ class API
3
+ class AutomationRequests < API
4
+ def summary(fields)
5
+ get("/automation/requests/summary/#{[*fields].join('/')}").parsed_response
6
+ end
7
+
8
+ def find_by_status(status)
9
+ get("/automation/requests/status/#{status}").parsed_response
10
+ end
11
+
12
+ def show(id)
13
+ get("/automation/requests/#{id}").parsed_response
14
+ end
15
+
16
+ def requeue(id)
17
+ get("/automation/requests/#{id}/requeue").parsed_response
18
+ end
19
+
20
+ def flush_queue()
21
+ get("/automation/requests/flush").parsed_response
22
+ end
23
+
24
+ def requeue_all_failed()
25
+ get("/automation/requests/requeue").parsed_response
26
+ end
27
+ end
28
+
29
+
30
+ # -----------------------------------------------------------------------------
31
+ class AutomationJobs < API
32
+ def list()
33
+ get("/automation/jobs/list").parsed_response
34
+ end
35
+
36
+ def show(name)
37
+ get("/automation/jobs/#{name}").parsed_response
38
+ end
39
+
40
+ def requests_waiting(name)
41
+ get("/automation/jobs/#{name}/waiting").parsed_response
42
+ end
43
+
44
+ def run(name, options={}, &block)
45
+ if block_given?
46
+ post("/automation/jobs/#{name}/run", {
47
+ :query => options
48
+ }, &block).parsed_response
49
+ else
50
+ get("/automation/jobs/#{name}/run", {
51
+ :query => options
52
+ }).parsed_response
53
+ end
54
+ end
55
+ end
56
+
57
+ # -----------------------------------------------------------------------------
58
+ class AutomationTasks < API
59
+ def run(name, options={})
60
+ get("/automation/tasks/#{name}/run", {
61
+ :query => options
62
+ }).parsed_response
63
+ end
64
+ end
65
+ end
66
+ end
@@ -1,47 +1,47 @@
1
-
2
1
  module Onering
3
- module API
4
- class Devices < Base
5
- class<<self
6
- def get(id)
7
- request("devices/#{id}")
8
- end
2
+ class API
3
+ class Devices < API
4
+ def show(id)
5
+ get("/devices/#{id}").parsed_response
6
+ end
9
7
 
10
- def get_field(id, field)
11
- request("devices/#{id}/get/#{field}")
12
- end
8
+ def get_field(id, field)
9
+ get("/devices/#{id}/get/#{field}").response.body
10
+ end
13
11
 
14
- def set_field(id, field, value)
15
- request("devices/#{id}/set/#{field}/#{value}")
16
- end
12
+ def set_field(id, field, value)
13
+ get("/devices/#{id}/set/#{field}/#{value}").response.body
14
+ end
17
15
 
18
- def list(field, options={
19
- :unique => true,
20
- :sort => true,
21
- :filter => nil
22
- })
23
- qs = {
24
- :q => make_filter(options[:filter])
25
- } if options[:filter]
26
-
27
- rv = request("devices/list/#{field}", {
28
- :fields => qs
29
- })
16
+ def list(field, options={
17
+ :unique => true,
18
+ :sort => true,
19
+ :filter => nil
20
+ })
21
+ qs = {
22
+ :q => make_filter(options[:filter])
23
+ } if options[:filter]
30
24
 
31
- rv = rv.uniq if options[:unique]
32
- rv = rv.sort if options[:sort]
25
+ rv = get("/devices/list/#{field}", {
26
+ :query => qs
27
+ }).parsed_response
33
28
 
34
- rv
35
- end
29
+ rv = rv.uniq if options[:unique]
30
+ rv = rv.sort if options[:sort]
36
31
 
37
- def find(filter, options={})
38
- request("devices/find/#{make_filter(filter)}")
39
- end
32
+ return rv
33
+ end
34
+
35
+ def find(filter, options={})
36
+ get("/devices/find/#{make_filter(filter)}").parsed_response
37
+ end
40
38
 
41
- def save(id, data)
42
- request("devices/#{id}", {
43
- :method => :post,
44
- :data => data
39
+ def save(id, data=nil, &block)
40
+ if block_given?
41
+ post("/devices/#{id}", {}, &block)
42
+ else
43
+ post("/devices/#{id}", {
44
+ :body => data
45
45
  })
46
46
  end
47
47
  end
@@ -22,6 +22,8 @@ module Onering
22
22
  ]
23
23
 
24
24
  class<<self
25
+ include Onering::Util
26
+
25
27
  attr_reader :facter_path
26
28
 
27
29
  def setup(config={})
@@ -50,15 +52,6 @@ module Onering
50
52
  end
51
53
  end
52
54
 
53
-
54
- def fact(name, default=nil)
55
- if defined?(Facter)
56
- return (Facter.value(name) or default)
57
- end
58
-
59
- return nil
60
- end
61
-
62
55
  def load_plugins
63
56
  # load plugins from @path
64
57
  @path.compact.each do |root|
@@ -103,8 +96,8 @@ module Onering
103
96
  @_report[:properties][:metrics].set(name, value) if value
104
97
  end
105
98
 
106
- def report
107
- @id = (@options[:id] || (IO.read('/etc/hardware.id').to_s.nil_empty rescue nil))
99
+ def report()
100
+ @id = (@options[:id] || Onering::Util.fact('hardwareid', nil))
108
101
 
109
102
  if not @id.nil?
110
103
  hostname = (Facter.value('fqdn') rescue %x{hostname -f}.strip.chomp)
@@ -122,12 +115,12 @@ module Onering
122
115
  # loads plugins and populates @_report
123
116
  load_plugins
124
117
 
125
- return @_report
118
+ return @_report.stringify_keys()
126
119
  else
127
120
  raise "Cannot generate report without a hardware ID"
128
121
  end
129
122
 
130
- nil
123
+ {}
131
124
  end
132
125
  end
133
126
  end
data/lib/onering/util.rb CHANGED
@@ -7,8 +7,53 @@ module Onering
7
7
  end
8
8
  end
9
9
 
10
+ extend self
10
11
 
11
- def self.gem_path(name)
12
+
13
+ HTTP_STATUS_CODES = {
14
+ 400 => 'Bad Request',
15
+ 401 => 'Unauthorized',
16
+ 402 => 'Payment Required',
17
+ 403 => 'Forbidden',
18
+ 404 => 'Not Found',
19
+ 405 => 'Method Not Allowed',
20
+ 406 => 'Not Acceptable',
21
+ 407 => 'Proxy Authentication Required',
22
+ 408 => 'Request Timeout',
23
+ 409 => 'Conflict',
24
+ 410 => 'Gone',
25
+ 411 => 'Length Required',
26
+ 412 => 'Precondition Failed',
27
+ 413 => 'Request Entity Too Large',
28
+ 414 => 'Request-URI Too Long',
29
+ 415 => 'Unsupported Media Type',
30
+ 416 => 'Requested Range Not Satisfiable',
31
+ 417 => 'Expectation Failed',
32
+ 418 => 'I\'m a Teapot',
33
+ 420 => 'Enhance Your Calm',
34
+ 422 => 'Unprocessable Entity',
35
+ 423 => 'Locked',
36
+ 424 => 'Failed Dependency',
37
+ 426 => 'Upgrade Required',
38
+ 428 => 'Precondition Required',
39
+ 429 => 'Too Many Requests',
40
+ 431 => 'Request Header Fields Too Large',
41
+ 444 => 'No Response',
42
+ 451 => 'Unavailable For Legal Reasons',
43
+
44
+ 500 => 'Internal Server Error',
45
+ 501 => 'Not Implemented',
46
+ 502 => 'Bad Gateway',
47
+ 503 => 'Service Unavailable',
48
+ 504 => 'Gateway Timeout',
49
+ 505 => 'HTTP Version Not Supported',
50
+ 508 => 'Loop Detected',
51
+ 509 => 'Bandwidth Limit Exceeded',
52
+ 510 => 'Not Extended',
53
+ 511 => 'Network Authentication Required'
54
+ }
55
+
56
+ def gem_path(name)
12
57
  if Gem::Specification.respond_to?(:find_by_name)
13
58
  return Gem::Specification.find_by_name(name).gem_dir
14
59
  else
@@ -17,9 +62,54 @@ module Onering
17
62
  }.last.full_gem_path
18
63
  end
19
64
  end
65
+
66
+ def fact(name, default=nil)
67
+ name = name.to_s
68
+
69
+ if defined?(Facter)
70
+ fact = Facter.value(name)
71
+
72
+ # short circuit nil responses
73
+ return default if fact.nil?
74
+
75
+ # if we are asking for a nested object...
76
+ if name.include?('.')
77
+ # ...and the response IS an object...
78
+ if fact.is_a?(Hash)
79
+ # remove the first part and return the rest
80
+ name = name.sub(/^[^\.]+\./,'')
81
+ return fact.get(name, default)
82
+ else
83
+ # not an object, return default
84
+ return default
85
+ end
86
+ else
87
+ # this is a simple request, return the fact
88
+ return fact
89
+ end
90
+ end
91
+
92
+ return default
93
+ end
94
+
95
+ def make_filter(filter)
96
+ filter = filter.collect{|k,v| "#{k}/#{v}" } if filter.is_a?(Hash)
97
+ filter = filter.collect{|i| i.sub(':','/') }.join("/") if filter.is_a?(Array)
98
+ return filter
99
+ end
100
+
101
+ def http_status(code)
102
+ return (HTTP_STATUS_CODES[code.to_i] || nil)
103
+ end
20
104
  end
21
105
  end
22
106
 
23
107
  class String
24
108
  include Onering::Util::String
109
+ end
110
+
111
+ class Module
112
+ def submodules
113
+ constants.collect {|const_name| const_get(const_name)}.select {|const| const.class == Module}
114
+ end
25
115
  end
data/lib/onering.rb CHANGED
@@ -3,4 +3,11 @@ require 'onering/util'
3
3
  require 'onering/api'
4
4
  require 'onering/plugins/devices'
5
5
  require 'onering/plugins/authentication'
6
+ require 'onering/plugins/automation'
6
7
  require 'onering/plugins/reporter'
8
+ require 'onering/cli'
9
+ require 'onering/cli/call'
10
+ require 'onering/cli/fact'
11
+ require 'onering/cli/devices'
12
+ require 'onering/cli/automation'
13
+ require 'onering/cli/reporter'
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.46
4
+ version: 0.0.50
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: &21024540 !ruby/object:Gem::Requirement
16
+ requirement: &6690160 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '0'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *21024540
24
+ version_requirements: *6690160
25
25
  - !ruby/object:Gem::Dependency
26
- name: subcommander
27
- requirement: &21022680 !ruby/object:Gem::Requirement
26
+ name: deep_merge
27
+ requirement: &6689220 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :runtime
34
34
  prerelease: false
35
- version_requirements: *21022680
35
+ version_requirements: *6689220
36
36
  - !ruby/object:Gem::Dependency
37
- name: deep_merge
38
- requirement: &21020640 !ruby/object:Gem::Requirement
37
+ name: addressable
38
+ requirement: &6688340 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :runtime
45
45
  prerelease: false
46
- version_requirements: *21020640
46
+ version_requirements: *6688340
47
47
  - !ruby/object:Gem::Dependency
48
- name: addressable
49
- requirement: &20995240 !ruby/object:Gem::Requirement
48
+ name: httparty
49
+ requirement: &6687680 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :runtime
56
56
  prerelease: false
57
- version_requirements: *20995240
57
+ version_requirements: *6687680
58
58
  - !ruby/object:Gem::Dependency
59
- name: rest-client
60
- requirement: &20993960 !ruby/object:Gem::Requirement
59
+ name: hashlib
60
+ requirement: &6686980 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :runtime
67
67
  prerelease: false
68
- version_requirements: *20993960
68
+ version_requirements: *6686980
69
69
  - !ruby/object:Gem::Dependency
70
- name: hashlib
71
- requirement: &20992780 !ruby/object:Gem::Requirement
70
+ name: multi_json
71
+ requirement: &6578580 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :runtime
78
78
  prerelease: false
79
- version_requirements: *20992780
79
+ version_requirements: *6578580
80
80
  - !ruby/object:Gem::Dependency
81
- name: multi_json
82
- requirement: &20990720 !ruby/object:Gem::Requirement
81
+ name: rainbow
82
+ requirement: &6577580 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
- version_requirements: *20990720
90
+ version_requirements: *6577580
91
91
  - !ruby/object:Gem::Dependency
92
- name: rainbow
93
- requirement: &20989400 !ruby/object:Gem::Requirement
92
+ name: trollop
93
+ requirement: &6576960 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,7 +98,7 @@ dependencies:
98
98
  version: '0'
99
99
  type: :runtime
100
100
  prerelease: false
101
- version_requirements: *20989400
101
+ version_requirements: *6576960
102
102
  description: A Ruby wrapper for Onering
103
103
  email: ghetzel@outbrain.com
104
104
  executables:
@@ -109,8 +109,15 @@ files:
109
109
  - lib/onering.rb
110
110
  - lib/onering/util.rb
111
111
  - lib/onering/api.rb
112
+ - lib/onering/cli.rb
113
+ - lib/onering/cli/fact.rb
114
+ - lib/onering/cli/call.rb
115
+ - lib/onering/cli/devices.rb
116
+ - lib/onering/cli/automation.rb
117
+ - lib/onering/cli/reporter.rb
112
118
  - lib/onering/plugins/devices.rb
113
119
  - lib/onering/plugins/authentication.rb
120
+ - lib/onering/plugins/automation.rb
114
121
  - lib/onering/plugins/reporter.rb
115
122
  - bin/onering
116
123
  homepage: https://github.com/outbrain/onering-ruby