mirror of
https://github.com/sasjs/core.git
synced 2026-01-05 00:20:05 +00:00
Compare commits
9 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1932c1e138 | ||
|
|
f7ee012be3 | ||
|
|
b49e11bc79 | ||
|
|
f709a11dfb | ||
|
|
17ed2240d3 | ||
|
|
a8b5107b1a | ||
|
|
735bab5d26 | ||
|
|
86f7876f50 | ||
|
|
46c96bc7ec |
370
all.sas
370
all.sas
@@ -7573,6 +7573,11 @@ create table &outds as
|
|||||||
outfile=0
|
outfile=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if "%substr(&sysver,1,4)"="V.04" %then %do;
|
||||||
|
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
%ml_gsubfile()
|
%ml_gsubfile()
|
||||||
|
|
||||||
%mend mp_gsubfile;
|
%mend mp_gsubfile;
|
||||||
@@ -18854,6 +18859,38 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
%mend ms_createfile;
|
%mend ms_createfile;
|
||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Gets a file from SASjs Drive
|
||||||
|
@details Fetches a file on SASjs Drive and stores it in the output fileref.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
%ms_getfile(/some/stored/file.ext, outref=myfile)
|
||||||
|
|
||||||
|
@param [in] driveloc The full path to the file in SASjs Drive
|
||||||
|
@param [out] outref= (msgetfil) The fileref to contain the file.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_getfile(driveloc
|
||||||
|
,outref=msgetfil
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
filename &outref temp;
|
||||||
|
|
||||||
|
proc http method='GET' out=&outref
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/drive/file?filePath=&driveloc";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=2;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mend ms_getfile;
|
||||||
/**
|
/**
|
||||||
@file
|
@file
|
||||||
@brief Executes a SASjs Server Stored Program
|
@brief Executes a SASjs Server Stored Program
|
||||||
@@ -20969,10 +21006,16 @@ libname &libref1a clear;
|
|||||||
%mv_deleteviyafolder(path=/Public/test)
|
%mv_deleteviyafolder(path=/Public/test)
|
||||||
|
|
||||||
|
|
||||||
@param path= The full path of the folder to be deleted
|
@param [in] path= The full path of the folder to be deleted
|
||||||
@param access_token_var= The global macro variable to contain the access token
|
@param [in] access_token_var= (ACCESS_TOKEN) The global macro variable to
|
||||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
contain the access token
|
||||||
The default is authorization_code.
|
@param [in] grant_type= (sas_services) Valid values are:
|
||||||
|
@li password
|
||||||
|
@li authorization_code
|
||||||
|
@li detect - will check if access_token exists, if not will use sas_services
|
||||||
|
if a SASStudioV session else authorization_code. Default option.
|
||||||
|
@li sas_services - will use oauth_bearer=sas_services.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
@version VIYA V.03.04
|
||||||
@@ -20990,6 +21033,7 @@ libname &libref1a clear;
|
|||||||
%macro mv_deleteviyafolder(path=
|
%macro mv_deleteviyafolder(path=
|
||||||
,access_token_var=ACCESS_TOKEN
|
,access_token_var=ACCESS_TOKEN
|
||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local oauth_bearer;
|
%local oauth_bearer;
|
||||||
%if &grant_type=detect %then %do;
|
%if &grant_type=detect %then %do;
|
||||||
@@ -21066,14 +21110,17 @@ run;
|
|||||||
%let libref1a=%mf_getuniquelibref();
|
%let libref1a=%mf_getuniquelibref();
|
||||||
libname &libref1a JSON fileref=&fname1a;
|
libname &libref1a JSON fileref=&fname1a;
|
||||||
|
|
||||||
data _null_;
|
%if %mf_existds(&libref1a..items_links) %then %do;
|
||||||
set &libref1a..items_links;
|
data _null_;
|
||||||
if href=:'/folders/folders' then return;
|
set &libref1a..items_links;
|
||||||
if rel='deleteResource' then
|
if href=:'/folders/folders' then return;
|
||||||
call execute('proc http method="DELETE" url='!!quote("&base_uri"!!trim(href))
|
if rel='deleteResource' then
|
||||||
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
call execute('proc http method="DELETE" url='
|
||||||
!!' "Accept"="*/*";run; /**/');
|
!!quote("&base_uri"!!trim(href))
|
||||||
run;
|
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
||||||
|
!!' "Accept"="*/*";run; /**/');
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
%put &sysmacroname: perform the delete operation ;
|
%put &sysmacroname: perform the delete operation ;
|
||||||
%local fname2;
|
%local fname2;
|
||||||
@@ -21094,12 +21141,15 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
%else %put &sysmacroname: &path successfully deleted;
|
%else %put &sysmacroname: &path successfully deleted;
|
||||||
|
|
||||||
/* clear refs */
|
%if &mdebug=0 %then %do;
|
||||||
filename &fname1 clear;
|
/* clear refs */
|
||||||
filename &fname2 clear;
|
filename &fname1 clear;
|
||||||
libname &libref1 clear;
|
filename &fname2 clear;
|
||||||
|
libname &libref1 clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
%mend mv_deleteviyafolder;/**
|
%mend mv_deleteviyafolder;
|
||||||
|
/**
|
||||||
@file mv_getclients.sas
|
@file mv_getclients.sas
|
||||||
@brief Get a list of Viya Clients
|
@brief Get a list of Viya Clients
|
||||||
@details First, be sure you have an access token (which requires an app token).
|
@details First, be sure you have an access token (which requires an app token).
|
||||||
@@ -21563,7 +21613,6 @@ libname &libref1 clear;
|
|||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mv_getfoldermembers.sas
|
@li mv_getfoldermembers.sas
|
||||||
@li ml_json.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -21574,7 +21623,7 @@ libname &libref1 clear;
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg;
|
%local dbg bufsize varcnt fname1 fname2 errmsg;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -21634,7 +21683,6 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
%local fname1;
|
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&joburi";
|
url="&base_uri&joburi";
|
||||||
@@ -21651,30 +21699,81 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%local fname2 fname3 fpath1 fpath2 fpath3;
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
%let fname3=%mf_getuniquefileref();
|
|
||||||
%let fpath1=%sysfunc(pathname(&fname1));
|
|
||||||
%let fpath2=%sysfunc(pathname(&fname2));
|
|
||||||
%let fpath3=%sysfunc(pathname(&fname3));
|
|
||||||
|
|
||||||
/* compile the lua JSON module */
|
%let fname2=%mf_getuniquefileref();
|
||||||
%ml_json()
|
filename &fname2 temp ;
|
||||||
/* read using LUA - this allows the code to be of any length */
|
|
||||||
|
/* cannot use lua IO package as not available in Viya 4 */
|
||||||
|
/* so use data step to read the JSON until the string `"code":"` is found */
|
||||||
data _null_;
|
data _null_;
|
||||||
file "&fpath3..lua";
|
file &fname2 recfm=n;
|
||||||
put '
|
infile &fname1 lrecl=1 recfm=n;
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
input sourcechar $ 1. @@;
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
format sourcechar hex2.;
|
||||||
io.input(infile)
|
retain startwrite 0;
|
||||||
local resp=json.decode(io.read())
|
if startwrite=0 and sourcechar='"' then do;
|
||||||
local job=resp["code"]
|
reentry:
|
||||||
outfile:write(job)
|
input sourcechar $ 1. @@;
|
||||||
io.close(infile)
|
if sourcechar='c' then do;
|
||||||
io.close(outfile)
|
reentry2:
|
||||||
';
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='o' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='d' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='e' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='"' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar=':' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='"' then do;
|
||||||
|
putlog 'code found';
|
||||||
|
startwrite=1;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='c' then goto reentry2;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
/* once the `"code":"` string is found, write until unescaped `"` is found */
|
||||||
|
if startwrite=1 then do;
|
||||||
|
if sourcechar='\' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar in ('"','\') then put sourcechar char1.;
|
||||||
|
else if sourcechar='n' then put '0A'x;
|
||||||
|
else if sourcechar='r' then put '0D'x;
|
||||||
|
else if sourcechar='t' then put '09'x;
|
||||||
|
else if sourcechar='u' then do;
|
||||||
|
length uni $4;
|
||||||
|
input uni $ 4. @@;
|
||||||
|
sourcechar=unicode('\u'!!uni);
|
||||||
|
put sourcechar char1.;
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
call symputx('errmsg',"Uncaught escape char: "!!sourcechar,'l');
|
||||||
|
call symputx('syscc',99);
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then stop;
|
||||||
|
else put sourcechar char1.;
|
||||||
|
end;
|
||||||
run;
|
run;
|
||||||
%inc "&fpath3..lua";
|
|
||||||
|
%mp_abort(iftrue=("&syscc"="99")
|
||||||
|
,mac=mv_getjobcode
|
||||||
|
,msg=%str(&errmsg)
|
||||||
|
)
|
||||||
|
|
||||||
/* export to desired destination */
|
/* export to desired destination */
|
||||||
%if "&outref"="0" %then %do;
|
%if "&outref"="0" %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
@@ -21699,7 +21798,6 @@ run;
|
|||||||
/* clear refs */
|
/* clear refs */
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
filename &fname3 clear;
|
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mv_getjobcode;
|
%mend mv_getjobcode;
|
||||||
@@ -21791,7 +21889,8 @@ run;
|
|||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_existfileref.sas
|
@li mf_existfileref.sas
|
||||||
@li ml_json.sas
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquelibref.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -21800,7 +21899,7 @@ run;
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg;
|
%local dbg libref1 libref2 loglocation fname1 fname2;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -21859,8 +21958,8 @@ options noquotelenmax;
|
|||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
%local fname1;
|
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
|
%let fname2=%mf_getuniquefileref();
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&uri";
|
url="&base_uri&uri";
|
||||||
headers
|
headers
|
||||||
@@ -21880,37 +21979,19 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%local fname2 fname3 fpath1 fpath2 fpath3;
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
%let fname3=%mf_getuniquefileref();
|
|
||||||
%let fpath1=%sysfunc(pathname(&fname1));
|
|
||||||
%let fpath2=%sysfunc(pathname(&fname2));
|
|
||||||
%let fpath3=%sysfunc(pathname(&fname3));
|
|
||||||
|
|
||||||
/* compile the lua JSON module */
|
%let libref1=%mf_getuniquelibref();
|
||||||
%ml_json()
|
libname &libref1 JSON fileref=&fname1;
|
||||||
/* read using LUA - this allows the code to be of any length */
|
|
||||||
data _null_;
|
data _null_;
|
||||||
file "&fpath3..lua";
|
set &libref1..root;
|
||||||
put '
|
call symputx('loglocation',loglocation,'l');
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
|
||||||
io.input(infile)
|
|
||||||
local resp=json.decode(io.read())
|
|
||||||
local logloc=resp["logLocation"]
|
|
||||||
outfile:write(logloc)
|
|
||||||
io.close(infile)
|
|
||||||
io.close(outfile)
|
|
||||||
';
|
|
||||||
run;
|
run;
|
||||||
%inc "&fpath3..lua";
|
|
||||||
/* get log path*/
|
/* validate log path*/
|
||||||
%let errflg=1;
|
%let errflg=1;
|
||||||
%let errmsg=No entry in &fname2 fileref;
|
%let errmsg=No loglocation entry in &fname1 fileref;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname2;
|
uri=symget('loglocation');
|
||||||
input;
|
|
||||||
uri=cats(_infile_);
|
|
||||||
if length(uri)<12 then do;
|
if length(uri)<12 then do;
|
||||||
call symputx('errflg',1);
|
call symputx('errflg',1);
|
||||||
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
||||||
@@ -21937,7 +22018,7 @@ run;
|
|||||||
|
|
||||||
/* we have a log uri - now fetch the log */
|
/* we have a log uri - now fetch the log */
|
||||||
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname2 &oauth_bearer
|
||||||
url="&base_uri&logloc/content?limit=10000";
|
url="&base_uri&logloc/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -21948,14 +22029,14 @@ run;
|
|||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
||||||
/* fetch log from parent session */
|
/* fetch log from parent session */
|
||||||
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
||||||
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname2 &oauth_bearer
|
||||||
url="&base_uri&logloc/log/content?limit=10000";
|
url="&base_uri&logloc/log/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -21965,47 +22046,32 @@ run;
|
|||||||
run;
|
run;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
||||||
%then %do;
|
%then %do;
|
||||||
%if &mdebug ne 1 %then %do; /* have already output above */
|
%if &mdebug ne 1 %then %do; /* have already output above */
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%mp_abort(mac=&sysmacroname
|
%mp_abort(mac=&sysmacroname
|
||||||
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
data _null_;
|
|
||||||
file "&fpath3..lua";
|
|
||||||
put '
|
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
|
||||||
io.input(infile)
|
|
||||||
local resp=json.decode(io.read())
|
|
||||||
for i, v in pairs(resp["items"]) do
|
|
||||||
outfile:write(v.line,"\n")
|
|
||||||
end
|
|
||||||
io.close(infile)
|
|
||||||
io.close(outfile)
|
|
||||||
';
|
|
||||||
run;
|
|
||||||
%inc "&fpath3..lua";
|
|
||||||
|
|
||||||
/* write log out to the specified fileref */
|
%let libref2=%mf_getuniquelibref();
|
||||||
|
libname &libref2 JSON fileref=&fname2;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname2 end=last;
|
|
||||||
file &outref mod;
|
file &outref mod;
|
||||||
if _n_=1 then do;
|
if _n_=1 then do;
|
||||||
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
||||||
end;
|
end;
|
||||||
input;
|
set &libref2..items end=last;
|
||||||
put _infile_;
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
putlog _infile_;
|
putlog line;
|
||||||
%end;
|
%end;
|
||||||
|
put line;
|
||||||
if last then do;
|
if last then do;
|
||||||
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
||||||
end;
|
end;
|
||||||
@@ -22014,7 +22080,8 @@ run;
|
|||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
filename &fname3 clear;
|
libname &libref1 clear;
|
||||||
|
libname &libref2 clear;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
@@ -24971,115 +25038,6 @@ endsub;
|
|||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mcf_length;/**
|
%mend mcf_length;/**
|
||||||
@file
|
|
||||||
@brief Provides a replacement for the stpsrv_header function
|
|
||||||
@details The stpsrv_header is normally a built-in function, used to set the
|
|
||||||
headers for SAS 9 Stored Processes as documented here:
|
|
||||||
https://go.documentation.sas.com/doc/en/itechcdc/9.4/stpug/srvhead.htm
|
|
||||||
|
|
||||||
The purpose of this custom function is to provide a replacement when running
|
|
||||||
similar code as a web service against
|
|
||||||
[sasjs/server](https://github.com/sasjs/server). It operates by creating a
|
|
||||||
text file with the headers. The location of this text file is determined by
|
|
||||||
a macro variable (`sasjs_stpsrv_header_loc`) which needs to be injected into
|
|
||||||
each service by the calling process, eg:
|
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc = C:/temp/some_uuid/stpsrv_header.txt;
|
|
||||||
|
|
||||||
Note - the function works by appending headers to the file. If multiple same-
|
|
||||||
named headers are provided, they will all be appended - the calling process
|
|
||||||
needs to pick up the last one. This will mean removing the attribute if the
|
|
||||||
final record has an empty value.
|
|
||||||
|
|
||||||
The function takes the following (positional) parameters:
|
|
||||||
|
|
||||||
| PARAMETER | DESCRIPTION |
|
|
||||||
|------------|-------------|
|
|
||||||
| name $ | name of the header attribute to create|
|
|
||||||
| value $ | value of the header attribute|
|
|
||||||
|
|
||||||
It returns 0 if successful, or -1 if an error occured.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt;
|
|
||||||
|
|
||||||
%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt");
|
|
||||||
run;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
|
|
||||||
@param [out] lib= (work) The output library in which to create the catalog.
|
|
||||||
@param [out] cat= (sasjs) The output catalog in which to create the package.
|
|
||||||
@param [out] pkg= (utils) The output package in which to create the function.
|
|
||||||
Uses a 3 part format: libref.catalog.package
|
|
||||||
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
|
|
||||||
values inserted only if needed.
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mcf_init.sas
|
|
||||||
|
|
||||||
<h4> Related Programs </h4>
|
|
||||||
@li mcf_stpsrv_header.test.sas
|
|
||||||
@li mp_init.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mcf_stpsrv_header(wrap=NO
|
|
||||||
,insert_cmplib=DEPRECATED
|
|
||||||
,lib=WORK
|
|
||||||
,cat=SASJS
|
|
||||||
,pkg=UTILS
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
%local i var cmpval found;
|
|
||||||
%if %mcf_init(stpsrv_header)=1 %then %return;
|
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
|
||||||
proc fcmp outlib=&lib..&cat..&pkg;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
function stpsrv_header(name $, value $);
|
|
||||||
length loc $128 val $512;
|
|
||||||
loc=symget('sasjs_stpsrv_header_loc');
|
|
||||||
val=trim(name)!!': '!!value;
|
|
||||||
length fref $8;
|
|
||||||
rc=filename(fref,loc);
|
|
||||||
if (rc ne 0) then return( -1 );
|
|
||||||
fid = fopen(fref,'a');
|
|
||||||
if (fid = 0) then return( -1 );
|
|
||||||
rc=fput(fid, val);
|
|
||||||
rc=fwrite(fid);
|
|
||||||
rc=fclose(fid);
|
|
||||||
rc=filename(fref);
|
|
||||||
return(0);
|
|
||||||
endsub;
|
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
|
||||||
quit;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* insert the CMPLIB if not already there */
|
|
||||||
%let cmpval=%sysfunc(getoption(cmplib));
|
|
||||||
%let found=0;
|
|
||||||
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
|
|
||||||
%let var=%scan(&cmpval,&i,%str( %(%)));
|
|
||||||
%if &var=&lib..&cat %then %let found=1;
|
|
||||||
%end;
|
|
||||||
%if &found=0 %then %do;
|
|
||||||
options insert=(CMPLIB=(&lib..&cat));
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend mcf_stpsrv_header;/**
|
|
||||||
@file
|
@file
|
||||||
@brief Adds a string to a file
|
@brief Adds a string to a file
|
||||||
@details Creates an fcmp function for appending a string to an external file.
|
@details Creates an fcmp function for appending a string to an external file.
|
||||||
|
|||||||
@@ -48,6 +48,11 @@
|
|||||||
outfile=0
|
outfile=0
|
||||||
)/*/STORE SOURCE*/;
|
)/*/STORE SOURCE*/;
|
||||||
|
|
||||||
|
%if "%substr(&sysver,1,4)"="V.04" %then %do;
|
||||||
|
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
%ml_gsubfile()
|
%ml_gsubfile()
|
||||||
|
|
||||||
%mend mp_gsubfile;
|
%mend mp_gsubfile;
|
||||||
|
|||||||
@@ -1,110 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Provides a replacement for the stpsrv_header function
|
|
||||||
@details The stpsrv_header is normally a built-in function, used to set the
|
|
||||||
headers for SAS 9 Stored Processes as documented here:
|
|
||||||
https://go.documentation.sas.com/doc/en/itechcdc/9.4/stpug/srvhead.htm
|
|
||||||
|
|
||||||
The purpose of this custom function is to provide a replacement when running
|
|
||||||
similar code as a web service against
|
|
||||||
[sasjs/server](https://github.com/sasjs/server). It operates by creating a
|
|
||||||
text file with the headers. The location of this text file is determined by
|
|
||||||
a macro variable (`sasjs_stpsrv_header_loc`) which needs to be injected into
|
|
||||||
each service by the calling process, eg:
|
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc = C:/temp/some_uuid/stpsrv_header.txt;
|
|
||||||
|
|
||||||
Note - the function works by appending headers to the file. If multiple same-
|
|
||||||
named headers are provided, they will all be appended - the calling process
|
|
||||||
needs to pick up the last one. This will mean removing the attribute if the
|
|
||||||
final record has an empty value.
|
|
||||||
|
|
||||||
The function takes the following (positional) parameters:
|
|
||||||
|
|
||||||
| PARAMETER | DESCRIPTION |
|
|
||||||
|------------|-------------|
|
|
||||||
| name $ | name of the header attribute to create|
|
|
||||||
| value $ | value of the header attribute|
|
|
||||||
|
|
||||||
It returns 0 if successful, or -1 if an error occured.
|
|
||||||
|
|
||||||
Usage:
|
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt;
|
|
||||||
|
|
||||||
%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt");
|
|
||||||
run;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
|
||||||
input;
|
|
||||||
putlog _infile_;
|
|
||||||
run;
|
|
||||||
|
|
||||||
|
|
||||||
@param [out] wrap= (NO) Choose YES to add the proc fcmp wrapper.
|
|
||||||
@param [out] lib= (work) The output library in which to create the catalog.
|
|
||||||
@param [out] cat= (sasjs) The output catalog in which to create the package.
|
|
||||||
@param [out] pkg= (utils) The output package in which to create the function.
|
|
||||||
Uses a 3 part format: libref.catalog.package
|
|
||||||
@param [out] insert_cmplib= DEPRECATED - The CMPLIB option is checked and
|
|
||||||
values inserted only if needed.
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mcf_init.sas
|
|
||||||
|
|
||||||
<h4> Related Programs </h4>
|
|
||||||
@li mcf_stpsrv_header.test.sas
|
|
||||||
@li mp_init.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%macro mcf_stpsrv_header(wrap=NO
|
|
||||||
,insert_cmplib=DEPRECATED
|
|
||||||
,lib=WORK
|
|
||||||
,cat=SASJS
|
|
||||||
,pkg=UTILS
|
|
||||||
)/*/STORE SOURCE*/;
|
|
||||||
%local i var cmpval found;
|
|
||||||
%if %mcf_init(stpsrv_header)=1 %then %return;
|
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
|
||||||
proc fcmp outlib=&lib..&cat..&pkg;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
function stpsrv_header(name $, value $);
|
|
||||||
length loc $128 val $512;
|
|
||||||
loc=symget('sasjs_stpsrv_header_loc');
|
|
||||||
val=trim(name)!!': '!!value;
|
|
||||||
length fref $8;
|
|
||||||
rc=filename(fref,loc);
|
|
||||||
if (rc ne 0) then return( -1 );
|
|
||||||
fid = fopen(fref,'a');
|
|
||||||
if (fid = 0) then return( -1 );
|
|
||||||
rc=fput(fid, val);
|
|
||||||
rc=fwrite(fid);
|
|
||||||
rc=fclose(fid);
|
|
||||||
rc=filename(fref);
|
|
||||||
return(0);
|
|
||||||
endsub;
|
|
||||||
|
|
||||||
%if &wrap=YES %then %do;
|
|
||||||
quit;
|
|
||||||
%end;
|
|
||||||
|
|
||||||
/* insert the CMPLIB if not already there */
|
|
||||||
%let cmpval=%sysfunc(getoption(cmplib));
|
|
||||||
%let found=0;
|
|
||||||
%do i=1 %to %sysfunc(countw(&cmpval,%str( %(%))));
|
|
||||||
%let var=%scan(&cmpval,&i,%str( %(%)));
|
|
||||||
%if &var=&lib..&cat %then %let found=1;
|
|
||||||
%end;
|
|
||||||
%if &found=0 %then %do;
|
|
||||||
options insert=(CMPLIB=(&lib..&cat));
|
|
||||||
%end;
|
|
||||||
|
|
||||||
%mend mcf_stpsrv_header;
|
|
||||||
@@ -95,6 +95,19 @@
|
|||||||
"tests/sas9only",
|
"tests/sas9only",
|
||||||
"tests/viyaonly"
|
"tests/viyaonly"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "viya4",
|
||||||
|
"serverUrl": "https://azureuse011059.my-trials.sas.com",
|
||||||
|
"serverType": "SASVIYA",
|
||||||
|
"appLoc": "/Public/temp/macrocore",
|
||||||
|
"macroFolders": [
|
||||||
|
"tests/viyaonly"
|
||||||
|
],
|
||||||
|
"deployConfig": {
|
||||||
|
"deployServicePack": true
|
||||||
|
},
|
||||||
|
"contextName": "SAS Job Execution compute context"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
32
server/ms_getfile.sas
Normal file
32
server/ms_getfile.sas
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Gets a file from SASjs Drive
|
||||||
|
@details Fetches a file on SASjs Drive and stores it in the output fileref.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
%ms_getfile(/some/stored/file.ext, outref=myfile)
|
||||||
|
|
||||||
|
@param [in] driveloc The full path to the file in SASjs Drive
|
||||||
|
@param [out] outref= (msgetfil) The fileref to contain the file.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
%macro ms_getfile(driveloc
|
||||||
|
,outref=msgetfil
|
||||||
|
,mdebug=0
|
||||||
|
);
|
||||||
|
|
||||||
|
filename &outref temp;
|
||||||
|
|
||||||
|
proc http method='GET' out=&outref
|
||||||
|
url="&_sasjs_apiserverurl/SASjsApi/drive/file?filePath=&driveloc";
|
||||||
|
%if &mdebug=1 %then %do;
|
||||||
|
debug level=2;
|
||||||
|
%end;
|
||||||
|
run;
|
||||||
|
|
||||||
|
|
||||||
|
%mend ms_getfile;
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
/**
|
|
||||||
@file
|
|
||||||
@brief Testing mcf_stpsrv_header macro
|
|
||||||
|
|
||||||
<h4> SAS Macros </h4>
|
|
||||||
@li mcf_stpsrv_header.sas
|
|
||||||
@li mp_assert.sas
|
|
||||||
|
|
||||||
**/
|
|
||||||
|
|
||||||
%let sasjs_stpsrv_header_loc=%sysfunc(pathname(work))/stpsrv_header.txt;
|
|
||||||
|
|
||||||
%mcf_stpsrv_header(wrap=YES, insert_cmplib=YES)
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
rc=stpsrv_header('Content-type','application/text');
|
|
||||||
rc=stpsrv_header('Content-disposition',"attachment; filename=file.txt");
|
|
||||||
run;
|
|
||||||
|
|
||||||
%let test1=FAIL;
|
|
||||||
%let test2=FAIL;
|
|
||||||
|
|
||||||
data _null_;
|
|
||||||
infile "&sasjs_stpsrv_header_loc";
|
|
||||||
input;
|
|
||||||
if _n_=1 and _infile_='Content-type: application/text'
|
|
||||||
then call symputx('test1','PASS');
|
|
||||||
else if _n_=2 & _infile_='Content-disposition: attachment; filename=file.txt'
|
|
||||||
then call symputx('test2','PASS');
|
|
||||||
run;
|
|
||||||
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%str(&test1)=%str(PASS)),
|
|
||||||
desc=Check first header line
|
|
||||||
)
|
|
||||||
%mp_assert(
|
|
||||||
iftrue=(%str(&test2)=%str(PASS)),
|
|
||||||
desc=Check second header line
|
|
||||||
)
|
|
||||||
@@ -8,6 +8,13 @@
|
|||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
%macro gsubtest();
|
||||||
|
%if "%substr(&sysver,1,4)"="V.04" %then %do;
|
||||||
|
%put %str(ERR)OR: Viya 4 does not support the IO library in lua;
|
||||||
|
%return;
|
||||||
|
%end;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* test 1 - simple replace
|
* test 1 - simple replace
|
||||||
*/
|
*/
|
||||||
@@ -63,4 +70,8 @@ run;
|
|||||||
iftrue=("&strcheck2b"="&str2"),
|
iftrue=("&strcheck2b"="&str2"),
|
||||||
desc=Check that multi line replacement was successful (line3),
|
desc=Check that multi line replacement was successful (line3),
|
||||||
outds=work.test_results
|
outds=work.test_results
|
||||||
)
|
)
|
||||||
|
|
||||||
|
%mend gsubtest;
|
||||||
|
|
||||||
|
%gsubtest()
|
||||||
|
|||||||
45
tests/serveronly/ms_getfile.test.sas
Normal file
45
tests/serveronly/ms_getfile.test.sas
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing ms_getfile.sas macro
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li ms_createfile.sas
|
||||||
|
@li ms_getfile.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
/* first make a remote file */
|
||||||
|
filename stpcode temp;
|
||||||
|
%let fname=%mf_getuniquename();
|
||||||
|
data _null_;
|
||||||
|
file stpcode;
|
||||||
|
put "data &fname;run;";
|
||||||
|
run;
|
||||||
|
%ms_createfile(/sasjs/tests/&fname..sas
|
||||||
|
,inref=stpcode
|
||||||
|
,mdebug=1
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%ms_getfile(/sasjs/tests/&fname..sas,outref=testref)
|
||||||
|
%mp_assertscope(COMPARE)
|
||||||
|
|
||||||
|
%let test1=0;
|
||||||
|
data _null_;
|
||||||
|
infile testref;
|
||||||
|
input;
|
||||||
|
call symputx('test1',_infile_);
|
||||||
|
run;
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=("&test1"="data &fname;run;"),
|
||||||
|
desc=Checking file was created with the same content,
|
||||||
|
outds=work.test_results
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
52
tests/viyaonly/mv_deleteviyafolder.test.sas
Normal file
52
tests/viyaonly/mv_deleteviyafolder.test.sas
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
@file
|
||||||
|
@brief Testing mv_deleteviyafolder macro function
|
||||||
|
|
||||||
|
<h4> SAS Macros </h4>
|
||||||
|
@li mf_uid.sas
|
||||||
|
@li mfv_existfolder.sas
|
||||||
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
|
@li mv_createfolder.sas
|
||||||
|
@li mv_deleteviyafolder.sas
|
||||||
|
|
||||||
|
**/
|
||||||
|
|
||||||
|
options mprint sgen;
|
||||||
|
|
||||||
|
%let folder=%mf_uid();
|
||||||
|
%let tgtfolder=&mcTestAppLoc/temp/&folder;
|
||||||
|
|
||||||
|
/* create a folder */
|
||||||
|
%mv_createfolder(path=&tgtfolder)
|
||||||
|
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mfv_existfolder(&tgtfolder)=1),
|
||||||
|
desc=Check if created folder exists
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mv_deleteviyafolder(path=&tgtfolder)
|
||||||
|
/* ignore proc json vars */
|
||||||
|
%mp_assertscope(COMPARE
|
||||||
|
,ignorelist=MCLIB0_JADP1LEN MCLIB0_JADP2LEN MCLIB0_JADVLEN MCLIB2_JADP1LEN
|
||||||
|
MCLIB2_JADVLEN
|
||||||
|
)
|
||||||
|
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mfv_existfolder(&tgtfolder)=0),
|
||||||
|
desc=Check if deleted folder is gone
|
||||||
|
)
|
||||||
|
|
||||||
|
/* delete folder with content */
|
||||||
|
%mv_createfolder(path=&tgtfolder/content/and/stuff)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mfv_existfolder(&tgtfolder/content/and/stuff)=1),
|
||||||
|
desc=Check if folder with content exists
|
||||||
|
)
|
||||||
|
%mv_deleteviyafolder(path=&tgtfolder)
|
||||||
|
%mp_assert(
|
||||||
|
iftrue=(%mfv_existfolder(&tgtfolder)=0),
|
||||||
|
desc=Check if deleted folder with subfolders is gone
|
||||||
|
)
|
||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
@li mv_createjob.sas
|
@li mv_createjob.sas
|
||||||
@li mv_getjobcode.sas
|
@li mv_getjobcode.sas
|
||||||
|
|
||||||
@@ -27,11 +28,17 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* now get the code back */
|
/* now get the code back */
|
||||||
|
%mp_assertscope(SNAPSHOT)
|
||||||
%mv_getjobcode(
|
%mv_getjobcode(
|
||||||
path=&mcTestAppLoc/services/temp,
|
path=&mcTestAppLoc/services/temp,
|
||||||
name=some_job,
|
name=some_job,
|
||||||
outref=mycode
|
outref=mycode
|
||||||
)
|
)
|
||||||
|
/* exclude automatic proc json macro variables from scope check */
|
||||||
|
%mp_assertscope(COMPARE,
|
||||||
|
ignorelist=MCLIB2_JADP1LEN MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
|
||||||
|
MCLIB2_JADP3LEN
|
||||||
|
)
|
||||||
|
|
||||||
%let diditexist=NO;
|
%let diditexist=NO;
|
||||||
data work.test1;
|
data work.test1;
|
||||||
@@ -46,4 +53,4 @@ run;
|
|||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(&diditexist=NO),
|
iftrue=(&diditexist=NO),
|
||||||
desc=Check if the code that was sent was successfully retrieved
|
desc=Check if the code that was sent was successfully retrieved
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
<h4> SAS Macros </h4>
|
<h4> SAS Macros </h4>
|
||||||
@li mp_assert.sas
|
@li mp_assert.sas
|
||||||
|
@li mp_assertscope.sas
|
||||||
@li mv_createjob.sas
|
@li mv_createjob.sas
|
||||||
@li mv_jobexecute.sas
|
@li mv_jobexecute.sas
|
||||||
@li mv_jobwaitfor.sas
|
@li mv_jobwaitfor.sas
|
||||||
@@ -49,8 +50,12 @@ data _null_;
|
|||||||
run;
|
run;
|
||||||
|
|
||||||
%* Finally, fetch the log;
|
%* Finally, fetch the log;
|
||||||
%mv_getjoblog(uri=%str(&uri),outref=mylog)
|
%mp_assertscope(SNAPSHOT)
|
||||||
|
%mv_getjoblog(uri=%str(&uri),outref=mylog,mdebug=1)
|
||||||
|
/* ignore auto proc json vars */
|
||||||
|
%mp_assertscope(COMPARE
|
||||||
|
,ignorelist=MCLIB2_JADP2LEN MCLIB2_JADPNUM MCLIB2_JADVLEN
|
||||||
|
)
|
||||||
|
|
||||||
data _null_;
|
data _null_;
|
||||||
infile mylog end=eof;
|
infile mylog end=eof;
|
||||||
@@ -67,4 +72,4 @@ run;
|
|||||||
%mp_assert(
|
%mp_assert(
|
||||||
iftrue=(%str(&found)=1),
|
iftrue=(%str(&found)=1),
|
||||||
desc=Check if the log was still fetched even though endsas was submitted
|
desc=Check if the log was still fetched even though endsas was submitted
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -8,10 +8,16 @@
|
|||||||
%mv_deleteviyafolder(path=/Public/test)
|
%mv_deleteviyafolder(path=/Public/test)
|
||||||
|
|
||||||
|
|
||||||
@param path= The full path of the folder to be deleted
|
@param [in] path= The full path of the folder to be deleted
|
||||||
@param access_token_var= The global macro variable to contain the access token
|
@param [in] access_token_var= (ACCESS_TOKEN) The global macro variable to
|
||||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
contain the access token
|
||||||
The default is authorization_code.
|
@param [in] grant_type= (sas_services) Valid values are:
|
||||||
|
@li password
|
||||||
|
@li authorization_code
|
||||||
|
@li detect - will check if access_token exists, if not will use sas_services
|
||||||
|
if a SASStudioV session else authorization_code. Default option.
|
||||||
|
@li sas_services - will use oauth_bearer=sas_services.
|
||||||
|
@param [in] mdebug= (0) Set to 1 to enable DEBUG messages
|
||||||
|
|
||||||
|
|
||||||
@version VIYA V.03.04
|
@version VIYA V.03.04
|
||||||
@@ -29,6 +35,7 @@
|
|||||||
%macro mv_deleteviyafolder(path=
|
%macro mv_deleteviyafolder(path=
|
||||||
,access_token_var=ACCESS_TOKEN
|
,access_token_var=ACCESS_TOKEN
|
||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local oauth_bearer;
|
%local oauth_bearer;
|
||||||
%if &grant_type=detect %then %do;
|
%if &grant_type=detect %then %do;
|
||||||
@@ -105,14 +112,17 @@ run;
|
|||||||
%let libref1a=%mf_getuniquelibref();
|
%let libref1a=%mf_getuniquelibref();
|
||||||
libname &libref1a JSON fileref=&fname1a;
|
libname &libref1a JSON fileref=&fname1a;
|
||||||
|
|
||||||
data _null_;
|
%if %mf_existds(&libref1a..items_links) %then %do;
|
||||||
set &libref1a..items_links;
|
data _null_;
|
||||||
if href=:'/folders/folders' then return;
|
set &libref1a..items_links;
|
||||||
if rel='deleteResource' then
|
if href=:'/folders/folders' then return;
|
||||||
call execute('proc http method="DELETE" url='!!quote("&base_uri"!!trim(href))
|
if rel='deleteResource' then
|
||||||
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
call execute('proc http method="DELETE" url='
|
||||||
!!' "Accept"="*/*";run; /**/');
|
!!quote("&base_uri"!!trim(href))
|
||||||
run;
|
!!'; headers "Authorization"="Bearer &&&access_token_var" '
|
||||||
|
!!' "Accept"="*/*";run; /**/');
|
||||||
|
run;
|
||||||
|
%end;
|
||||||
|
|
||||||
%put &sysmacroname: perform the delete operation ;
|
%put &sysmacroname: perform the delete operation ;
|
||||||
%local fname2;
|
%local fname2;
|
||||||
@@ -133,9 +143,11 @@ run;
|
|||||||
%end;
|
%end;
|
||||||
%else %put &sysmacroname: &path successfully deleted;
|
%else %put &sysmacroname: &path successfully deleted;
|
||||||
|
|
||||||
/* clear refs */
|
%if &mdebug=0 %then %do;
|
||||||
filename &fname1 clear;
|
/* clear refs */
|
||||||
filename &fname2 clear;
|
filename &fname1 clear;
|
||||||
libname &libref1 clear;
|
filename &fname2 clear;
|
||||||
|
libname &libref1 clear;
|
||||||
|
%end;
|
||||||
|
|
||||||
%mend mv_deleteviyafolder;
|
%mend mv_deleteviyafolder;
|
||||||
|
|||||||
@@ -33,7 +33,6 @@
|
|||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_getuniquefileref.sas
|
@li mf_getuniquefileref.sas
|
||||||
@li mv_getfoldermembers.sas
|
@li mv_getfoldermembers.sas
|
||||||
@li ml_json.sas
|
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -44,7 +43,7 @@
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg;
|
%local dbg bufsize varcnt fname1 fname2 errmsg;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -104,7 +103,6 @@ run;
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
%local fname1;
|
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&joburi";
|
url="&base_uri&joburi";
|
||||||
@@ -121,30 +119,81 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%local fname2 fname3 fpath1 fpath2 fpath3;
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
%let fname3=%mf_getuniquefileref();
|
|
||||||
%let fpath1=%sysfunc(pathname(&fname1));
|
|
||||||
%let fpath2=%sysfunc(pathname(&fname2));
|
|
||||||
%let fpath3=%sysfunc(pathname(&fname3));
|
|
||||||
|
|
||||||
/* compile the lua JSON module */
|
%let fname2=%mf_getuniquefileref();
|
||||||
%ml_json()
|
filename &fname2 temp ;
|
||||||
/* read using LUA - this allows the code to be of any length */
|
|
||||||
|
/* cannot use lua IO package as not available in Viya 4 */
|
||||||
|
/* so use data step to read the JSON until the string `"code":"` is found */
|
||||||
data _null_;
|
data _null_;
|
||||||
file "&fpath3..lua";
|
file &fname2 recfm=n;
|
||||||
put '
|
infile &fname1 lrecl=1 recfm=n;
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
input sourcechar $ 1. @@;
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
format sourcechar hex2.;
|
||||||
io.input(infile)
|
retain startwrite 0;
|
||||||
local resp=json.decode(io.read())
|
if startwrite=0 and sourcechar='"' then do;
|
||||||
local job=resp["code"]
|
reentry:
|
||||||
outfile:write(job)
|
input sourcechar $ 1. @@;
|
||||||
io.close(infile)
|
if sourcechar='c' then do;
|
||||||
io.close(outfile)
|
reentry2:
|
||||||
';
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='o' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='d' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='e' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='"' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar=':' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar='"' then do;
|
||||||
|
putlog 'code found';
|
||||||
|
startwrite=1;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='c' then goto reentry2;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then goto reentry;
|
||||||
|
end;
|
||||||
|
/* once the `"code":"` string is found, write until unescaped `"` is found */
|
||||||
|
if startwrite=1 then do;
|
||||||
|
if sourcechar='\' then do;
|
||||||
|
input sourcechar $ 1. @@;
|
||||||
|
if sourcechar in ('"','\') then put sourcechar char1.;
|
||||||
|
else if sourcechar='n' then put '0A'x;
|
||||||
|
else if sourcechar='r' then put '0D'x;
|
||||||
|
else if sourcechar='t' then put '09'x;
|
||||||
|
else if sourcechar='u' then do;
|
||||||
|
length uni $4;
|
||||||
|
input uni $ 4. @@;
|
||||||
|
sourcechar=unicode('\u'!!uni);
|
||||||
|
put sourcechar char1.;
|
||||||
|
end;
|
||||||
|
else do;
|
||||||
|
call symputx('errmsg',"Uncaught escape char: "!!sourcechar,'l');
|
||||||
|
call symputx('syscc',99);
|
||||||
|
stop;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
else if sourcechar='"' then stop;
|
||||||
|
else put sourcechar char1.;
|
||||||
|
end;
|
||||||
run;
|
run;
|
||||||
%inc "&fpath3..lua";
|
|
||||||
|
%mp_abort(iftrue=("&syscc"="99")
|
||||||
|
,mac=mv_getjobcode
|
||||||
|
,msg=%str(&errmsg)
|
||||||
|
)
|
||||||
|
|
||||||
/* export to desired destination */
|
/* export to desired destination */
|
||||||
%if "&outref"="0" %then %do;
|
%if "&outref"="0" %then %do;
|
||||||
data _null_;
|
data _null_;
|
||||||
@@ -169,7 +218,6 @@ run;
|
|||||||
/* clear refs */
|
/* clear refs */
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
filename &fname3 clear;
|
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%mend mv_getjobcode;
|
%mend mv_getjobcode;
|
||||||
|
|||||||
@@ -86,7 +86,8 @@
|
|||||||
@li mp_abort.sas
|
@li mp_abort.sas
|
||||||
@li mf_getplatform.sas
|
@li mf_getplatform.sas
|
||||||
@li mf_existfileref.sas
|
@li mf_existfileref.sas
|
||||||
@li ml_json.sas
|
@li mf_getuniquefileref.sas
|
||||||
|
@li mf_getuniquelibref.sas
|
||||||
|
|
||||||
**/
|
**/
|
||||||
|
|
||||||
@@ -95,7 +96,7 @@
|
|||||||
,grant_type=sas_services
|
,grant_type=sas_services
|
||||||
,mdebug=0
|
,mdebug=0
|
||||||
);
|
);
|
||||||
%local dbg;
|
%local dbg libref1 libref2 loglocation fname1 fname2;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname entry vars:;
|
%put &sysmacroname entry vars:;
|
||||||
%put _local_;
|
%put _local_;
|
||||||
@@ -154,8 +155,8 @@ options noquotelenmax;
|
|||||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||||
|
|
||||||
/* prepare request*/
|
/* prepare request*/
|
||||||
%local fname1;
|
|
||||||
%let fname1=%mf_getuniquefileref();
|
%let fname1=%mf_getuniquefileref();
|
||||||
|
%let fname2=%mf_getuniquefileref();
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname1 &oauth_bearer
|
||||||
url="&base_uri&uri";
|
url="&base_uri&uri";
|
||||||
headers
|
headers
|
||||||
@@ -175,37 +176,19 @@ run;
|
|||||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
%local fname2 fname3 fpath1 fpath2 fpath3;
|
|
||||||
%let fname2=%mf_getuniquefileref();
|
|
||||||
%let fname3=%mf_getuniquefileref();
|
|
||||||
%let fpath1=%sysfunc(pathname(&fname1));
|
|
||||||
%let fpath2=%sysfunc(pathname(&fname2));
|
|
||||||
%let fpath3=%sysfunc(pathname(&fname3));
|
|
||||||
|
|
||||||
/* compile the lua JSON module */
|
%let libref1=%mf_getuniquelibref();
|
||||||
%ml_json()
|
libname &libref1 JSON fileref=&fname1;
|
||||||
/* read using LUA - this allows the code to be of any length */
|
|
||||||
data _null_;
|
data _null_;
|
||||||
file "&fpath3..lua";
|
set &libref1..root;
|
||||||
put '
|
call symputx('loglocation',loglocation,'l');
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
|
||||||
io.input(infile)
|
|
||||||
local resp=json.decode(io.read())
|
|
||||||
local logloc=resp["logLocation"]
|
|
||||||
outfile:write(logloc)
|
|
||||||
io.close(infile)
|
|
||||||
io.close(outfile)
|
|
||||||
';
|
|
||||||
run;
|
run;
|
||||||
%inc "&fpath3..lua";
|
|
||||||
/* get log path*/
|
/* validate log path*/
|
||||||
%let errflg=1;
|
%let errflg=1;
|
||||||
%let errmsg=No entry in &fname2 fileref;
|
%let errmsg=No loglocation entry in &fname1 fileref;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname2;
|
uri=symget('loglocation');
|
||||||
input;
|
|
||||||
uri=cats(_infile_);
|
|
||||||
if length(uri)<12 then do;
|
if length(uri)<12 then do;
|
||||||
call symputx('errflg',1);
|
call symputx('errflg',1);
|
||||||
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
call symputx('errmsg',"URI is invalid (too short) - '&uri'",'l');
|
||||||
@@ -232,7 +215,7 @@ run;
|
|||||||
|
|
||||||
/* we have a log uri - now fetch the log */
|
/* we have a log uri - now fetch the log */
|
||||||
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
%&dbg.put &sysmacroname: querying &base_uri&logloc/content;
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname2 &oauth_bearer
|
||||||
url="&base_uri&logloc/content?limit=10000";
|
url="&base_uri&logloc/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -243,14 +226,14 @@ run;
|
|||||||
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/content;
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
%if &SYS_PROCHTTP_STATUS_CODE=400 %then %do;
|
||||||
/* fetch log from parent session */
|
/* fetch log from parent session */
|
||||||
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
%let logloc=%substr(&logloc,1,%index(&logloc,%str(/jobs/))-1);
|
||||||
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
%&dbg.put &sysmacroname: Now querying &base_uri&logloc/log/content;
|
||||||
proc http method='GET' out=&fname1 &oauth_bearer
|
proc http method='GET' out=&fname2 &oauth_bearer
|
||||||
url="&base_uri&logloc/log/content?limit=10000";
|
url="&base_uri&logloc/log/content?limit=10000";
|
||||||
headers
|
headers
|
||||||
%if &grant_type=authorization_code %then %do;
|
%if &grant_type=authorization_code %then %do;
|
||||||
@@ -260,47 +243,32 @@ run;
|
|||||||
run;
|
run;
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
%put &sysmacroname: fetching log content from &base_uri&logloc/log/content;
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%end;
|
%end;
|
||||||
|
|
||||||
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
%if &SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201
|
||||||
%then %do;
|
%then %do;
|
||||||
%if &mdebug ne 1 %then %do; /* have already output above */
|
%if &mdebug ne 1 %then %do; /* have already output above */
|
||||||
data _null_;infile &fname1;input;putlog _infile_;run;
|
data _null_;infile &fname2;input;putlog _infile_;run;
|
||||||
%end;
|
%end;
|
||||||
%mp_abort(mac=&sysmacroname
|
%mp_abort(mac=&sysmacroname
|
||||||
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
,msg=%str(logfetch: &SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||||
)
|
)
|
||||||
%end;
|
%end;
|
||||||
data _null_;
|
|
||||||
file "&fpath3..lua";
|
|
||||||
put '
|
|
||||||
infile = io.open (sas.symget("fpath1"), "r")
|
|
||||||
outfile = io.open (sas.symget("fpath2"), "w")
|
|
||||||
io.input(infile)
|
|
||||||
local resp=json.decode(io.read())
|
|
||||||
for i, v in pairs(resp["items"]) do
|
|
||||||
outfile:write(v.line,"\n")
|
|
||||||
end
|
|
||||||
io.close(infile)
|
|
||||||
io.close(outfile)
|
|
||||||
';
|
|
||||||
run;
|
|
||||||
%inc "&fpath3..lua";
|
|
||||||
|
|
||||||
/* write log out to the specified fileref */
|
%let libref2=%mf_getuniquelibref();
|
||||||
|
libname &libref2 JSON fileref=&fname2;
|
||||||
data _null_;
|
data _null_;
|
||||||
infile &fname2 end=last;
|
|
||||||
file &outref mod;
|
file &outref mod;
|
||||||
if _n_=1 then do;
|
if _n_=1 then do;
|
||||||
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
put "/** SASJS Viya Job Log Extract start: &uri **/";
|
||||||
end;
|
end;
|
||||||
input;
|
set &libref2..items end=last;
|
||||||
put _infile_;
|
|
||||||
%if &mdebug=1 %then %do;
|
%if &mdebug=1 %then %do;
|
||||||
putlog _infile_;
|
putlog line;
|
||||||
%end;
|
%end;
|
||||||
|
put line;
|
||||||
if last then do;
|
if last then do;
|
||||||
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
put "/** SASJS Viya Job Log Extract end: &uri **/";
|
||||||
end;
|
end;
|
||||||
@@ -309,7 +277,8 @@ run;
|
|||||||
%if &mdebug=0 %then %do;
|
%if &mdebug=0 %then %do;
|
||||||
filename &fname1 clear;
|
filename &fname1 clear;
|
||||||
filename &fname2 clear;
|
filename &fname2 clear;
|
||||||
filename &fname3 clear;
|
libname &libref1 clear;
|
||||||
|
libname &libref2 clear;
|
||||||
%end;
|
%end;
|
||||||
%else %do;
|
%else %do;
|
||||||
%put &sysmacroname exit vars:;
|
%put &sysmacroname exit vars:;
|
||||||
|
|||||||
Reference in New Issue
Block a user