Skip to content

Commit 7e880b5

Browse files
committed
oslcquery now doesn't fail when confgurations have been archived
1 parent 3384ce0 commit 7e880b5

Some content is hidden

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

69 files changed

+16132
-16684
lines changed

elmclient/_ccm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ def resolve_uri_to_name(self, uri, trytouseasid=False):
281281
result = self.server.jts.user_uritoname_resolver(uri)
282282
else:
283283
if uri.startswith( "http://" ) or uri.startswith( "https://" ):
284-
uri1 = rdfxml.uri_to_prefixed_tag(uri)
284+
uri1 = rdfxml.uri_to_prefixed_tag(uri, oktocreate=False,noexception=True)
285285
logger.debug( f"Returning the raw URI {uri} so changed it to prefixed {uri1}" )
286286
uri = uri1
287287
result = uri

elmclient/_queryparser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
#
1818
# This enhanced OSLC Query grammar supports "||", "&&" and bracketed evaluation
19-
# This is based on the EBNF in OSLC Query 3.0 standard https://tools.oasis-open.org/version-control/browse/wsvn/oslc-core/trunk/specs/oslc-query.html
19+
# This is based on the EBNF in OSLC Query 3.0 standard https://docs.oasis-open-projects.org/oslc-op/query/v3.0/os/oslc-query.html
2020
# Differences/enhancements from the OSLC 3.0 definition:
2121
# You can combine compound_terms using && and || - note when using these the compound_term MUST be in ( ) (which also makes reading the expression easier)
2222
# also accepts just a single compound_term with no ( ) needed (i.e. this is basically the vanilla OSLC Query 3.0 syntax)

elmclient/_rm.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,11 @@ def load_components_and_configurations(self,force=False, cacheable=True):
358358
configs = self.execute_get_xml(compuri+"/configurations", intent="Retrieve project/component's list of all configurations", cacheable=cacheable)
359359
for conf in rdfxml.xml_find_elements(configs,'.//rdfs:member'):
360360
confu = rdfxml.xmlrdf_get_resource_uri(conf)
361-
thisconfx = self.execute_get_xml(confu, intent="Retrieve a configuration definition", cacheable=cacheable)
361+
try:
362+
thisconfx = self.execute_get_xml(confu, intent="Retrieve a configuration definition", cacheable=cacheable)
363+
except:
364+
logger.info( f"Singlemode config ERROR probably archived {confu} !!!!!!!" )
365+
continue
362366
conftitle= rdfxml.xmlrdf_get_resource_text(thisconfx,'.//dcterms:title')
363367
created = rdfxml.xmlrdf_get_resource_uri(thisconfx, './/dcterms:created')
364368
# e.g. http://open-services.net/ns/config#Stream
@@ -396,7 +400,11 @@ def load_components_and_configurations(self,force=False, cacheable=True):
396400
confs = configs["http://www.w3.org/2000/01/rdf-schema#member"]
397401
for aconf in confs:
398402
confu = aconf['@id']
399-
confx = self.execute_get_xml(confu, intent="Retrieve configuration definition RDF", cacheable=cacheable)
403+
try:
404+
confx = self.execute_get_xml(confu, intent="Retrieve configuration definition RDF", cacheable=cacheable)
405+
except:
406+
logger.info( f"Old optin config ERROR probably archived {confu} !!!!!!!" )
407+
continue
400408
conftitle = rdfxml.xmlrdf_get_resource_text(confx,'.//dcterms:title')
401409
conftype = 'Stream' if 'stream' in confu else 'Baseline'
402410
created = rdfxml.xmlrdf_get_resource_uri(confx, './/dcterms:created')
@@ -522,7 +530,7 @@ def load_configs(self, cacheable=True ):
522530
try:
523531
configs_xml = self.execute_get_rdf_xml(confu, intent="Retrieve a configuration definition", cacheable=cacheable)
524532
except:
525-
logger.info( f"Config ERROR {thisconfu} !!!!!!!" )
533+
logger.info( f"Config ERROR {thisconfu} ignored (the config was probably archived) !!!!!!!" )
526534
continue
527535

528536
confmemberx = rdfxml.xml_find_elements(configs_xml, './/rdfs:member[@rdf:resource]')

