11####
2- # This script demonstrates how to query for permissions using TSC
2+ # This script is for smoke testing VizQL Data Service.
33# To run the script, you must have installed Python 3.7 or later.
44#
5- # Example usage: 'python query_permissions.py -s https://10ax.online.tableau.com --site
6- # devSite123 -u [email protected] b4065286-80f0-11ea-af1b-cb7191f48e45' 5+ # Example usage: 'python vizql_data_service_smoke_test_cap.py --token-name token
6+ # --token-value DUCg0rbPROuuAMz9rDI4+Q==:OM2SzwPVK7dNITHo4nfUgsTZvVBQj8iQ
7+ # --server stage-dataplane7.online.vnext.tabint.net
8+ # --site hbistagedp7
9+ # --datasouce-luid ebe79f30-bdff-425a-8a9c-3cda79dbbbfd
10+ # --cap 2000'
11+
712####
813
914import argparse
1015import logging
1116import requests
1217import json
18+ import xml .etree .ElementTree as ET
19+
20+ def parse_token_from_response (xml_response ):
21+ namespace = {'ns' : 'http://tableau.com/api' }
22+ root = ET .fromstring (xml_response )
23+
24+ # Find the token attribute in the credentials tag
25+ credentials = root .find ('ns:credentials' , namespace )
26+ if credentials is not None :
27+ token = credentials .get ('token' )
28+ return token
29+ else :
30+ raise ValueError ("Token not found in the XML response." )
31+
32+
33+ def sign_in (args ):
34+ url = f"https://{ args .server } /api/3.22/auth/signin"
35+
36+ payload = json .dumps ({
37+ "credentials" : {
38+ "personalAccessTokenName" : args .token_name ,
39+ "personalAccessTokenSecret" : args .token_value ,
40+ "site" : {
41+ "contentUrl" : args .site
42+ }
43+ }
44+ })
45+ headers = {
46+ 'Content-Type' : 'application/json'
47+ }
1348
14- import tableauserverclient as TSC
15-
49+ response = requests .request ("POST" , url , headers = headers , data = payload )
50+ auth_token = parse_token_from_response (response .text )
51+ return auth_token
1652
1753def main ():
1854 parser = argparse .ArgumentParser (description = "Query permissions of a given resource." )
19- # Common options; please keep those in sync across all samples
2055 parser .add_argument ("--server" , "-s" , help = "server address" )
2156 parser .add_argument ("--site" , "-S" , help = "site name" )
2257 parser .add_argument ("--token-name" , "-p" , help = "name of the personal access token used to sign into the server" )
@@ -28,39 +63,46 @@ def main():
2863 default = "error" ,
2964 help = "desired logging level (set to error by default)" ,
3065 )
31- parser .add_argument ("resource_id" )
66+ parser .add_argument ("--datasource-luid" , "-ds" , help = "The luid of the datasource to query" , required = True )
67+ parser .add_argument ("--cap" , "-c" , type = int , help = "The cap on the current cloud site" , required = True )
68+
69+ args = parser .parse_args ()
3270
3371 # Set logging level based on user input, or error by default
3472 logging_level = getattr (logging , args .logging_level .upper ())
3573 logging .basicConfig (level = logging_level )
3674
3775 # Sign in
38- tableau_auth = TSC .PersonalAccessTokenAuth (args .token_name , args .token_value , site_id = args .site )
39- server = TSC .Server (args .server , use_server_version = True )
40-
41- with server .auth .sign_in (tableau_auth ):
42- endpoint = server .datasources
43-
44- # Get the resource by its ID
45- resource = endpoint .get_by_id (args .resource_id )
46- print (server )
76+ auth_token = sign_in (args )
4777
78+ url = "https://" + args .server + "/api/v1/vizql-data-service/read-metadata"
4879
49- url = "https://" + args .server + "/api/v1/vizql-data-service/read-metadata"
50-
51- payload = "{\n \" datasource\" : {\n \" datasourceLuid\" : \" " + args .resource_id + "\" \n },\n \" options\" : {\n \" debug\" : true\n }\n }"
52- headers = {
53- 'X-Tableau-Auth' : server .auth_token ,
54- 'Content-Type' : 'application/json' ,
80+ payload = json .dumps ({
81+ "datasource" : {
82+ "datasourceLuid" : args .datasource_luid
5583 }
84+ })
85+ headers = {
86+ 'X-Tableau-Auth' : auth_token ,
87+ 'Content-Type' : 'application/json' ,
88+ }
5689
57- response = requests .request ("POST" , url , headers = headers , data = payload )
90+ # Test cap limit
91+ for i in range (args .cap + 1 ):
92+ response = requests .post (url , headers = headers , data = payload )
93+ status_code = response .status_code
5894
59- print (response .text )
95+ if i < args .cap and status_code != 200 :
96+ response_message = response .text
97+ exceptionMsg = f"Unexpected status code for call { i + 1 } : { status_code } (Expected: 200). Response message: { response_message } " ;
98+ raise Exception (exceptionMsg )
99+ elif i >= args .cap and status_code != 429 :
100+ exceptionMsg = f"Call not rate limited: Unexpected status code for call { i + 1 } : { status_code } (Expected: 429)" ;
101+ raise Exception (exceptionMsg )
60102
103+ logging .info (f"Call { i + 1 } /{ args .cap } : Status Code { status_code } " )
61104
105+ print (f"Completed { args .cap } calls to VizQL Data Service." )
62106
63107if __name__ == "__main__" :
64108 main ()
65-
66-
0 commit comments