redhat_access_lib 1.0.6
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.
- checksums.yaml +7 -0
- data/Rakefile +9 -0
- data/lib/api/api.rb +43 -0
- data/lib/api/telemetry_api.rb +230 -0
- data/lib/brokers/article.rb +24 -0
- data/lib/brokers/attachment.rb +81 -0
- data/lib/brokers/broker.rb +16 -0
- data/lib/brokers/case.rb +145 -0
- data/lib/brokers/comment.rb +69 -0
- data/lib/brokers/entitlement.rb +15 -0
- data/lib/brokers/group.rb +15 -0
- data/lib/brokers/problem.rb +51 -0
- data/lib/brokers/product.rb +15 -0
- data/lib/brokers/solution.rb +22 -0
- data/lib/brokers/symptom.rb +19 -0
- data/lib/network/ftp_connection.rb +19 -0
- data/lib/network/http_connection.rb +109 -0
- data/lib/network/http_request.rb +55 -0
- data/lib/network/http_resource.rb +175 -0
- data/lib/redhat_access_lib.rb +111 -0
- data/redhat_access_lib.gemspec +16 -0
- metadata +99 -0
@@ -0,0 +1,69 @@
|
|
1
|
+
module RedHatSupportLib
|
2
|
+
module Brokers
|
3
|
+
class Comment < Broker
|
4
|
+
def initialize(connection)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def get(case_number, comment_id)
|
9
|
+
#TODO check params
|
10
|
+
params =[];
|
11
|
+
result = @connection.get("/rs/cases/#{case_number}/comments/#{comment_id}",
|
12
|
+
{:accept => :json})
|
13
|
+
end
|
14
|
+
|
15
|
+
def list(case_number, start_date, end_date, filter=[])
|
16
|
+
|
17
|
+
uri = "/rs/cases/#{case_number}/comments"
|
18
|
+
param = ''
|
19
|
+
if start_date
|
20
|
+
param = "?startDate=#{start_date}"
|
21
|
+
end
|
22
|
+
if end_date
|
23
|
+
if start_date
|
24
|
+
param = param + "&endDate=#{end_date}"
|
25
|
+
else
|
26
|
+
param = param + "?endDate=#{end_date}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
result = @connection.get(uri+param, {:accept => :json})
|
30
|
+
end
|
31
|
+
|
32
|
+
def add(text, case_number, is_draft, is_public=true)
|
33
|
+
headers = {:content_type => 'application/xml'}
|
34
|
+
data = create_comment(text, case_number, is_draft, is_public)
|
35
|
+
result = @connection.post("/rs/cases/#{case_number}/comments", data, headers) do |code, headers|
|
36
|
+
if code == 201
|
37
|
+
location = headers[:location]
|
38
|
+
return get_id(location)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_comment(comment, case_number, is_draft, is_public=true)
|
44
|
+
#for now use xml version
|
45
|
+
filter = StringIO.new
|
46
|
+
filter << '<?xml version="1.0" encoding="UTF-8" standalone="yes"?>'
|
47
|
+
filter << '<tns:comment xmlns:tns="http://www.redhat.com/gss/strata"' << " caseNumber=\"#{case_number}\">"
|
48
|
+
filter << "<tns:text>#{comment}</tns:text>"
|
49
|
+
if is_public
|
50
|
+
filter << "<tns:public>true</tns:public>"
|
51
|
+
else
|
52
|
+
filter << "<tns:public>false</tns:public>"
|
53
|
+
end
|
54
|
+
if is_draft
|
55
|
+
filter << "<tns:draft>true</tns:draft>"
|
56
|
+
else
|
57
|
+
filter << "<tns:draft>false</tns:draft>"
|
58
|
+
end
|
59
|
+
filter << "</tns:comment>"
|
60
|
+
filter.string
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_id(uri)
|
64
|
+
parts = uri.split("/")
|
65
|
+
parts.pop
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module RedHatSupportLib
|
2
|
+
module Brokers
|
3
|
+
class Problem < Broker
|
4
|
+
def initialize(connection)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def diagnose_string(input)
|
9
|
+
#rs/problems
|
10
|
+
#TODO encode input and error handling
|
11
|
+
#payload = input
|
12
|
+
#headers = {"Content-Type" => "application/json",'Accept' => 'application/vnd.redhat.json.suggestions'}
|
13
|
+
headers = {:content_type => 'text/plain', :accept => :json}
|
14
|
+
result = @connection.post("/rs/problems", input, headers)
|
15
|
+
response = result['source_or_link_or_problem'][2]['source_or_link']
|
16
|
+
if response
|
17
|
+
response.each do |resp|
|
18
|
+
id = {:solution_id => get_solution_id(resp)}
|
19
|
+
resp.merge! id
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def diagnose_file(file_path)
|
26
|
+
|
27
|
+
File.open(file_path) do |file|
|
28
|
+
headers = {:content_type => 'application/octet-stream', :accept => :json}
|
29
|
+
result = @connection.post("/rs/problems", file, headers)
|
30
|
+
response = result['source_or_link_or_problem'][2]['source_or_link']
|
31
|
+
if response
|
32
|
+
response.each do |resp|
|
33
|
+
id = {:solution_id => get_solution_id(resp)}
|
34
|
+
resp.merge! id
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
private
|
43
|
+
def get_solution_id(problem)
|
44
|
+
uri = problem["uri"]
|
45
|
+
parts = uri.split("/")
|
46
|
+
parts.pop
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
module RedHatSupportLib
|
3
|
+
module Brokers
|
4
|
+
class Solution < Broker
|
5
|
+
def initialize(connection)
|
6
|
+
super
|
7
|
+
end
|
8
|
+
|
9
|
+
def search(text, limit=10)
|
10
|
+
text = URI::encode(text)
|
11
|
+
result = @connection.get("/rs/solutions?keyword=#{text}&limit=#{limit}", {:accept => :json})
|
12
|
+
result['solution']
|
13
|
+
end
|
14
|
+
|
15
|
+
def get_solution(id)
|
16
|
+
#error handling
|
17
|
+
result = @connection.get("/rs/solutions/#{id}", {:accept => :json})
|
18
|
+
#result.parsed_response
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RedHatSupportLib
|
2
|
+
module Brokers
|
3
|
+
class Symptom < Broker
|
4
|
+
def initialize(connection)
|
5
|
+
super
|
6
|
+
end
|
7
|
+
|
8
|
+
def diagnose_file(file_path)
|
9
|
+
|
10
|
+
File.open(file_path) do |file|
|
11
|
+
headers = {:content_type => 'text/plain', :accept => :json}
|
12
|
+
result = @connection.post("/rs/symptoms/extractor", file, headers)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'net/ftp'
|
2
|
+
module RedHatSupportLib
|
3
|
+
module Network
|
4
|
+
class FtpConnection
|
5
|
+
def initialize(host)
|
6
|
+
@host = host
|
7
|
+
end
|
8
|
+
|
9
|
+
def upload(file_name, remote_directory)
|
10
|
+
Net::FTP.open(@host) do |ftp|
|
11
|
+
ftp.login
|
12
|
+
files = ftp.chdir(remote_directory)
|
13
|
+
ftp.putbinaryfile(file_name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
require 'json'
|
3
|
+
require "base64"
|
4
|
+
require_relative './http_request'
|
5
|
+
require_relative './http_resource'
|
6
|
+
|
7
|
+
|
8
|
+
module RedHatSupportLib
|
9
|
+
module Network
|
10
|
+
class HttpConnection
|
11
|
+
USER_AGENT = "ruby-rest-client"
|
12
|
+
attr_reader :config
|
13
|
+
|
14
|
+
def initialize(config)
|
15
|
+
@config = config
|
16
|
+
user_agent = USER_AGENT
|
17
|
+
unless config.user_agent.nil?
|
18
|
+
user_agent = config.user_agent
|
19
|
+
end
|
20
|
+
@additional_headers = {:user_agent => user_agent}
|
21
|
+
#unless config.proxy_host.nil? || config.proxy_host.strip.empty?
|
22
|
+
# RestClient.proxy = "http://#{config.proxy_user}:#{config.proxy_password}@#{config.proxy_host}:#{config.proxy_port}"
|
23
|
+
#end
|
24
|
+
unless config.log_location.nil?
|
25
|
+
RestClient.log = config.log_location
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get(relative_uri, headers={}, &block)
|
30
|
+
|
31
|
+
hdr = @additional_headers.merge!(headers)
|
32
|
+
result = get_resource(relative_uri).get hdr
|
33
|
+
parse_response(result.body, headers[:accept])
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
def post(relative_uri, data, headers={}, &block)
|
38
|
+
|
39
|
+
hdr = @additional_headers.merge!(headers)
|
40
|
+
result = get_resource(relative_uri).post data, hdr
|
41
|
+
if block
|
42
|
+
yield result.code, result.headers
|
43
|
+
end
|
44
|
+
parse_response(result.body, headers[:accept])
|
45
|
+
end
|
46
|
+
|
47
|
+
def put(relative_uri, data, headers={}, &block)
|
48
|
+
|
49
|
+
hdr = @additional_headers.merge!(headers)
|
50
|
+
result = get_resource(relative_uri).put data, hdr
|
51
|
+
if block
|
52
|
+
yield result.code, result.headers
|
53
|
+
end
|
54
|
+
parse_response(result.body, headers[:accept])
|
55
|
+
end
|
56
|
+
|
57
|
+
def delete(relative_uri, headers={}, &block)
|
58
|
+
|
59
|
+
hdr = @additional_headers.merge!(headers)
|
60
|
+
result = get_resource(relative_uri).delete hdr
|
61
|
+
if block
|
62
|
+
yield result.code, result.headers
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
#upload a file as multipart
|
67
|
+
def upload(relative_uri, file, headers={}, &block)
|
68
|
+
request = RedHatSupportLib::Network::HttpRequest.new(
|
69
|
+
:headers => headers,
|
70
|
+
:method => :post,
|
71
|
+
:url => "#{@config.base_uri}#{relative_uri}",
|
72
|
+
:user => @config.username,
|
73
|
+
:password => @config.password,
|
74
|
+
:payload => {
|
75
|
+
:multipart => true,
|
76
|
+
:file => file
|
77
|
+
},
|
78
|
+
:proxy => config.proxy
|
79
|
+
)
|
80
|
+
|
81
|
+
result = request.execute
|
82
|
+
if block
|
83
|
+
yield result.code, result.headers
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
private
|
88
|
+
def get_resource(relative_uri)
|
89
|
+
resource = RedHatSupportLib::Network::HttpResource.new("#{@config.base_uri}#{relative_uri}",
|
90
|
+
{:user => @config.username,
|
91
|
+
:password => @config.password,
|
92
|
+
:proxy => config.proxy})
|
93
|
+
end
|
94
|
+
|
95
|
+
def parse_response(body, format)
|
96
|
+
return nil if body.nil? || body.strip.empty? || body == "null"
|
97
|
+
if (format == :json)
|
98
|
+
return JSON.parse(body)
|
99
|
+
end
|
100
|
+
body # for now do nothing for other formats
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
class Config
|
105
|
+
attr_accessor :username, :password, :base_uri, :user_agent,
|
106
|
+
:proxy, :log_location
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'rest_client'
|
2
|
+
|
3
|
+
module RedHatSupportLib
|
4
|
+
module Network
|
5
|
+
#
|
6
|
+
# This HACK class allows us to set proxy on per connection basis
|
7
|
+
# when using RestClient libraries 1.6.x and below
|
8
|
+
# THINGS MAY BREAK when we upgrade RestClient.....
|
9
|
+
#
|
10
|
+
class HttpRequest < RestClient::Request
|
11
|
+
|
12
|
+
def initialize (args={})
|
13
|
+
if args[:proxy]
|
14
|
+
@proxy = args[:proxy]
|
15
|
+
end
|
16
|
+
super(args)
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.execute(args, & block)
|
20
|
+
new(args).execute(& block)
|
21
|
+
end
|
22
|
+
|
23
|
+
# The proxy URI for this request. If `:proxy` was provided on this request,
|
24
|
+
# use it over `RestClient.proxy`.
|
25
|
+
#
|
26
|
+
# @return [URI, nil]
|
27
|
+
#
|
28
|
+
def proxy_uri
|
29
|
+
if defined?(@proxy)
|
30
|
+
if @proxy
|
31
|
+
URI.parse(@proxy)
|
32
|
+
else
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
elsif RestClient.proxy
|
36
|
+
URI.parse(RestClient.proxy)
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def net_http_class
|
43
|
+
p = proxy_uri
|
44
|
+
if p
|
45
|
+
host = URI.decode(p.hostname) if p.hostname
|
46
|
+
user = URI.decode(p.user) if p.user
|
47
|
+
password = URI.decode(p.password) if p.password
|
48
|
+
Net::HTTP::Proxy(host,p.port, user, password)
|
49
|
+
else
|
50
|
+
Net::HTTP
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require_relative './http_request'
|
2
|
+
|
3
|
+
module RedHatSupportLib
|
4
|
+
module Network
|
5
|
+
# A class that can be instantiated for access to a RESTful resource,
|
6
|
+
# including authentication.
|
7
|
+
#
|
8
|
+
# Example:
|
9
|
+
#
|
10
|
+
# resource = RestClient::Resource.new('http://some/resource')
|
11
|
+
# jpg = resource.get(:accept => 'image/jpg')
|
12
|
+
#
|
13
|
+
# With HTTP basic authentication:
|
14
|
+
#
|
15
|
+
# resource = RestClient::Resource.new('http://protected/resource', :user => 'user', :password => 'password')
|
16
|
+
# resource.delete
|
17
|
+
#
|
18
|
+
# With a timeout (seconds):
|
19
|
+
#
|
20
|
+
# RestClient::Resource.new('http://slow', :timeout => 10)
|
21
|
+
#
|
22
|
+
# With an open timeout (seconds):
|
23
|
+
#
|
24
|
+
# RestClient::Resource.new('http://behindfirewall', :open_timeout => 10)
|
25
|
+
#
|
26
|
+
# You can also use resources to share common headers. For headers keys,
|
27
|
+
# symbols are converted to strings. Example:
|
28
|
+
#
|
29
|
+
# resource = RestClient::Resource.new('http://some/resource', :headers => { :client_version => 1 })
|
30
|
+
#
|
31
|
+
# This header will be transported as X-Client-Version (notice the X prefix,
|
32
|
+
# capitalization and hyphens)
|
33
|
+
#
|
34
|
+
# Use the [] syntax to allocate subresources:
|
35
|
+
#
|
36
|
+
# site = RestClient::Resource.new('http://example.com', :user => 'adam', :password => 'mypasswd')
|
37
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
38
|
+
#
|
39
|
+
class HttpResource
|
40
|
+
attr_reader :url, :options, :block
|
41
|
+
|
42
|
+
def initialize(url, options={}, backwards_compatibility=nil, &block)
|
43
|
+
@url = url
|
44
|
+
@block = block
|
45
|
+
if options.class == Hash
|
46
|
+
@options = options
|
47
|
+
else # compatibility with previous versions
|
48
|
+
@options = {:user => options, :password => backwards_compatibility}
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def get(additional_headers={}, &block)
|
53
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
54
|
+
HttpRequest.execute(options.merge(
|
55
|
+
:method => :get,
|
56
|
+
:url => url,
|
57
|
+
:headers => headers), &(block || @block))
|
58
|
+
end
|
59
|
+
|
60
|
+
def head(additional_headers={}, &block)
|
61
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
62
|
+
HttpRequest.execute(options.merge(
|
63
|
+
:method => :head,
|
64
|
+
:url => url,
|
65
|
+
:headers => headers), &(block || @block))
|
66
|
+
end
|
67
|
+
|
68
|
+
def post(payload, additional_headers={}, &block)
|
69
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
70
|
+
HttpRequest.execute(options.merge(
|
71
|
+
:method => :post,
|
72
|
+
:url => url,
|
73
|
+
:payload => payload,
|
74
|
+
:headers => headers), &(block || @block))
|
75
|
+
end
|
76
|
+
|
77
|
+
def put(payload, additional_headers={}, &block)
|
78
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
79
|
+
HttpRequest.execute(options.merge(
|
80
|
+
:method => :put,
|
81
|
+
:url => url,
|
82
|
+
:payload => payload,
|
83
|
+
:headers => headers), &(block || @block))
|
84
|
+
end
|
85
|
+
|
86
|
+
def patch(payload, additional_headers={}, &block)
|
87
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
88
|
+
HttpRequest.execute(options.merge(
|
89
|
+
:method => :patch,
|
90
|
+
:url => url,
|
91
|
+
:payload => payload,
|
92
|
+
:headers => headers), &(block || @block))
|
93
|
+
end
|
94
|
+
|
95
|
+
def delete(additional_headers={}, &block)
|
96
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
97
|
+
HttpRequest.execute(options.merge(
|
98
|
+
:method => :delete,
|
99
|
+
:url => url,
|
100
|
+
:headers => headers), &(block || @block))
|
101
|
+
end
|
102
|
+
|
103
|
+
def to_s
|
104
|
+
url
|
105
|
+
end
|
106
|
+
|
107
|
+
def user
|
108
|
+
options[:user]
|
109
|
+
end
|
110
|
+
|
111
|
+
def password
|
112
|
+
options[:password]
|
113
|
+
end
|
114
|
+
|
115
|
+
def headers
|
116
|
+
options[:headers] || {}
|
117
|
+
end
|
118
|
+
|
119
|
+
def timeout
|
120
|
+
options[:timeout]
|
121
|
+
end
|
122
|
+
|
123
|
+
def open_timeout
|
124
|
+
options[:open_timeout]
|
125
|
+
end
|
126
|
+
|
127
|
+
# Construct a subresource, preserving authentication.
|
128
|
+
#
|
129
|
+
# Example:
|
130
|
+
#
|
131
|
+
# site = RestClient::Resource.new('http://example.com', 'adam', 'mypasswd')
|
132
|
+
# site['posts/1/comments'].post 'Good article.', :content_type => 'text/plain'
|
133
|
+
#
|
134
|
+
# This is especially useful if you wish to define your site in one place and
|
135
|
+
# call it in multiple locations:
|
136
|
+
#
|
137
|
+
# def orders
|
138
|
+
# RestClient::Resource.new('http://example.com/orders', 'admin', 'mypasswd')
|
139
|
+
# end
|
140
|
+
#
|
141
|
+
# orders.get # GET http://example.com/orders
|
142
|
+
# orders['1'].get # GET http://example.com/orders/1
|
143
|
+
# orders['1/items'].delete # DELETE http://example.com/orders/1/items
|
144
|
+
#
|
145
|
+
# Nest resources as far as you want:
|
146
|
+
#
|
147
|
+
# site = RestClient::Resource.new('http://example.com')
|
148
|
+
# posts = site['posts']
|
149
|
+
# first_post = posts['1']
|
150
|
+
# comments = first_post['comments']
|
151
|
+
# comments.post 'Hello', :content_type => 'text/plain'
|
152
|
+
#
|
153
|
+
def [](suburl, &new_block)
|
154
|
+
case
|
155
|
+
when block_given? then
|
156
|
+
self.class.new(concat_urls(url, suburl), options, &new_block)
|
157
|
+
when block then
|
158
|
+
self.class.new(concat_urls(url, suburl), options, &block)
|
159
|
+
else
|
160
|
+
self.class.new(concat_urls(url, suburl), options)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
|
164
|
+
def concat_urls(url, suburl) # :nodoc:
|
165
|
+
url = url.to_s
|
166
|
+
suburl = suburl.to_s
|
167
|
+
if url.slice(-1, 1) == '/' or suburl.slice(0, 1) == '/'
|
168
|
+
url + suburl
|
169
|
+
else
|
170
|
+
"#{url}/#{suburl}"
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|