Update API - Builds

git-svn-id: svn://10.0.0.236/trunk@247060 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
ghendricks%novell.com
2008-03-05 00:36:14 +00:00
parent 899886b9de
commit 39ead0495c
6 changed files with 266 additions and 336 deletions

View File

@@ -13,7 +13,7 @@
# The Original Code is the Bugzilla Testopia System.
#
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Maciej Maczynski are Copyright (C) 2006
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Greg Hendricks <ghendricks@novell.com>
@@ -188,6 +188,7 @@ sub check_build {
"SELECT build_id FROM test_builds
WHERE name = ? AND product_id = ?",
undef, $name, $product->id);
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $name}) unless $is;
return $is;
}
@@ -340,27 +341,43 @@ and are associated with a milestone if targetmilestones are used in Bugzilla.
=head1 FIELDS
+-------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+------------------+------+-----+---------+----------------+
| build_id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| product_id | smallint(6) | NO | MUL | 0 | |
| milestone | varchar(20) | YES | MUL | NULL | |
| name | varchar(255) | YES | MUL | NULL | |
| description | text | YES | | NULL | |
| isactive | tinyint(4) | NO | | 1 | |
+-------------+------------------+------+-----+---------+----------------+
=over
=item C<build_id>
The unique id of this build in the database.
=item C<name>
=item C<name> B<REQUIRED>
A unique name for this build.
=item C<product_id>
=item C<product_id> B<REQUIRED> B<CREATE ONLY>
The id of the Bugzilla product this build is attached to.
=item C<milestone>
=item C<milestone> I<OPTIONAL>
The value from the Bugzilla product milestone table this build is associated with.
=item C<isactive>
=item C<description> I<OPTIONAL>
Boolean - determines whether to show this build in lists for selection.
A description of this build.
=item C<isactive> I<OPTIONAL>
Boolean - Determines whether to show this build in lists for selection.
Defaults to true.
=back
@@ -404,10 +421,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: A blessed Bugzilla::Testopia::Build object
=back
=over
=item C<create()>
Description: Creates a new build object and stores it in the database
@@ -417,10 +430,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: The newly created object.
=back
=over
=item C<set_description()>
Description: Replaces the current build's description. Must call update to
@@ -430,10 +439,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: nothing.
=back
=over
=item C<set_isactive()>
Description: Sets the isactive field.
@@ -442,10 +447,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: nothing.
=back
=over
=item C<set_milestone()>
Description: Assigns this build to a different milestone
@@ -454,10 +455,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: nothing.
=back
=over
=item C<set_name()>
Description: Renames the current build. If the new name is already in use
@@ -468,10 +465,6 @@ Boolean - determines whether to show this build in lists for selection.
Returns: nothing.
=back
=over
=item C<to_json()>
Description: Outputs a JSON representation of the object.

View File

