I hear quite often nowadays this question: how do I run my SAS (Viya) programs from outside using REST APIs?
There is an excellent Github repository which addresses this question, with several practical code examples: https://github.com/sassoftware/rest-api-use-cases .
By following these examples, I tested SAS job execution from Python client. My example SAS program produces some summary statistics and a line graph from SASHELP.AIR dataset, which is filtered by two macro variables.
/* Create dataset */
proc sql;
create table air_subset as
select * from sashelp.air
where date between "&startdate"d and "&enddate"d;
quit;
ods graphics / reset width=6.4in height=4.8in imagemap;
/* Summary statistics */
proc means data=WORK.AIR_SUBSET chartype mean std min max median n vardef=df qmethod=os;
var AIR;
run;
/* Histogram plot */
proc univariate data=WORK.AIR_SUBSET vardef=df noprint;
var AIR;
histogram AIR;
run;
proc sort data=WORK.AIR_SUBSET out=_SeriesPlotTaskData;
by DATE;
run;
/* Line graph*/
proc sgplot data=_SeriesPlotTaskData;
series x=DATE y=AIR /;
xaxis grid;
yaxis grid;
run;
ods graphics / reset;
proc datasets library=WORK noprint;
delete _SeriesPlotTaskData;
run;
I saved the sas-program as plot_air.sas and created a job definition of it. I placed the job definition in Public-folder.
Our SAS part of the experiment is now ready!
Let’s do the REST call in Python next.
First thing to do is the authentication. For my testing purposes, I authenticate with user id and password. There are more secure ways to do the authentication: you should follow the security policies of your organization.
Note that steps 1 and 2 are for registrating the client, and they are not needed to run after initial registration.
import requests as request
import time
# To get the client_token, you need to run this command in Viya server:
# kubectl -n sse get secret sas-consul-client -o jsonpath="{.data.CONSUL_TOKEN}" | echo "$(base64 -d)"
sasserver = "https://myviyaserver.sas.com"
client_token = "<client token from kubectl command above>"
username = “myusername”
password = “mypassword”
client_id = "myclient"
client_secret = "mysecret"
# Step 1 : Get the client access token
url = sasserver+"/SASLogon/oauth/clients/consul?callback=false&serviceId=" + client_id
payload = {}
headers = {
"X-Consul-Token": client_token
}
response = request.request("POST", url, headers=headers, data = payload, verify=False).json()
client_access_token = response["access_token"]
# Step 2 : Register the client
url = sasserver+"/SASLogon/oauth/clients"
payload = {"client_id": client_id,
"client_secret": client_secret,
"scope": ["*"],
"resource_ids": "none",
"authorities": ["uaa.none"],
"authorized_grant_types": ["password"],
"access_token_validity": 36000}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + client_access_token
}
response = request.request("POST", url, headers = headers, json = payload, verify=False).json()
# Step 3 : Get the access token
url = sasserver + "/SASLogon/oauth/token"
data = {
'grant_type': 'password',
'username': username,
'password': password
}
headers = {'Accept': 'application/json'}
response = request.post(url, headers=headers, data=data, auth=(client_id, client_secret), verify=False).json()
access_token = response["access_token"]
Step 4 makes the REST API call to the desired job (/Public/plot_air). Note that the macro variables (startdate, enddate) which filter the AIR-dataset in plot_air.sas are set as parameters in URL.
# Step 4 : Call the SAS job plot_air with parameters startdate and enddate
job_url = sasserver+"/SASJobExecution/?_program=/Public/plot_air&startdate=1JAN1950&enddate=31DEC1959"
url = job_url + '&_action=json&_resultfile=*&_omittextlog=false'
headers = {
'Authorization': 'bearer ' + access_token,
'Content-Type': 'application/vnd.sas.job.execution.job.request',
'Accept': 'application/vnd.sas.job.execution.job'
}
r = request.post(url, headers=headers, verify=False).json()
In Step 5, the result URLs are read from the HTTP response. log_uri contains the URL into SAS log, and output_uri into SAS output.
# Step 5 : get the SAS log and SAS output URLs
log_uri = sasserver + r['items'][1]['href']
output_uri = sasserver + r['items'][2]['href']
print(log_uri)
print(output_uri)
In the last step, the HTML result is written into local file.
# Step 6 : write the SAS output html-file into local folder
output_str = request.get(output_uri, headers=headers, verify=False).text
filename = "c:\\temp\\Output_"+time.strftime("%Y%m%d-%H%M%S")+".html"
with open(filename, "w") as output_html:
output_html.write(output_str)
And this is how the result HTML looks!