1313from SnowLibrary .exceptions import QueryNotExecuted
1414
1515
16+ class Singleton :
17+ def __init__ (self , cls ):
18+ self ._cls = cls
19+
20+ def Instance (self , ** kwargs ):
21+ try :
22+ return self ._instance
23+ except AttributeError :
24+ self ._instance = self ._cls (** kwargs )
25+ return self ._instance
26+
27+ def __call__ (self ):
28+ raise TypeError ('Singletons must be accessed through `Instance()`.' )
29+
30+ def __instancecheck__ (self , inst ):
31+ return isinstance (inst , self ._cls )
32+
33+
34+ @Singleton
35+ class RESTClientImpl :
36+ """
37+ client to ServiceNow
38+ """
39+ def __init__ (self , host = None , user = None , password = None , is_admin = None ):
40+ self .__is_admin_default = True
41+
42+ self .reset ()
43+ self .__is_admin = is_admin
44+ self .__host = host
45+ self .__user = user
46+ self .__password = password
47+
48+ def reset (self ):
49+ self .__is_admin = None
50+ self .__host = None
51+ self .__user = None
52+ self .__password = None
53+ self .__client = None
54+ self .__instance = None
55+
56+ @property
57+ def is_admin (self ):
58+ if self .__is_admin is None :
59+ if "SNOW_REST_IS_ADMIN" not in os .environ :
60+ raise Exception ("not is_admin argument nor "
61+ "SNOW_REST_IS_ADMIN found in environ" )
62+ self .__is_admin = True \
63+ if os .environ .get ("SNOW_REST_IS_ADMIN" ) == "1" \
64+ else False
65+ return self .__is_admin
66+
67+ @property
68+ def host (self ):
69+ if self .__host is None :
70+ if "SNOW_TEST_URL" not in os .environ :
71+ raise Exception ("not host argument nor SNOW_TEST_URL "
72+ "found in environ" )
73+ self .__host = os .environ .get ("SNOW_TEST_URL" ).strip ()
74+ return self .__host
75+
76+ @property
77+ def user (self ):
78+ if self .__user is None :
79+ if "SNOW_REST_USER" not in os .environ :
80+ raise Exception ("not user argument nor SNOW_REST_USER "
81+ "found in environ" )
82+ self .__user = os .environ .get ("SNOW_REST_USER" )
83+ return self .__user
84+
85+ @property
86+ def password (self ):
87+ if self .__password is None :
88+ if "SNOW_REST_PASS" not in os .environ :
89+ raise Exception ("not password argument nor SNOW_REST_PASS "
90+ "found in environ" )
91+ self .__password = os .environ .get ("SNOW_REST_PASS" )
92+ return self .__password
93+
94+ @property
95+ def user (self ):
96+ if self .__user is None :
97+ if "SNOW_REST_USER" not in os .environ :
98+ raise Exception ("not user argument nor SNOW_REST_USER "
99+ "found in environ" )
100+ self .__user = os .environ .get ("SNOW_REST_USER" )
101+ return self .__user
102+
103+ @property
104+ def instance (self ):
105+ if self .__instance is None :
106+ if "http" not in self .host :
107+ self .__instance = urlparse (self .host ).path .split ("." )[0 ]
108+ else :
109+ self .__instance = urlparse (self .host ).netloc .split ("." )[0 ]
110+
111+ if self .__instance == "" :
112+ raise AssertionError (
113+ "Unable to determine SNOW Instance. Verify that the "
114+ "SNOW_TEST_URL environment variable been set." )
115+ return self .__instance
116+
117+ @property
118+ def client (self ):
119+ if self .__client is None :
120+ logger .debug ("init new client instance:{} user:{}" .format (
121+ self .instance ,
122+ self .user ))
123+ self .__client = pysnow .Client (
124+ instance = self .instance ,
125+ user = self .user ,
126+ password = self .password )
127+ return self .__client
128+
129+
130+ class RESTClient :
131+ """
132+ robotframework keywords
133+ """
134+ def __init__ (self , host = None , user = None , password = None , is_admin = None ):
135+ RESTClientImpl .Instance (host = host , user = user , password = password , is_admin = is_admin )
136+
137+ def get (self ):
138+ RESTClientImpl .Instance ()
139+ return RESTClientImpl .Instance ()
140+
141+ @keyword
142+ def get_snow_instance (self ):
143+ return RESTClientImpl .Instance ().instance
144+
145+ @keyword
146+ def get_snow_user (self ):
147+ return RESTClientImpl .Instance ().user
148+
149+ @keyword
150+ def get_snow_is_admin (self ):
151+ return RESTClientImpl .Instance ().is_admin
152+
153+ @keyword
154+ def snow_reset_client (self ):
155+ logger .info ("snow_reset_client" )
156+ RESTClientImpl .Instance ().reset ()
157+
158+
16159class RESTQuery :
17160 """
18161 This library implements keywords for retrieving current data for testing from ServiceNow. It leverages the
@@ -43,6 +186,7 @@ class RESTQuery:
43186 VALID_OPERANDS = ["AND" , "OR" , "NQ" ]
44187
45188 def __init__ (self , host = None , user = None , password = None , query_table = None , response = None ):
189+ RESTClientImpl .Instance (host = host , user = user , password = password )
46190 """
47191 The following arguments can be optionally provided when importing this library:
48192 - ``host``: The URL to your target ServiceNow instance (e.g. https://iceuat.service-now.com/). If none is provided,
@@ -55,31 +199,12 @@ def __init__(self, host=None, user=None, password=None, query_table=None, respon
55199 - ``response``: Set the response object from the ServiceNow REST API (intended to be used for testing).
56200
57201 """
58- if host is None :
59- self .host = os .environ .get ("SNOW_TEST_URL" ).strip ()
60- else :
61- self .host = host .strip ()
62- if user is None :
63- self .user = os .environ .get ("SNOW_REST_USER" )
64- else :
65- self .user = user
66- if password is None :
67- self .password = os .environ .get ("SNOW_REST_PASS" )
68- else :
69- self .password = password
70- if "http" not in self .host :
71- self .instance = urlparse (self .host ).path .split ("." )[0 ]
72- else :
73- self .instance = urlparse (self .host ).netloc .split ("." )[0 ]
74- if self .instance == "" :
75- raise AssertionError (
76- "Unable to determine SNOW Instance. Verify that the SNOW_TEST_URL environment variable been set." )
77- self .client = pysnow .Client (instance = self .instance , user = self .user , password = self .password )
78202 self .query_table = query_table
79203 self .query = pysnow .QueryBuilder ()
80204 self .response = response
81205 self .record_count = None
82206 self .desired_response_fields = list ()
207+
83208
84209 @staticmethod
85210 def _parse_datetime (date ):
@@ -263,7 +388,8 @@ def execute_query(self, multiple=False):
263388 or no table has been defined, an error is thrown.
264389 """
265390 assert self .query_table is not None , "Query table must already be specified in this test case, but is not."
266- query_resource = self .client .resource (api_path = "/table/{query_table}" .format (query_table = self .query_table ))
391+ query_resource = RESTClientImpl .Instance ().client .resource (
392+ api_path = "/table/{query_table}" .format (query_table = self .query_table ))
267393 try : # Catch empty queries or errors making the request
268394 if self .desired_response_fields :
269395 logger .info ("Response fields specified in query parameters." )
@@ -431,7 +557,8 @@ def get_records_created_in_date_range(self, start, end):
431557 start_dt = self ._parse_datetime (start )
432558 end_dt = self ._parse_datetime (end )
433559
434- query_resource = self .client .resource (api_path = "/table/{query_table}" .format (query_table = self .query_table ))
560+ query_resource = RESTClientImpl .Instance ().client .resource (
561+ api_path = "/table/{query_table}" .format (query_table = self .query_table ))
435562 fields = ['sys_id' ]
436563 content = query_resource .get (
437564 query = "sys_created_onBETWEENjavascript:gs.dateGenerate('{start}')@javascript:gs.dateGenerate('{end}')" .format (
@@ -449,6 +576,7 @@ class RESTInsert:
449576 ROBOT_LIBRARY_SCOPE = "TEST CASE"
450577
451578 def __init__ (self , host = None , user = None , password = None , insert_table = None , response = None ):
579+ RESTClientImpl .Instance (host = host , user = user , password = password )
452580
453581 """The following arguments can be optionally provided when importing this library:
454582 - ``host``: The URL to your target ServiceNow instance (e.g. https://iceuat.service-now.com/).
@@ -462,34 +590,10 @@ def __init__(self, host=None, user=None, password=None, insert_table=None, respo
462590 - ``response``: Set the response object from the ServiceNow REST API (intended to be used for testing).
463591 """
464592
465- if host is None :
466- self .host = os .environ .get ("SNOW_TEST_URL" ).strip ()
467- else :
468- self .host = host .strip ()
469-
470- if user is None :
471- self .user = os .environ .get ("SNOW_REST_USER" )
472- else :
473- self .user = user
474-
475- if password is None :
476- self .password = os .environ .get ("SNOW_REST_PASS" )
477- else :
478- self .password = password
479-
480- if "http" not in self .host :
481- self .instance = urlparse (self .host ).path .split ("." )[0 ]
482- else :
483- self .instance = urlparse (self .host ).netloc .split ("." )[0 ]
484-
485- if self .instance == "" :
486- raise AssertionError (
487- "Unable to determine SNOW Instance. Verify that the SNOW_TEST_URL environment variable been set." )
488-
489- self .client = pysnow .Client (instance = self .instance , user = self .user , password = self .password )
593+
490594 self .insert_table = insert_table
491595 self .response = response
492-
596+
493597 @keyword
494598 def insert_table_is (self , insert_table ):
495599 """
@@ -530,7 +634,8 @@ def insert_record_parameters(self, new_record_payload):
530634 def insert_record (self ):
531635 """This keyword inserts the record in Servicenow by calling Create function from pysnow. It returns the sysid
532636 of the newly created record."""
533- insert_resource = self .client .resource (api_path = "/table/{insert_table}" .format (insert_table = self .insert_table ))
637+ insert_resource = RESTClientImpl .Instance ().client .resource (
638+ api_path = "/table/{insert_table}" .format (insert_table = self .insert_table ))
534639 result = insert_resource .create (payload = self .new_record_payload )
535640 sys_id = result ['sys_id' ]
536641 return sys_id
0 commit comments