@@ -10,10 +10,14 @@
# implied. See the License for the specific language governing
# rights and limitations under the License.
#
# The Original Code is the Bugzilla Bug Tracking System.
# The Original Code is the Bugzilla Testopia System.
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Dallas Harken <dharken@novell.com>
# The Initial Developer of the Original Code is Greg Hendricks.
# Portions created by Greg Hendricks are Copyright (C) 2006
# Novell. All Rights Reserved.
#
# Contributor(s): Dallas Harken <dharken@novell.com>
# Greg Hendricks <ghendricks@novell.com>
package Bugzilla::WebService::Testopia::Build;
@@ -21,119 +25,141 @@ use strict;
use base qw(Bugzilla::WebService);
use Bugzilla::Constants;
use Bugzilla::Testopia::Build;
sub get
{
sub get {
my $self = shift;
my ($build_id) = @_;
$self->login;
#Result is a test plan hash map
Bugzilla->login(LOGIN_REQUIRED);
# Result is a build object hash
my $build = new Bugzilla::Testopia::Build($build_id);
if (not defined $build)
{
$self->logout;
die "Build, " . $build_id . ", not found";
}
ThrowUserError('invalid-test-id-non-existent', {type => 'Build', id => $build_id}) unless $build;
$self->logout;
$build->run_count();
return $build;
}
sub create
{
sub check_build {
my ($name, $product) = @_;
Bugzilla->login(LOGIN_REQUIRED);
if (ref $product){
$product = $product;
}
elsif ($product =~ /^\d+$/){
$product = Bugzilla::Testopia::Product->new($product);
}
else {
$product = Bugzilla::Product::check_product($product);
}
return Bugzilla::Testopia::Build->new(check_build($name, $product));
}
sub create{
my $self = shift;
my ($new_values) = @_; # Required: name, product_id
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
$new_values->{'milestone'} ||= '---';
my $build = Bugzilla::Testopia::Build->create($new_values);
$self->logout;
# Result is new build id
return $build->id;
}
sub update
{
my $self =shift;
my ($build_id, $new_values) = @_; # Modifiable: name, description, milestone
$self->login;
my $build = new Bugzilla::Testopia::Build($build_id);
if (not defined $build)
{
$self->logout;
die "Build, " . $build_id . ", not found";
}
my $name = $$new_values{name};
if (defined($name) && check_build($name, new Bugzilla::Product($build->product_id)))
{
die "Build name, " . $name . ", already exists";
}
if (!defined($name))
{
$name = $build->name();
}
my $description = (defined($$new_values{description}) ? $$new_values{description} : $build->description());
my $milestone = (defined($$new_values{milestone}) ? $$new_values{milestone} : $build->milestone());
$build->set_name($name);
$build->set_description($description);
$build->set_milestone($milestone);
$build->update;
$self->logout;
# Result is modified build, otherwise an exception will be thrown
# Result is new build
return $build;
}
sub update{
my $self = shift;
my ($ids, $new_values) = @_;
Bugzilla->login(LOGIN_REQUIRED);
my @ids;
if (ref $ids eq 'ARRAY'){
@ids = @$ids;
}
elsif ($ids =~ /,/){
@ids = split(/[\s,]+/, $ids);
}
else {
push @ids, $ids;
}
my @builds;
foreach my $id (@ids){
my $build = new Bugzilla::Testopia::Build($id);
unless ($build){
ThrowUserError("invalid-test-id-non-existent", {'id' => $id, 'type' => 'Build'}) if scalar @ids == 1;
push @builds, {FAILED => 1, message => "Build $id does not exist"};
next;
}
if (exists $new_values->{'name'}){
check_build($new_values->{'name'}, $build->product) if scalar @ids == 1;
eval {check_build($new_values->{'name'}, $build->product)};
if ($@){
push @builds, {FAILED => 1, message => "A Build named " . $new_values->{'name'} . " already exists in the selected product."};
next;
}
}
if (exists $new_values->{'milestone'}){
Bugzilla::Milestone::check_milestone($build->product, $new_values->{'milestone'}) if scalar @ids == 1;
eval {Bugzilla::Milestone::check_milestone($build->product, $new_values->{'milestone'})};
if ($@){
push @builds, {FAILED => 1, message => "Invalid milestone"};
next;
}
}
$build->set_name($new_values->{'name'}) if $new_values->{'name'};
$build->set_description($new_values->{'description'}) if exists $new_values->{'description'};
$build->set_milestone($new_values->{'milestone'}) if $new_values->{'milestone'};
$build->set_isactive($new_values->{'isactive'} =~ /(true|1|yes)/i ? 1 : 0) if exists $new_values->{'isactive'};
$build->update;
return $build if scalar @ids == 1;
}
return @builds;
}
# DEPRECATED use Build::get instead
sub lookup_name_by_id
{
my $self = shift;
my ($build_id) = @_;
Bugzilla->login(LOGIN_REQUIRED);
die "Invalid Build ID"
unless defined $build_id && length($build_id) > 0 && $build_id > 0;
$self->login;
my $build = new Bugzilla::Testopia::Build($build_id);
my $result = defined $build ? $build->name : '';
$self->logout;
# Result is build name string or empty string if failed
return $result;
}
# DEPRECATED use Build::check_build($name, $product_obj) instead
# DEPRECATED use Build::check_build($name, $product) instead
sub lookup_id_by_name
{
my $self = shift;
my ($name) = @_;
$self->login;
Bugzilla->login(LOGIN_REQUIRED);
my $result = Bugzilla::Testopia::Build::check_build_by_name($name);
$self->logout;
if (!defined $result)
{
$result = 0;
@@ -143,4 +169,108 @@ sub lookup_id_by_name
return $result;
}
1;
1;
__END__
=head1 NAME
Bugzilla::Testopia::Webservice::Build
=head1 EXTENDS
Bugzilla::Webservice
=head1 DESCRIPTION
Provides methods for automated scripts to manipulate Testopia Builds
=head1 METHODS
=over
=item C<get($id)>
Description: Used to load an existing build from the database.
Params: $id - An integer representing the ID in the database
Returns: A blessed Bugzilla::Testopia::Build object hash
=item C<check_build($name, $product)>
Description: Creates a new build object and stores it in the database
Params: $name - String: name of the build.
$product - Integer/String/Object
Integer: product_id of the product in the Database
String: Product name
Object: Blessed Bugzilla::Product object
Returns: Hash: Matching Build object hash.
=item C<update($ids, $values)>
Description: Updates the fields of the selected build or builds.
Params: $ids - Integer/String/Array
Integer: A single build ID.
String: A comma separates string of Build IDs for batch
processing.
Array: An array of build IDs for batch mode processing
$values - Hash of keys matching Build fields and the new values
to set each field to.
Returns: Hash/Array: In the case of a single build it is returned. If a
list was passed, it returns an array of build hashes. If the
update on any particular build failed, the has will contain a
FAILED key and the message as to why it failed.
=item C<create($values)>
Description: Creates a new build object and stores it in the database
Params: $values - Hash: A reference to a hash with keys and values
matching the fields of the build to be created.
See Bugzilla::Testopia::Build for a list of required fields.
Returns: The newly created object hash.
=item C<update($ids, $values)>
Description: Updates the fields of the selected build or builds.
Params: $ids - Integer/String/Array
Integer: A single build ID.
String: A comma separates string of Build IDs for batch
processing.
Array: An array of build IDs for batch mode processing
$values - Hash of keys matching Build fields and the new values
to set each field to.
Returns: Hash/Array: In the case of a single build, it is returned. If a
list was passed, it returns an array of build hashes. If the
update on any particular build failed, the hash will contain a
FAILED key and the message as to why it failed.
=item C<lookup_name_by_id> B<DEPRICATED> Use Build::get instead
=item C<lookup_id_by_name> B<DEPRICATED - CONSIDERED HARMFUL> Use Build::check_build instead
=back
=head1 SEE ALSO
=over
L<Bugzilla::Testopia::Build>
L<Bugzilla::Webservice>
=back
=head1 AUTHOR
Greg Hendricks <ghendricks@novell.com>

View File

@@ -177,20 +177,20 @@ sub update
die "Update of TestCase's author_id is not allowed";
}
$test_case->set_case_status($new_values->{'case_status_id'});
$test_case->set_category($new_values->{'category_id'});
$test_case->set_priority($new_values->{'priority_id'});
$test_case->set_default_tester($new_values->{'default_tester_id'});
$test_case->set_sortkey($new_values->{'sortkey'});
$test_case->set_requirement($new_values->{'requirement'});
$test_case->set_isautomated($new_values->{'isautomated'});
$test_case->set_script($new_values->{'script'});
$test_case->set_arguments($new_values->{'arguments'});
$test_case->set_summary($new_values->{'summary'});
$test_case->set_alias($new_values->{'alias'});
$test_case->set_estimated_time($new_values->{'estimated_time'});
$test_case->set_dependson($new_values->{'dependson'});
$test_case->set_blocks($new_values->{'blocks'});
$test_case->set_case_status($new_values->{'case_status_id'}) if exists $new_values->{'case_status_id'};
$test_case->set_category($new_values->{'category_id'}) if exists $new_values->{'category_id'};
$test_case->set_priority($new_values->{'priority_id'}) if exists $new_values->{'priority_id'};
$test_case->set_default_tester($new_values->{'default_tester_id'}) if exists $new_values->{'default_tester_id'};
$test_case->set_sortkey($new_values->{'sortkey'}) if exists $new_values->{'sortkey'};
$test_case->set_requirement($new_values->{'requirement'}) if exists $new_values->{'requirement'};
$test_case->set_isautomated($new_values->{'isautomated'}) if exists $new_values->{'isautomated'};
$test_case->set_script($new_values->{'script'}) if exists $new_values->{'script'};
$test_case->set_arguments($new_values->{'arguments'}) if exists $new_values->{'arguments'};
$test_case->set_summary($new_values->{'summary'}) if exists $new_values->{'summary'};
$test_case->set_alias($new_values->{'alias'}) if exists $new_values->{'alias'};
$test_case->set_estimated_time($new_values->{'estimated_time'}) if exists $new_values->{'estimated_time'};
$test_case->set_dependson($new_values->{'dependson'}) if exists $new_values->{'dependson'};
$test_case->set_blocks($new_values->{'blocks'}) if exists $new_values->{'blocks'};
$test_case->update();

View File

@@ -53,6 +53,8 @@ use strict;
use Getopt::Long;
use Pod::Usage;
use XMLRPC::Lite;
use File::Basename qw(dirname);
use HTTP::Cookies;
my $help;
my $Bugzilla_uri;
@@ -149,7 +151,12 @@ pod2usage({'-verbose' => 1, '-exitval' => 0}) if $help;
syntaxhelp('URI unspecified') unless $Bugzilla_uri;
my $proxy = XMLRPC::Lite->proxy($Bugzilla_uri);
my $cookie_jar =
new HTTP::Cookies('file' => File::Spec->catdir(dirname($0), 'cookies.txt'),
'autosave' => 1);
my $proxy = XMLRPC::Lite->proxy($Bugzilla_uri,
'cookie_jar' => $cookie_jar);
my $query = {
'field0-0-0' => 'author',
@@ -157,8 +164,22 @@ my $query = {
'value0-0-0' => 'Second'
};
if (defined($Bugzilla_login)) {
if ($Bugzilla_login ne '') {
# Log in.
$soapresult = $proxy->call('User.login',
{ login => $Bugzilla_login,
password => $Bugzilla_password } );
print "Login successful.\n";
}
else {
# Log out.
$soapresult = $proxy->call('User.logout');
print "Logout successful.\n";
}
}
$soapresult = $proxy->call('TestPlan.list', {type_id=>4, pagesize=>1000});
#$soapresult = $proxy->call('TestPlan.list', {type_id=>4, pagesize=>1000});
#$soapresult = $proxy->call('TestPlan.list', {page=>0, pagesize=>10});
#$soapresult = $proxy->call('TestPlan.lookup_type_name_by_id', 1);
#$soapresult = $proxy->call('TestPlan.lookup_type_id_by_name', 'unit2');
@@ -203,7 +224,7 @@ $soapresult = $proxy->call('TestPlan.list', {type_id=>4, pagesize=>1000});
#$soapresult = $proxy->call('TestRun.get_test_cases', 1758);
#$soapresult = $proxy->call('TestRun.get_test_case_runs', 1);
#$soapresult = $proxy->call('TestPlan.get_builds', 2);
#$soapresult = $proxy->call('Build.get', 2);
$soapresult = $proxy->call('Build.get', 2);
#$soapresult = $proxy->call('Build.create', {name=>'Another Build', product_id=>1});
#$soapresult = $proxy->call('Build.update', 2, {name=>'Second Build', description=>'desc', milestone=>'hmm'});
#$soapresult = $proxy->call('Build.update', 2, {milestone=>'hmm3'});

View File

@@ -14,96 +14,6 @@ diff -u -r1.141 editusers.cgi
'fielddefs READ',
'tokens WRITE',
'logincookies WRITE',
Index: Bugzilla/WebService.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/WebService.pm,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 WebService.pm
--- Bugzilla/WebService.pm 26 Mar 2007 07:57:32 -0000 1.5.2.1
+++ Bugzilla/WebService.pm 25 Jun 2007 21:41:54 -0000
@@ -14,10 +14,12 @@
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Max Kanat-Alexander <mkanat@bugzilla.org>
+# Dallas Harken <dharken@novell.com>
package Bugzilla::WebService;
use strict;
+use Bugzilla::Config;
use Bugzilla::WebService::Constants;
use Date::Parse;
@@ -48,9 +50,48 @@
Bugzilla->login;
}
+sub login {
+ my $self = shift;
+
+ # Check for use of iChain first
+ if (Bugzilla->params->{'user_verify_class'} ne 'iChain')
+ {
+ #
+ # Check for use of Basic Authorization
+ #
+ # WARNING - Your must modify your Apache server's configuration
+ # to allow the HTTP_AUTHORIZATION env parameter to be passed through!
+ # This requires using the rewrite module.
+ #
+ if (defined($ENV{'HTTP_AUTHORIZATION'}))
+ {
+ if ($ENV{'HTTP_AUTHORIZATION'} =~ /^Basic +(.*)$/os)
+ {
+ # HTTP Basic Authentication
+ my($login, $password) = split(/:/, MIME::Base64::decode_base64($1), 2);
+
+ my $cgi = Bugzilla->cgi;
+ $cgi->param("Bugzilla_login", $login);
+ $cgi->param("Bugzilla_password", $password);
+ }
+ }
+ }
+
+ Bugzilla->login;
+}
+
+sub logout
+{
+# Testopia's method does not persist anything so logout in unneccessary.
+# my $self = shift;
+#
+# Bugzilla->logout;
+}
+
package Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI;
use strict;
+use Bugzilla::WebService::Constants;
eval 'use base qw(XMLRPC::Transport::HTTP::CGI)';
sub make_response {
@@ -65,6 +106,13 @@
}
}
+sub make_fault {
+ my $self = shift;
+
+ # RPC Fault Code must be an integer
+ $self->SUPER::make_fault(ERROR_FAULT_SERVER, $_[1]);
+}
+
1;
__END__
@@ -131,4 +179,4 @@
Sometimes a function will throw an error that doesn't have a specific
error code. In this case, the code will be C<-32000> if it's a "fatal"
-error, and C<32000> if it's a "transient" error.
+error, and C<32000> if it's a "transient" error.
\ No newline at end of file
Index: template/en/default/global/common-links.html.tmpl
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/template/en/default/global/common-links.html.tmpl,v
@@ -278,23 +188,6 @@ diff -u -r1.148 User.pm
my $user = $class->SUPER::create(@_);
Index: Bugzilla/WebService/Constants.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/WebService/Constants.pm,v
retrieving revision 1.6
diff -u -r1.6 Constants.pm
--- Bugzilla/WebService/Constants.pm 4 Feb 2007 16:23:21 -0000 1.6
+++ Bugzilla/WebService/Constants.pm 25 Jun 2007 22:07:59 -0000
@@ -21,6 +21,9 @@
use base qw(Exporter);
@Bugzilla::WebService::Constants::EXPORT = qw(
+ ERROR_GENERAL
+ ERROR_FAULT_SERVER
+
WS_ERROR_CODE
ERROR_UNKNOWN_FATAL
ERROR_UNKNOWN_TRANSIENT
Index: Bugzilla/WebService/User.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/WebService/User.pm,v

View File

@@ -130,96 +130,6 @@ diff -u -r1.19.2.3 Error.pm
}
exit;
}
Index: Bugzilla/WebService.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/WebService.pm,v
retrieving revision 1.5.2.1
diff -u -r1.5.2.1 WebService.pm
--- Bugzilla/WebService.pm 26 Mar 2007 07:57:32 -0000 1.5.2.1
+++ Bugzilla/WebService.pm 29 Feb 2008 23:19:44 -0000
@@ -14,10 +14,12 @@
#
# Contributor(s): Marc Schumann <wurblzap@gmail.com>
# Max Kanat-Alexander <mkanat@bugzilla.org>
+# Dallas Harken <dharken@novell.com>
package Bugzilla::WebService;
use strict;
+use Bugzilla::Config;
use Bugzilla::WebService::Constants;
use Date::Parse;
@@ -48,9 +50,48 @@
Bugzilla->login;
}
+sub login {
+ my $self = shift;
+
+ # Check for use of iChain first
+ if (Bugzilla->params->{'user_verify_class'} ne 'iChain')
+ {
+ #
+ # Check for use of Basic Authorization
+ #
+ # WARNING - Your must modify your Apache server's configuration
+ # to allow the HTTP_AUTHORIZATION env parameter to be passed through!
+ # This requires using the rewrite module.
+ #
+ if (defined($ENV{'HTTP_AUTHORIZATION'}))
+ {
+ if ($ENV{'HTTP_AUTHORIZATION'} =~ /^Basic +(.*)$/os)
+ {
+ # HTTP Basic Authentication
+ my($login, $password) = split(/:/, MIME::Base64::decode_base64($1), 2);
+
+ my $cgi = Bugzilla->cgi;
+ $cgi->param("Bugzilla_login", $login);
+ $cgi->param("Bugzilla_password", $password);
+ }
+ }
+ }
+
+ Bugzilla->login;
+}
+
+sub logout
+{
+# Testopia's method does not persist anything so logout in unneccessary.
+# my $self = shift;
+#
+# Bugzilla->logout;
+}
+
package Bugzilla::WebService::XMLRPC::Transport::HTTP::CGI;
use strict;
+use Bugzilla::WebService::Constants;
eval 'use base qw(XMLRPC::Transport::HTTP::CGI)';
sub make_response {
@@ -65,6 +106,13 @@
}
}
+sub make_fault {
+ my $self = shift;
+
+ # RPC Fault Code must be an integer
+ $self->SUPER::make_fault(ERROR_FAULT_SERVER, $_[1]);
+}
+
1;
__END__
@@ -131,4 +179,4 @@
Sometimes a function will throw an error that doesn't have a specific
error code. In this case, the code will be C<-32000> if it's a "fatal"
-error, and C<32000> if it's a "transient" error.
+error, and C<32000> if it's a "transient" error.
\ No newline at end of file
Index: Bugzilla/Constants.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Constants.pm,v
@@ -353,23 +263,6 @@ diff -u -r1.4.2.1 User.pm
1;
__END__
Index: Bugzilla/WebService/Constants.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/WebService/Constants.pm,v
retrieving revision 1.6.2.2
diff -u -r1.6.2.2 Constants.pm
--- Bugzilla/WebService/Constants.pm 18 Sep 2007 23:30:20 -0000 1.6.2.2
+++ Bugzilla/WebService/Constants.pm 29 Feb 2008 23:19:45 -0000
@@ -21,6 +21,9 @@
use base qw(Exporter);
@Bugzilla::WebService::Constants::EXPORT = qw(
+ ERROR_GENERAL
+ ERROR_FAULT_SERVER
+
WS_ERROR_CODE
ERROR_UNKNOWN_FATAL
ERROR_UNKNOWN_TRANSIENT
Index: Bugzilla/Install/Filesystem.pm
===================================================================
RCS file: /cvsroot/mozilla/webtools/bugzilla/Bugzilla/Install/Filesystem.pm,v