bugzilla 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +8 -0
- data/.travis.yml +17 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Dockerfile +5 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +76 -0
- data/LICENSE.txt +21 -0
- data/README.md +48 -0
- data/Rakefile +26 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/bugzilla.gemspec +34 -0
- data/lib/bugzilla.rb +12 -0
- data/lib/bugzilla/api_template.rb +44 -0
- data/lib/bugzilla/bug.rb +356 -0
- data/lib/bugzilla/bugzilla.rb +149 -0
- data/lib/bugzilla/classification.rb +74 -0
- data/lib/bugzilla/group.rb +43 -0
- data/lib/bugzilla/plugin.rb +67 -0
- data/lib/bugzilla/plugins/nvbugzilla.rb +49 -0
- data/lib/bugzilla/plugins/rhbugzilla.rb +210 -0
- data/lib/bugzilla/product.rb +179 -0
- data/lib/bugzilla/skeleton.rb +42 -0
- data/lib/bugzilla/user.rb +182 -0
- data/lib/bugzilla/utils.rb +53 -0
- data/lib/bugzilla/version.rb +27 -0
- data/lib/bugzilla/xmlrpc.rb +92 -0
- metadata +211 -0
@@ -0,0 +1,179 @@
|
|
1
|
+
# product.rb
|
2
|
+
# Copyright (C) 2010-2012 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'bugzilla/api_template'
|
21
|
+
|
22
|
+
module Bugzilla
|
23
|
+
# rdoc
|
24
|
+
#
|
25
|
+
# === Bugzilla::Product
|
26
|
+
#
|
27
|
+
# Bugzilla::Product class is to access
|
28
|
+
# the Bugzilla::WebService::Product API that allows you to
|
29
|
+
# list the available Products and get information about them.
|
30
|
+
#
|
31
|
+
|
32
|
+
class Product < APITemplate
|
33
|
+
# rdoc
|
34
|
+
#
|
35
|
+
# ==== Bugzilla::Product#selectable_products
|
36
|
+
#
|
37
|
+
# Returns Hash table for the products information that the user
|
38
|
+
# can search on. the Hash key is the product name and containing
|
39
|
+
# a Hash table which contains id, name, description,
|
40
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
41
|
+
# components, versions and milestones. please see
|
42
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
43
|
+
# for more details.
|
44
|
+
#
|
45
|
+
|
46
|
+
def selectable_products
|
47
|
+
ids = get_selectable_products
|
48
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
49
|
+
end # def selectable_products
|
50
|
+
|
51
|
+
# rdoc
|
52
|
+
#
|
53
|
+
# ==== Bugzilla::Product#enterable_products
|
54
|
+
#
|
55
|
+
# Returns Hash table for the products information that the user
|
56
|
+
# can enter bugs against. the Hash key is the product name and
|
57
|
+
# containing a Hash table which contains id, name, description,
|
58
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
59
|
+
# components, versions and milestones. please see
|
60
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
61
|
+
# for more details.
|
62
|
+
#
|
63
|
+
|
64
|
+
def enterable_products
|
65
|
+
ids = get_enterable_products
|
66
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
67
|
+
end # def enterable_products
|
68
|
+
|
69
|
+
# rdoc
|
70
|
+
#
|
71
|
+
# ==== Bugzilla::Product#accessible_products
|
72
|
+
#
|
73
|
+
# Returns Hash table for the products information that the user
|
74
|
+
# can search or enter bugs against. the Hash key is the product
|
75
|
+
# name and containing a Hash table which contains id, name, description,
|
76
|
+
# is_active, default_milestone, has_uncomfirmed, classification,
|
77
|
+
# components, versions and milestones. please see
|
78
|
+
# http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html#get
|
79
|
+
# for more details.
|
80
|
+
#
|
81
|
+
|
82
|
+
def accessible_products
|
83
|
+
ids = get_accessible_products
|
84
|
+
Hash[*get(ids)['products'].map { |x| [x['name'], x] }.flatten]
|
85
|
+
end # def accessible_products
|
86
|
+
|
87
|
+
# rdoc
|
88
|
+
#
|
89
|
+
# ==== Bugzilla::Product#get_selectable_products
|
90
|
+
#
|
91
|
+
# Raw Bugzilla API to obtain the products that the user can
|
92
|
+
# search on.
|
93
|
+
#
|
94
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
95
|
+
#
|
96
|
+
|
97
|
+
# rdoc
|
98
|
+
#
|
99
|
+
# ==== Bugzilla::Product#get_enterable_products
|
100
|
+
#
|
101
|
+
# Raw Bugzilla API to obtain the products that the user can
|
102
|
+
# enter bugs against.
|
103
|
+
#
|
104
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
105
|
+
#
|
106
|
+
|
107
|
+
# rdoc
|
108
|
+
#
|
109
|
+
# ==== Bugzilla::Product#get_accessible_products
|
110
|
+
#
|
111
|
+
# Raw Bugzilla API to obtain the products that the user can
|
112
|
+
# search or enter bugs against.
|
113
|
+
#
|
114
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
115
|
+
#
|
116
|
+
|
117
|
+
# rdoc
|
118
|
+
#
|
119
|
+
# ==== Bugzilla::Product#get(params)
|
120
|
+
#
|
121
|
+
# Raw Bugzilla API to obtain a list of information about the products
|
122
|
+
# passed to it.
|
123
|
+
#
|
124
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/Product.html
|
125
|
+
#
|
126
|
+
|
127
|
+
protected
|
128
|
+
|
129
|
+
def _get_selectable_products(cmd, *_args)
|
130
|
+
@iface.call(cmd)
|
131
|
+
end # def _get_selectable_products
|
132
|
+
|
133
|
+
def _get_enterable_products(cmd, *_args)
|
134
|
+
@iface.call(cmd)
|
135
|
+
end # def _get_entrable_products
|
136
|
+
|
137
|
+
def _get_accessible_products(cmd, *_args)
|
138
|
+
@iface.call(cmd)
|
139
|
+
end # def _get_accessible_products
|
140
|
+
|
141
|
+
def _get(cmd, ids, *_args)
|
142
|
+
# This is still in experimental and apparently the behavior was changed since 4.2.
|
143
|
+
# We don't keep the backward-compatibility and just require the proper version here.
|
144
|
+
requires_version(cmd, 4.2)
|
145
|
+
|
146
|
+
params = {}
|
147
|
+
|
148
|
+
if ids.is_a?(Hash)
|
149
|
+
raise ArgumentError, format('Invalid parameter: %s', ids.inspect) unless ids.include?('ids') || ids.include?('names')
|
150
|
+
params[:ids] = ids['ids'] || ids['names']
|
151
|
+
elsif ids.is_a?(Array)
|
152
|
+
r = ids.map { |x| x.is_a?(Integer) ? x : nil }.compact
|
153
|
+
if r.length != ids.length
|
154
|
+
params[:names] = ids
|
155
|
+
else
|
156
|
+
params[:ids] = ids
|
157
|
+
end
|
158
|
+
else
|
159
|
+
if ids.is_a?(Integer)
|
160
|
+
params[:ids] = [ids]
|
161
|
+
else
|
162
|
+
params[:names] = [ids]
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
@iface.call(cmd, params)
|
167
|
+
end # def _get
|
168
|
+
|
169
|
+
def __create(cmd, *args)
|
170
|
+
# FIXME
|
171
|
+
end # def _create
|
172
|
+
|
173
|
+
def __update(cmd, *_args)
|
174
|
+
requires_version(cmd, 4.4)
|
175
|
+
|
176
|
+
# FIXME
|
177
|
+
end # def _update
|
178
|
+
end # class Product
|
179
|
+
end # module Bugzilla
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# skeleton.rb
|
2
|
+
# Copyright (C) 2010-2014 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
module Bugzilla
|
21
|
+
# rdoc
|
22
|
+
#
|
23
|
+
# === Bugzilla::Skeleton
|
24
|
+
#
|
25
|
+
|
26
|
+
class Skeleton
|
27
|
+
def initialize(iface)
|
28
|
+
@iface = iface
|
29
|
+
end # def initialize
|
30
|
+
|
31
|
+
def method_missing(symbol, *args)
|
32
|
+
m = "_#{symbol}"
|
33
|
+
klass = self.class.to_s.sub(/\ABugzilla::/, '')
|
34
|
+
fm = "#{klass}.#{symbol}"
|
35
|
+
if respond_to?(m, true)
|
36
|
+
__send__(m, fm, *args)
|
37
|
+
else
|
38
|
+
raise NoMethodError, format('No such Bugzilla APIs: %s.%s', klass, symbol)
|
39
|
+
end
|
40
|
+
end # def method_missing
|
41
|
+
end # class Skeleton
|
42
|
+
end # module Bugzilla
|
@@ -0,0 +1,182 @@
|
|
1
|
+
# user.rb
|
2
|
+
# Copyright (C) 2010-2014 Red Hat, Inc.
|
3
|
+
#
|
4
|
+
# Authors:
|
5
|
+
# Akira TAGOH <tagoh@redhat.com>
|
6
|
+
#
|
7
|
+
# This library is free software: you can redistribute it and/or
|
8
|
+
# modify it under the terms of the GNU Lesser General Public
|
9
|
+
# License as published by the Free Software Foundation, either
|
10
|
+
# version 3 of the License, or (at your option) any later version.
|
11
|
+
#
|
12
|
+
# This library is distributed in the hope that it will be useful,
|
13
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
15
|
+
# GNU General Public License for more details.
|
16
|
+
#
|
17
|
+
# You should have received a copy of the GNU General Public License
|
18
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
19
|
+
|
20
|
+
require 'yaml'
|
21
|
+
require 'bugzilla/api_template'
|
22
|
+
|
23
|
+
module Bugzilla
|
24
|
+
# rdoc
|
25
|
+
#
|
26
|
+
# === Bugzilla::User
|
27
|
+
#
|
28
|
+
# Bugzilla::User class is to access the
|
29
|
+
# Bugzilla::WebService::User API that allows you to create
|
30
|
+
# User Accounts and log in/out using an existing account.
|
31
|
+
#
|
32
|
+
|
33
|
+
class User < APITemplate
|
34
|
+
# rdoc
|
35
|
+
#
|
36
|
+
# ==== Bugzilla::User#session(user, password)
|
37
|
+
#
|
38
|
+
# Keeps the bugzilla session during doing something in the block.
|
39
|
+
#
|
40
|
+
|
41
|
+
def session(user, password)
|
42
|
+
key, fname = authentication_method
|
43
|
+
|
44
|
+
# TODO
|
45
|
+
# make those variables available
|
46
|
+
host = @iface.instance_variable_get(:@xmlrpc).instance_variable_get(:@host)
|
47
|
+
|
48
|
+
conf = load_authentication_token(fname)
|
49
|
+
|
50
|
+
val = conf.fetch(host, nil)
|
51
|
+
|
52
|
+
if !val.nil?
|
53
|
+
if key == :token
|
54
|
+
@iface.token = val
|
55
|
+
else
|
56
|
+
@iface.cookie = val
|
57
|
+
end
|
58
|
+
yield
|
59
|
+
elsif user.nil? || password.nil?
|
60
|
+
yield
|
61
|
+
return
|
62
|
+
else
|
63
|
+
login('login' => user, 'password' => password, 'remember' => true)
|
64
|
+
yield
|
65
|
+
end
|
66
|
+
|
67
|
+
conf[host] = @iface.send(key) if %i[token cookie].include? key
|
68
|
+
|
69
|
+
save_authentication_token(fname, conf)
|
70
|
+
key
|
71
|
+
end # def session
|
72
|
+
|
73
|
+
# rdoc
|
74
|
+
#
|
75
|
+
# ==== Bugzilla::User#get_userinfo(params)
|
76
|
+
#
|
77
|
+
|
78
|
+
def get_userinfo(user)
|
79
|
+
p = {}
|
80
|
+
ids = []
|
81
|
+
names = []
|
82
|
+
|
83
|
+
if user.is_a?(Array)
|
84
|
+
user.each do |u|
|
85
|
+
names << u if u.is_a?(String)
|
86
|
+
id << u if u.is_a?(Integer)
|
87
|
+
end
|
88
|
+
elsif user.is_a?(String)
|
89
|
+
names << user
|
90
|
+
elsif user.is_a?(Integer)
|
91
|
+
ids << user
|
92
|
+
else
|
93
|
+
raise ArgumentError, format('Unknown type of arguments: %s', user.class)
|
94
|
+
end
|
95
|
+
|
96
|
+
result = get('ids' => ids, 'names' => names)
|
97
|
+
|
98
|
+
result['users']
|
99
|
+
end # def get_userinfo
|
100
|
+
|
101
|
+
# rdoc
|
102
|
+
#
|
103
|
+
# ==== Bugzilla::User#login(params)
|
104
|
+
#
|
105
|
+
# Raw Bugzilla API to log into Bugzilla.
|
106
|
+
#
|
107
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/User.html
|
108
|
+
#
|
109
|
+
|
110
|
+
# rdoc
|
111
|
+
#
|
112
|
+
# ==== Bugzilla::User#logout
|
113
|
+
#
|
114
|
+
# Raw Bugzilla API to log out the user.
|
115
|
+
#
|
116
|
+
# See http://www.bugzilla.org/docs/tip/en/html/api/Bugzilla/WebService/User.html
|
117
|
+
#
|
118
|
+
|
119
|
+
protected
|
120
|
+
|
121
|
+
def load_authentication_token(fname)
|
122
|
+
if File.exist?(fname) && File.lstat(fname).mode & 0o600 == 0o600
|
123
|
+
YAML.safe_load(File.open(fname).read)
|
124
|
+
else
|
125
|
+
{}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def save_authentication_token(fname, conf)
|
130
|
+
File.open(fname, 'w') { |f| f.chmod(0o600); f.write(conf.to_yaml) }
|
131
|
+
end
|
132
|
+
|
133
|
+
def is_token_supported?
|
134
|
+
check_version('4.4.3')[0] == true
|
135
|
+
rescue StandardError
|
136
|
+
false
|
137
|
+
end
|
138
|
+
|
139
|
+
# it returns an array with authentication type and the name of the storage
|
140
|
+
def authentication_method
|
141
|
+
# if version supported, use token, otherwise cookie
|
142
|
+
if is_token_supported?
|
143
|
+
[:token, File.join(ENV['HOME'], '.ruby-bugzilla-token.yml')]
|
144
|
+
else
|
145
|
+
[:cookie, File.join(ENV['HOME'], '.ruby-bugzilla-cookie.yml')]
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
def _login(cmd, *args)
|
150
|
+
raise ArgumentError, 'Invalid parameters' unless args[0].is_a?(Hash)
|
151
|
+
|
152
|
+
res = @iface.call(cmd, args[0])
|
153
|
+
@iface.token = res['token'] unless res['token'].nil?
|
154
|
+
|
155
|
+
res
|
156
|
+
end # def _login
|
157
|
+
|
158
|
+
def _logout(cmd, *_args)
|
159
|
+
@iface.call(cmd)
|
160
|
+
end # def _logout
|
161
|
+
|
162
|
+
def __offer_account_by_email(cmd, *args)
|
163
|
+
# FIXME
|
164
|
+
end # def _offer_account_by_email
|
165
|
+
|
166
|
+
def __create(cmd, *args)
|
167
|
+
# FIXME
|
168
|
+
end # def _create
|
169
|
+
|
170
|
+
def __update(cmd, *args)
|
171
|
+
# FIXME
|
172
|
+
end # def _update
|
173
|
+
|
174
|
+
def _get(cmd, *args)
|
175
|
+
raise ArgumentError, 'Invalid parameters' unless args[0].is_a?(Hash)
|
176
|
+
|
177
|
+
requires_version(cmd, 3.4)
|
178
|
+
res = @iface.call(cmd, args[0])
|
179
|
+
# FIXME
|
180
|
+
end # def _get
|
181
|
+
end # class User
|
182
|
+
end # module Bugzilla
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Bugzilla
|
2
|
+
module Utils
|
3
|
+
def get_proxy(info)
|
4
|
+
uri = info[:Proxy] || ENV['http_proxy']
|
5
|
+
proxy_uri = uri.nil? ? nil : URI.parse(uri)
|
6
|
+
proxy_host = proxy_uri.nil? ? nil : proxy_uri.host
|
7
|
+
proxy_port = proxy_uri.nil? ? nil : proxy_uri.port
|
8
|
+
[proxy_host, proxy_port]
|
9
|
+
end
|
10
|
+
|
11
|
+
def get_xmlrpc(conf = {}, opts = {})
|
12
|
+
info = conf
|
13
|
+
uri = URI.parse(info[:URL])
|
14
|
+
host = uri.host
|
15
|
+
port = uri.port
|
16
|
+
path = uri.path.empty? ? nil : uri.path
|
17
|
+
proxy_host, proxy_port = get_proxy(info)
|
18
|
+
timeout = opts[:timeout].nil? ? 60 : opts[:timeout]
|
19
|
+
yield host if block_given? # if you want to run some pre hook
|
20
|
+
xmlrpc = XMLRPC.new(host, port: port, path: path, proxy_host:
|
21
|
+
proxy_host, proxy_port: proxy_port, timeout:
|
22
|
+
timeout, http_basic_auth_user: uri.user,
|
23
|
+
http_basic_auth_pass: uri.password, debug: opts[:debug])
|
24
|
+
[xmlrpc, host]
|
25
|
+
end
|
26
|
+
def read_config(opts)
|
27
|
+
fname = opts[:config].nil? ? @defaultyamlfile : opts[:config]
|
28
|
+
begin
|
29
|
+
# TODO: fix config file
|
30
|
+
# Psych doesnt allow Symbol as class
|
31
|
+
# conf = YAML.safe_load(File.open(fname).read)
|
32
|
+
conf = YAML.load(File.open(fname).read)
|
33
|
+
rescue Errno::ENOENT
|
34
|
+
conf = {}
|
35
|
+
end
|
36
|
+
conf.each do |_k, v|
|
37
|
+
load(v[:Plugin]) if v.is_a?(Hash) && v.include?(:Plugin)
|
38
|
+
end
|
39
|
+
conf
|
40
|
+
end # def read_config
|
41
|
+
|
42
|
+
def save_config(opts, conf)
|
43
|
+
fname = opts[:config].nil? ? @defaultyamlfile : opts[:config]
|
44
|
+
if File.exist?(fname)
|
45
|
+
st = File.lstat(fname)
|
46
|
+
if st.mode & 0o600 != 0o600
|
47
|
+
raise format('The permissions of %s has to be 0600', fname)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
File.open(fname, 'w') { |f| f.chmod(0o600); f.write(conf.to_yaml) }
|
51
|
+
end # def save_config
|
52
|
+
end
|
53
|
+
end
|