elmclient/examples/oneperminute.py

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
##
2+
## © Copyright 2021- IBM Inc. All rights reserved
3+
# SPDX-License-Identifier: MIT
4+
##
5+
6+
# Test for authentication timeout
7+
# retrieve a protected resource with login, then
8+
# sits retreiving it every minute with login disabled, i.e. until login fails
9+
# due to authentication timeout
10+
11+
#import csv
12+
import logging
13+
14+
import time
15+
16+
import lxml.etree as ET
17+
18+
import elmclient.server as elmserver
19+
import elmclient.utils as utils
20+
import elmclient.rdfxml as rdfxml
21+
22+
# setup logging - see levels in utils.py
23+
#loglevel = "INFO,INFO"
24+
loglevel = "TRACE,OFF"
25+
levels = [utils.loglevels.get(l,-1) for l in loglevel.split(",",1)]
26+
if len(levels)<2:
27+
# assert console logging level OFF if not provided
28+
levels.append(None)
29+
if -1 in levels:
30+
raise Exception( f'Logging level {loglevel} not valid - should be comma-separated one or two values from DEBUG, INFO, WARNING, ERROR, CRITICAL, OFF' )
31+
utils.setup_logging( filelevel=levels[0], consolelevel=levels[1] )
32+
33+
logger = logging.getLogger(__name__)
34+
35+
POLLINTERVAL=10
36+
37+
jazzhost = 'https://jazz.ibm.com:9443'
38+
username = 'ibm'
39+
password = 'ibm'
40+
#username = 'tokenuser'
41+
#password = 'tokenuser'
42+
43+
protected_u = jazzhost+"/rm/process/project-areas"
44+
45+
jtscontext = 'jts' # specifies /jts change to e.g. jts:jts23 if your jts is on a different context root such as /jts23
46+
rmcontext = 'rm' # specifies /ccm change to e.g. ccm:ccm2 if your ccm is on a different context root such as /ccm2
47+
48+
#proj = "SGC Planning and Tasks"
49+
50+
#workitemid=38
51+
52+
#outfile = "ccm_simple_findworkitem_output.csv"
53+
54+
# caching control
55+
# 0=fully cached (but code below specifies queries aren't cached)
56+
# 1=clear cache initially then continue with cache enabled
57+
# 2=clear cache and disable caching
58+
caching = 2
59+
60+
# create our "server" which is how we connect to EWM
61+
# first enable the proxy so if a proxy is running it can monitor the communication with server (this is ignored if proxy isn't running)
62+
elmserver.setupproxy(jazzhost,proxyport=8888)
63+
#theserver = elmserver.JazzTeamServer(jazzhost, username, password, verifysslcerts=False, jtsappstring=f"jts:{jtscontext}", appstring='rm', cachingcontrol=caching)
64+
theserver = elmserver.JazzTeamServer(jazzhost, username, password, verifysslcerts=False, jtsappstring=f"jts:{jtscontext}", cachingcontrol=caching)
65+
66+
# create the RM application interface
67+
#rmapp = theserver.find_app( f"rm:{rmcontext}", ok_to_create=True )
68+
69+
#p = ccmapp.find_project( proj )
70+
71+
starttime = time.perf_counter()
72+
nextendtime = starttime
73+
autologin = True
74+
75+
while True:
76+
# now retrieve the protected resource
77+
elapsedsecs = time.perf_counter() - starttime
78+
print( f"Runtime {int(elapsedsecs/60)}m {int(elapsedsecs%60):02d}s" )
79+
80+
resource_x = theserver.execute_get_xml( protected_u, intent="Retrieve protected resource", automaticlogin=autologin, close=True )
81+
82+
autologin = False
83+
84+
while nextendtime < time.perf_counter():
85+
nextendtime += POLLINTERVAL
86+
87+
time.sleep( nextendtime - time.perf_counter() )
88+
89+
if utils.kbhit():
90+
ch = utils.getch()
91+
print( f"{ch=}" )
92+
if ch == b'\x1b':
93+
break
94+
95+
print( "Finished" )

elmclient/examples/oslcquery.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ def do_oslc_query(inputargs=None):
207207

208208
utils.log_commandline( os.path.basename(sys.argv[0]),inputargs )
209209

210-
if args.password is None:
210+
if args.password is None or args.password=="PROMPT":
211211
args.password = getpass.getpass(prompt=f'Password for user {args.username}: ')
212212

