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