Skip to content

Commit 3e55d80

Browse files
committed
temporary patch to address Rally WSAPI v2.0 defect with projects collection endpoint when user is not a subscription admin and the user has no visibility to some projects in a workspace
1 parent 4cb3371 commit 3e55d80

42 files changed

Lines changed: 4442 additions & 440 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

README.rst

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ relevant packages.
5959
>> import requests
6060
>> import pyral
6161
>> pyral.__version__
62-
(1, 0, 0)
62+
(1, 0, 1)
6363

6464

6565

@@ -259,6 +259,9 @@ Prerequisites
259259
Versions
260260
--------
261261

262+
* 1.0.1 - Patch to address defect with Rally WSAPI v2.0 projects collection endpoint
263+
providing conflicting information.
264+
262265
* 1.0.0 -
263266
Default WSAPI version in config is v2.0. This version is not compatible
264267
with Rally WSAPI version 1.x.

VERSIONS

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,4 +52,11 @@
5252
Added UserIterationCapacity, Fixed the *CumulativeFlowData entity names.
5353
Added internal facility to accept Rally reference identifiers in a list form and convert them
5454
to a list of dicts with each dict containing a key-value pair for '_ref' and associated value.
55-
Added a details method for any WorkspaceDomain derived entity instance.
55+
Added a details method for any WorkspaceDomain derived entity instance.
56+
57+
1.0.0 - May 2014
58+
Upped default WSAPI version to v2.0 and stated in docs that prior WSAPI versions (1.x) were no longer supported.
59+
60+
1.0.1 - June 2014
61+
Patch to address flaw in WSAPI v2.0 projects collection endpoint having a mismatch between TotalResultCount and
62+
actual information about projects.

build/lib/pyral/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
__version__ = (1, 0, 0)
2+
from .config import rallySettings
3+
from .restapi import Rally, RallyRESTAPIError, RallyUrlBuilder
4+
from .rallyresp import RallyRESTResponse
5+