213213
# request proxy config if appropriate

elmclient/httpops.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# SPDX-License-Identifier: MIT
44
##
55

6+
67
import codecs
78
import html.parser
89
import http
@@ -558,7 +559,7 @@ def get_auth_path(self, request_url, response):
558559
# 1. if the response indicates login is required then login and try the request again
559560
# 2. if request is rejected for various reasons retry with the CSRF header applied
560561
# supports Jazz Form authorization and Jazz Authorization Server login
561-
def _execute_one_request_with_login( self, *, no_error_log=False, close=False, donotlogbody=False, retry_get_after_login=True, remove_headers=None, remove_parameters=None, intent=None, action = None ):
562+
def _execute_one_request_with_login( self, *, no_error_log=False, close=False, donotlogbody=False, retry_get_after_login=True, remove_headers=None, remove_parameters=None, intent=None, action = None, automaticlogin=True ):
562563
# if intent is None:
563564
# raise Exception( "No intent provided!" )
564565
intent = intent or ""
@@ -610,6 +611,13 @@ def _execute_one_request_with_login( self, *, no_error_log=False, close=False, d
610611

611612
response.raise_for_status()
612613

614+
if not automaticlogin:
615+
# print( f"No auto login {response}" )
616+
return response
617+
else:
618+
# print( f"auto login allowed {response}" )
619+
pass
620+
613621
# check for a non-error response which also indicates that authentication is needed using
614622
# a special header (in which case the response is not the data requested)
615623
if 'X-com-ibm-team-repository-web-auth-msg' in response.headers:
@@ -622,6 +630,9 @@ def _execute_one_request_with_login( self, *, no_error_log=False, close=False, d
622630
retry_after_login_needed = True
623631

624632
except requests.HTTPError as e:
633+
if not automaticlogin:
634+
# the only real reason to be here is due to needing auth!
635+
raise
625636
if not no_error_log:
626637
logger.trace( f"HTTPError {e}" )
627638
if e.response.status_code == 401 and 'X-jazz-web-oauth-url' in e.response.headers:
@@ -756,11 +767,12 @@ def _jsa_login(self, auth_url, ap_redirect_url, url):
756767
# step 2 - check for response indicating
757768
# if auth_url_response.status_code != 200 or 'X-JSA-LOGIN-REQUIRED' not in auth_url_response.headers:
758769

759-
if auth_url_response.status_code != 200 and not ap_redirect-Url:
770+
if auth_url_response.status_code != 200 and not ap_redirect_url:
760771
return auth_url_response # no more auth required
761772
if ap_redirect_url and auth_url_response.status_code==401:
762773
if not authurl_response.headers.get( 'WWW-Authenticate',"" ).startswith( "Negotiate"):
763774
return auth_url_response # no more auth required
775+
764776
if ap_redirect_url and 'X-JSA-LOGIN-REQUIRED' not in auth_url_response.headers:
765777
# app password login
766778
# decide if SAML or OIDC, or perhaps we are authenticated and there's nothing else to do!
@@ -779,7 +791,7 @@ def _jsa_login(self, auth_url, ap_redirect_url, url):
779791
# do the login
780792
username, password = self.get_user_password(auth_url)
781793
appassword = self.get_app_password( url )
782-
794+
# print( f"{username=} {password=} {appassword=}" )
783795
# if redirects are automatically followed on this call to authenticate with the OP, the GET of the original protected resource fails, and so the authentication fails.
784796
# this may be because this GET doesn't have headers like OSLC-Core-Version.
785797
# Solution is not to follow redirects and ensure that the original GET is repeated, i.e. with the correct headers :-)
@@ -796,6 +808,7 @@ def _jsa_login(self, auth_url, ap_redirect_url, url):
796808
if auth_url_response.status_code == 200:
797809
# use basic auth - 3iii in https://jazz.net/wiki/bin/view/Main/NativeClientAuthentication
798810
username, password = self.get_user_password(auth_url)
811+
print( f"{username=} {password=}" )
799812
auth_url_response = self._session.get( str(auth_url), auth=(username, password) ) # Load up them cookies!
800813
else:
801814
logger.error('''Something about JSA OIDC login has changed since this script was written. I can no longer determine where to authorize myself.''')

0 commit comments

Comments
 (0)