build/lib/pyral/config.py

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
#!/opt/local/bin/python2.6
2+
3+
###################################################################################################
4+
#
5+
# pyral.config - config and "consts" for the Rally 'pyral' package for REST API operations
6+
#
7+
###################################################################################################
8+
9+
__version__ = (1, 0, 0)
10+
11+
import datetime
12+
import os
13+
import platform
14+
import re
15+
import glob
16+
17+
###################################################################################################
18+
19+
PROTOCOL = "https"
20+
SERVER = "rally1.rallydev.com"
21+
WEB_SERVICE = "slm/webservice/%s"
22+
SCHEMA_SERVICE = "slm/schema/%s"
23+
AUTH_ENDPOINT = "security/authorize"
24+
WS_API_VERSION = "v2.0"
25+
26+
USER_NAME = "wiley@acme.com"
27+
PASSWORD = "G3ronim0!"
28+
29+
START_INDEX = 1
30+
PAGESIZE = 100
31+
MAX_PAGESIZE = 200
32+
MAX_ITEMS = 1000000 # a million seems an eminently reasonable limit ...
33+
34+
RALLY_REST_HEADERS = \
35+
{
36+
#'X-RallyIntegrationName' : 'Python toolkit for Rally REST API', # although syntactically this is the more correct
37+
'X-RallyIntegrationName' : 'Rally REST API toolkit for Python', # this matches the format of the other language toolkits
38+
'X-RallyIntegrationVendor' : 'Rally Software Development',
39+
'X-RallyIntegrationVersion' : '%s.%s.%s' % __version__,
40+
'X-RallyIntegrationLibrary' : 'pyral-%s.%s.%s' % __version__,
41+
'X-RallyIntegrationPlatform' : 'Python %s' % platform.python_version(),
42+
'X-RallyIntegrationOS' : platform.platform(),
43+
'User-Agent' : 'Pyral Rally WebServices Agent',
44+
'Content-Type' : 'application/json',
45+
'Accept-Encoding' : 'gzip'
46+
}
47+
48+
##################################################################################################
49+
50+
def timestamp():
51+
# for now, don't worry about timezone fluff, and cut off the microseconds to become millis
52+
return datetime.datetime.today().strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
53+
54+
##################################################################################################
55+
56+
CONFIG_SETTING_PATT = re.compile('^([A-Z]+)\s*=\s*(.+)$')
57+
RALLY_ARG_SETTING_PATT1 = re.compile('^--(rally[SUPW][a-z]+)=(.+)\s*$')
58+
RALLY_ARG_SETTING_PATT2 = re.compile('^--([SUPWsupw][a-z]+)=(.+)\s*$')
59+
RALLY_CONFIG_FILE_PATT = re.compile('^--(cfg|conf|config|rallyConfig)=(\S+)$')
60+
61+
################################################################################
62+
63+
def rallySettings(args):
64+
"""
65+
priority order of Python Rally REST API server ident, credentials, workspace/project:
66+
1) command line args with --rallyServer, --rallyUser, --rallyPassword, --workspace, --project
67+
2) command line arg specifying a config file --rallyConfig=<config_file_name>
68+
or --config=<config_file_name>
69+
or --conf=<config_file_name>
70+
or --cfg=<config_file_name>
71+
3) ENV variable with location of rally-<version>.cfg --> RALLY_CONFIG
72+
4) current directory with rally-<version>.cfg
73+
5) RALLY_SERVER, RALLY_USER_NAME, RALLY_PASSWORD, RALLY_WORKSPACE, RALLY_PROJECT env VARS
74+
6) SERVER, USER_NAME, PASSWORD defined in this module
75+
76+
start by priming the return values with #6 and work your way up the priority ladder
77+
"""
78+
# #6
79+
# start with the defaults defined in this module
80+
server_creds = [SERVER, USER_NAME, PASSWORD, "default", "default"]
81+
82+
def snarfSettings(targetFile, server_creds):
83+
"""
84+
read the filename and look for lines containing relevant Rally settings.
85+
alter the server_creds list if there are entries in the file to do so.
86+
"""
87+
if not os.path.exists(targetFile):
88+
cfg_suffixed = "%s.cfg" % targetFile
89+
if not os.path.exists(cfg_suffixed):
90+
return server_creds
91+
else:
92+
targetFile = cfg_suffixed
93+
94+
try:
95+
cf = open(targetFile, 'r')
96+
for line in cf:
97+
mo = CONFIG_SETTING_PATT.match(line)
98+
if mo:
99+
item, value = mo.groups()
100+
if item == 'SERVER':
101+
server_creds[0] = value
102+
elif item == 'USER':
103+
server_creds[1] = value
104+
elif item == 'PASSWORD':
105+
server_creds[2] = value
106+
elif item == 'WORKSPACE':
107+
server_creds[3] = value
108+
elif item == 'PROJECT':
109+
server_creds[4] = value
110+
cf.close()
111+
sc = "%s, %s, %s, %s, %s" % tuple(server_creds)
112+
return server_creds
113+
except Exception as ex:
114+
pass
115+
116+
# #5
117+
# if there are environment vars, use them
118+
#
119+
for ix, name in enumerate(['RALLY_SERVER', 'RALLY_USER', 'RALLY_PASSWORD', 'RALLY_WORKSPACE', 'RALLY_PROJECT']):
120+
if name in os.environ:
121+
server_creds[ix] = name
122+
123+
# #4
124+
# if there is a rally-<version>.cfg file in the current directory matching the WS_API_VERSION
125+
# load with contents of that file
126+
entries = glob.glob('rally-*.cfg')
127+
target_version_config = 'rally-%s.cfg' % WS_API_VERSION
128+
if entries:
129+
if target_version_config in entries:
130+
server_creds = snarfSettings(target_version_config, server_creds)
131+
else:
132+
print "Ignoring non-matching version of Rally config settings: %s (working version: %s)" % \
133+
(entries.pop(), WS_API_VERSION)
134+
135+
# #3
136+
# if there is a RALLY_CONFIG environment variable pointing to a file, load with contents of file
137+
config_file = os.environ.get('RALLY_CONFIG', None)
138+
if config_file:
139+
server_creds = snarfSettings(config_file, server_creds)
140+
141+
# #2
142+
# now look at the args (from command line invocation)
143+
# grab any --(rallyConfig|config|conf|cfg)=<filename> args,
144+
# and if filename exists attempt to load with contents therein
145+
for arg in args:
146+
mo = RALLY_CONFIG_FILE_PATT.match(arg)
147+
if mo:
148+
config_name, config_file = mo.groups()
149+
server_creds = snarfSettings(config_file, server_creds)
150+
151+
# #1
152+
# now look at the args (from command line invocation)
153+
# grab any --rallyServer=?, --rallyUser=?, --rallyPassword=?, --rallyWorkspace=?, --rallyProject=? in args
154+
# grab any --server=?, --user=?, --password=?, --workspace=?, --project=? in args
155+
for arg in args:
156+
mo = RALLY_ARG_SETTING_PATT1.match(arg)
157+
if mo:
158+
item, value = mo.groups()
159+
if item == 'rallyServer':
160+
server_creds[0] = value
161+
elif item == 'rallyUser':
162+
server_creds[1] = value
163+
elif item == 'rallyPassword':
164+
server_creds[2] = value
165+
elif item == 'rallyWorkspace':
166+
server_creds[3] = value
167+
elif item == 'rallyProject':
168+
server_creds[4] = value
169+
170+
mo = RALLY_ARG_SETTING_PATT2.match(arg)
171+
if mo:
172+
item, value = mo.groups()
173+
if item == 'server':
174+
server_creds[0] = value
175+
elif item == 'user':
176+
server_creds[1] = value
177+
elif item == 'password':
178+
server_creds[2] = value
179+
elif item == 'workspace':
180+
server_creds[3] = value
181+
elif item == 'project':
182+
server_creds[4] = value
183+
184+
return server_creds
185+

0 commit comments

Comments
 (0)