mirror of
https://github.com/sasjs/core.git
synced 2025-12-11 06:24:35 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| c0e33175cf | |||
| 2bfa72f48f | |||
| fdc2e8ac8a | |||
| 2a894419ab | |||
| 58bfc7b4aa |
521
all.sas
521
all.sas
@@ -2441,25 +2441,27 @@ run;
|
||||
@brief Create a CARDS file from a SAS dataset.
|
||||
@details Uses dataset attributes to convert all data into datalines.
|
||||
Running the generated file will rebuild the original dataset.
|
||||
usage:
|
||||
Usage:
|
||||
|
||||
%mp_ds2cards(base_ds=sashelp.class
|
||||
, cards_file= "C:\temp\class.sas"
|
||||
, maxobs=5)
|
||||
|
||||
stuff to add
|
||||
TODO:
|
||||
- labelling the dataset
|
||||
- explicity setting a unix LF
|
||||
- constraints / indexes etc
|
||||
|
||||
@param base_ds= Should be two level - eg work.blah. This is the table that
|
||||
@param [in] base_ds= Should be two level - eg work.blah. This is the table that
|
||||
is converted to a cards file.
|
||||
@param tgt_ds= Table that the generated cards file would create. Optional -
|
||||
@param [in] tgt_ds= Table that the generated cards file would create. Optional -
|
||||
if omitted, will be same as BASE_DS.
|
||||
@param cards_file= Location in which to write the (.sas) cards file
|
||||
@param maxobs= to limit output to the first <code>maxobs</code> observations
|
||||
@param showlog= whether to show generated cards file in the SAS log (YES/NO)
|
||||
@param outencoding= provide encoding value for file statement (eg utf-8)
|
||||
@param [out] cards_file= Location in which to write the (.sas) cards file
|
||||
@param [in] maxobs= to limit output to the first <code>maxobs</code> observations
|
||||
@param [in] showlog= whether to show generated cards file in the SAS log (YES/NO)
|
||||
@param [in] outencoding= provide encoding value for file statement (eg utf-8)
|
||||
@param [in] append= If NO then will rebuild the cards file if it already exists,
|
||||
otherwise will append to it. Used by the mp_lib2cards.sas macro.
|
||||
|
||||
|
||||
@version 9.2
|
||||
@@ -2472,6 +2474,7 @@ run;
|
||||
,random_sample=NO
|
||||
,showlog=YES
|
||||
,outencoding=
|
||||
,append=NO
|
||||
)/*/STORE SOURCE*/;
|
||||
%local i setds nvars;
|
||||
|
||||
@@ -2484,6 +2487,8 @@ run;
|
||||
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
|
||||
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
|
||||
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
|
||||
%if ("&append" = "") %then %let append=;
|
||||
%else %let append=mod;
|
||||
|
||||
/* get varcount */
|
||||
%let nvars=0;
|
||||
@@ -2610,7 +2615,7 @@ data _null_;
|
||||
run;
|
||||
|
||||
data _null_;
|
||||
file &cards_file. &outencoding lrecl=32767 termstr=nl;
|
||||
file &cards_file. &outencoding lrecl=32767 termstr=nl &append;
|
||||
length __attrib $32767;
|
||||
if _n_=1 then do;
|
||||
put '/*******************************************************************';
|
||||
@@ -4013,21 +4018,35 @@ create table &outds (rename=(
|
||||
%mend;/**
|
||||
@file
|
||||
@brief Convert all library members to CARDS files
|
||||
@details Gets list of members then calls the <code>%mp_ds2cards()</code>
|
||||
macro
|
||||
usage:
|
||||
@details Gets list of members then calls the <code>%mp_ds2cards()</code> macro.
|
||||
Usage:
|
||||
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= C:\temp )
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= C:\temp )
|
||||
|
||||
The output will be one cards file in the `outloc` directory per dataset in the
|
||||
input `lib` library. If the `outloc` directory does not exist, it is created.
|
||||
|
||||
To create a single SAS file with the first 1000 records of each table in a
|
||||
library you could use this syntax:
|
||||
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= /tmp
|
||||
, outfile= myfile.sas
|
||||
, maxobs= 1000
|
||||
)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_mkdir.sas
|
||||
@li mf_trimstr.sas
|
||||
@li mp_ds2cards.sas
|
||||
|
||||
@param lib= Library in which to convert all datasets
|
||||
@param outloc= Location in which to store output. Defaults to WORK library.
|
||||
Do not use a trailing slash (my/path not my/path/). No quotes.
|
||||
@param maxobs= limit output to the first <code>maxobs</code> observations
|
||||
@param [in] lib= Library in which to convert all datasets
|
||||
@param [out] outloc= Location in which to store output. Defaults to WORK
|
||||
library. No quotes.
|
||||
@param [out] outfile= Optional output file NAME - if provided, then will create
|
||||
a single output file instead of one file per input table.
|
||||
@param [in] maxobs= limit output to the first <code>maxobs</code> observations
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
@@ -4037,6 +4056,7 @@ create table &outds (rename=(
|
||||
,outloc=%sysfunc(pathname(work)) /* without trailing slash */
|
||||
,maxobs=max
|
||||
,random_sample=NO
|
||||
,outfile=0
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
/* Find the tables */
|
||||
@@ -4048,16 +4068,28 @@ select distinct lowcase(memname)
|
||||
from dictionary.tables
|
||||
where upcase(libname)="%upcase(&lib)";
|
||||
|
||||
/* trim trailing slash, if provided */
|
||||
%let outloc=%mf_trimstr(&outloc,/);
|
||||
%let outloc=%mf_trimstr(&outloc,\);
|
||||
|
||||
/* create the output directory */
|
||||
%mf_mkdir(&outloc)
|
||||
|
||||
/* create the cards files */
|
||||
%do x=1 %to %sysfunc(countw(&memlist));
|
||||
%let ds=%scan(&memlist,&x);
|
||||
%mp_ds2cards(base_ds=&lib..&ds
|
||||
,cards_file="&outloc/&ds..sas"
|
||||
,maxobs=&maxobs
|
||||
,random_sample=&random_sample)
|
||||
%let ds=%scan(&memlist,&x);
|
||||
%mp_ds2cards(base_ds=&lib..&ds
|
||||
,maxobs=&maxobs
|
||||
,random_sample=&random_sample
|
||||
%if "&outfile" ne "0" %then %do;
|
||||
,append=YES
|
||||
,cards_file="&outloc/&outfile"
|
||||
%end;
|
||||
%else %do;
|
||||
,append=NO
|
||||
,cards_file="&outloc/&ds..sas"
|
||||
%end;
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend;/**
|
||||
@@ -8073,20 +8105,117 @@ filename __outdoc clear;
|
||||
|
||||
%mend;
|
||||
/**
|
||||
@file mm_getfoldertree.sas
|
||||
@file
|
||||
@brief Returns all direct child members of a particular folder
|
||||
@details Displays the children for a particular folder, in a similar fashion
|
||||
to the viya counterpart (mv_getfoldermembers.sas)
|
||||
|
||||
Usage:
|
||||
|
||||
%mm_getfoldermembers(root=/, outds=rootfolders)
|
||||
|
||||
%mm_getfoldermembers(root=/User Folders/&sysuserid, outds=usercontent)
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> Data Outputs </h4>
|
||||
|
||||
Example for `root=/`:
|
||||
|
||||
|metauri $17|metaname $256|metatype $32|
|
||||
|---|---|---|
|
||||
|A5XLSNXI.AA000001|Products |Folder|
|
||||
|A5XLSNXI.AA000002|Shared Data |Folder|
|
||||
|A5XLSNXI.AA000003|User Folders |Folder|
|
||||
|A5XLSNXI.AA000004|System |Folder|
|
||||
|A5XLSNXI.AA00003K|30.SASApps |Folder|
|
||||
|A5XLSNXI.AA00006A|Public|Folder|
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mm_getfoldertree.sas
|
||||
@li mf_getuniquefileref.sas
|
||||
@li mf_getuniquelibref.sas
|
||||
|
||||
@version 9.4
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
%macro mm_getfoldermembers(
|
||||
root=
|
||||
,outds=work.mm_getfoldertree
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%if "&root" = "/" %then %do;
|
||||
%local fname1 fname2 fname3;
|
||||
%let fname1=%mf_getuniquefileref();
|
||||
%let fname2=%mf_getuniquefileref();
|
||||
%let fname3=%mf_getuniquefileref();
|
||||
data _null_ ;
|
||||
file &fname1 ;
|
||||
put '<GetMetadataObjects>' ;
|
||||
put '<Reposid>$METAREPOSITORY</Reposid>' ;
|
||||
put '<Type>Tree</Type>' ;
|
||||
put '<NS>SAS</NS>' ;
|
||||
put '<Flags>388</Flags>' ;
|
||||
put '<Options>' ;
|
||||
put '<XMLSelect search="Tree[SoftwareComponents/SoftwareComponent'@;
|
||||
put '[@Name=''BIP Service'']]"/>';
|
||||
put '</Options>' ;
|
||||
put '</GetMetadataObjects>' ;
|
||||
run ;
|
||||
proc metadata in=&fname1 out=&fname2 verbose;run;
|
||||
|
||||
/* create an XML map to read the response */
|
||||
data _null_;
|
||||
file &fname3;
|
||||
put '<SXLEMAP version="1.2" name="SASFolders">';
|
||||
put '<TABLE name="SASFolders">';
|
||||
put '<TABLE-PATH syntax="XPath">//Objects/Tree</TABLE-PATH>';
|
||||
put '<COLUMN name="metauri">><LENGTH>17</LENGTH>';
|
||||
put '<PATH syntax="XPath">//Objects/Tree/@Id</PATH></COLUMN>';
|
||||
put '<COLUMN name="metaname"><LENGTH>256</LENGTH>>';
|
||||
put '<PATH syntax="XPath">//Objects/Tree/@Name</PATH></COLUMN>';
|
||||
put '</TABLE></SXLEMAP>';
|
||||
run;
|
||||
%local libref1;
|
||||
%let libref1=%mf_getuniquelibref();
|
||||
libname &libref1 xml xmlfileref=&fname2 xmlmap=&fname3;
|
||||
|
||||
data &outds;
|
||||
length metatype $32;
|
||||
retain metatype 'Folder';
|
||||
set &libref1..sasfolders;
|
||||
run;
|
||||
|
||||
%end;
|
||||
%else %do;
|
||||
%mm_getfoldertree(root=&root, outds=&outds,depth=1)
|
||||
data &outds;
|
||||
set &outds(rename=(name=metaname publictype=metatype));
|
||||
keep metaname metauri metatype;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
/**
|
||||
@file
|
||||
@brief Returns all folders / subfolder content for a particular root
|
||||
@details Shows all members and SubTrees recursively for a particular root.
|
||||
Note - for big sites, this returns a lot of data! So you may wish to reduce
|
||||
the logging to speed up the process (see example below)
|
||||
the logging to speed up the process (see example below), OR - use mm_tree.sas
|
||||
which uses proc metadata and is far more efficient.
|
||||
|
||||
Usage:
|
||||
|
||||
options ps=max nonotes nosource;
|
||||
%mm_getfoldertree(root=/My/Meta/Path, outds=iwantthisdataset)
|
||||
options notes source;
|
||||
|
||||
@param root= the parent folder under which to return all contents
|
||||
@param outds= the dataset to create that contains the list of directories
|
||||
@param mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
|
||||
@@ -8134,7 +8263,7 @@ data &outds.TMP/view=&outds.TMP;
|
||||
__n1+1;
|
||||
/* Walk through all possible associations of this object. */
|
||||
__n2=1;
|
||||
if assoctype in ('Members','SubTrees') then
|
||||
if assoctype in ('Members','SubTrees') then
|
||||
do while(metadata_getnasn(pathuri,assoctype,__n2,metauri)>0);
|
||||
__n2+1;
|
||||
call missing(name,publictype,MetadataUpdated,MetadataCreated);
|
||||
@@ -10806,7 +10935,314 @@ options noquotelenmax;
|
||||
libname &libref1 clear;
|
||||
%end;
|
||||
%mend;/**
|
||||
@file mv_createwebservice.sas
|
||||
@file
|
||||
@brief Creates a Viya Job
|
||||
@details
|
||||
Code is passed in as one or more filerefs.
|
||||
|
||||
%* Step 1 - compile macros ;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* Step 2 - Create some SAS code and add it to a job;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
data some_code;
|
||||
set sashelp.class;
|
||||
run;
|
||||
;;;;
|
||||
%mv_createjob(path=/Public/app/sasjstemp/jobs/myjobs,name=myjob)
|
||||
|
||||
The path to the job will then be shown in the log, eg as follows:
|
||||
|
||||

|
||||
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_abort.sas
|
||||
@li mv_createfolder.sas
|
||||
@li mf_getuniquelibref.sas
|
||||
@li mf_getuniquefileref.sas
|
||||
@li mf_getplatform.sas
|
||||
@li mf_isblank.sas
|
||||
@li mv_deletejes.sas
|
||||
|
||||
@param path= The full path (on SAS Drive) where the job will be created
|
||||
@param name= The name of the job
|
||||
@param desc= The description of the job
|
||||
@param precode= Space separated list of filerefs, pointing to the code that
|
||||
needs to be attached to the beginning of the job
|
||||
@param code= Fileref(s) of the actual code to be added
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param replace= select NO to avoid replacing any existing job in that location
|
||||
@param contextname= Choose a specific context on which to run the Job. Leave
|
||||
blank to use the default context. From Viya 3.5 it is possible to configure
|
||||
a shared context - see
|
||||
https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
|
||||
|
||||
@version VIYA V.03.04
|
||||
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe)
|
||||
|
||||
**/
|
||||
|
||||
%macro mv_createjob(path=
|
||||
,name=
|
||||
,desc=Created by the mv_createjob.sas macro
|
||||
,precode=
|
||||
,code=ft15f001
|
||||
,access_token_var=ACCESS_TOKEN
|
||||
,grant_type=sas_services
|
||||
,replace=YES
|
||||
,debug=0
|
||||
,contextname=
|
||||
);
|
||||
%local oauth_bearer;
|
||||
%if &grant_type=detect %then %do;
|
||||
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
|
||||
%else %let grant_type=sas_services;
|
||||
%end;
|
||||
%if &grant_type=sas_services %then %do;
|
||||
%let oauth_bearer=oauth_bearer=sas_services;
|
||||
%let &access_token_var=;
|
||||
%end;
|
||||
%put &sysmacroname: grant_type=&grant_type;
|
||||
|
||||
/* initial validation checking */
|
||||
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
||||
and &grant_type ne sas_services
|
||||
)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(Invalid value for grant_type: &grant_type)
|
||||
)
|
||||
%mp_abort(iftrue=(%mf_isblank(&path)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(path value must be provided)
|
||||
)
|
||||
%mp_abort(iftrue=(%length(&path)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(path value must be provided)
|
||||
)
|
||||
%mp_abort(iftrue=(%mf_isblank(&name)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(name value must be provided)
|
||||
)
|
||||
|
||||
options noquotelenmax;
|
||||
|
||||
* remove any trailing slash ;
|
||||
%if "%substr(&path,%length(&path),1)" = "/" %then
|
||||
%let path=%substr(&path,1,%length(&path)-1);
|
||||
|
||||
/* ensure folder exists */
|
||||
%put &sysmacroname: Path &path being checked / created;
|
||||
%mv_createfolder(path=&path)
|
||||
|
||||
%local base_uri; /* location of rest apis */
|
||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||
|
||||
/* fetching folder details for provided path */
|
||||
%local fname1;
|
||||
%let fname1=%mf_getuniquefileref();
|
||||
proc http method='GET' out=&fname1 &oauth_bearer
|
||||
url="&base_uri/folders/folders/@item?path=&path";
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
headers "Authorization"="Bearer &&&access_token_var";
|
||||
%end;
|
||||
run;
|
||||
%if &debug %then %do;
|
||||
data _null_;
|
||||
infile &fname1;
|
||||
input;
|
||||
putlog _infile_;
|
||||
run;
|
||||
%end;
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
|
||||
/* path exists. Grab follow on link to check members */
|
||||
%local libref1;
|
||||
%let libref1=%mf_getuniquelibref();
|
||||
libname &libref1 JSON fileref=&fname1;
|
||||
|
||||
data _null_;
|
||||
set &libref1..links;
|
||||
if rel='members' then call symputx('membercheck',quote("&base_uri"!!trim(href)),'l');
|
||||
else if rel='self' then call symputx('parentFolderUri',href,'l');
|
||||
run;
|
||||
data _null_;
|
||||
set &libref1..root;
|
||||
call symputx('folderid',id,'l');
|
||||
run;
|
||||
%local fname2;
|
||||
%let fname2=%mf_getuniquefileref();
|
||||
proc http method='GET'
|
||||
out=&fname2
|
||||
&oauth_bearer
|
||||
url=%unquote(%superq(membercheck));
|
||||
headers
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
"Authorization"="Bearer &&&access_token_var"
|
||||
%end;
|
||||
'Accept'='application/vnd.sas.collection+json'
|
||||
'Accept-Language'='string';
|
||||
%if &debug=1 %then %do;
|
||||
debug level = 3;
|
||||
%end;
|
||||
run;
|
||||
/*data _null_;infile &fname2;input;putlog _infile_;run;*/
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
|
||||
%if %upcase(&replace)=YES %then %do;
|
||||
%mv_deletejes(path=&path, name=&name)
|
||||
%end;
|
||||
%else %do;
|
||||
/* check that job does not already exist in that folder */
|
||||
%local libref2;
|
||||
%let libref2=%mf_getuniquelibref();
|
||||
libname &libref2 JSON fileref=&fname2;
|
||||
%local exists; %let exists=0;
|
||||
data _null_;
|
||||
set &libref2..items;
|
||||
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then
|
||||
call symputx('exists',1,'l');
|
||||
run;
|
||||
%mp_abort(iftrue=(&exists=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(Job &name already exists in &path)
|
||||
)
|
||||
libname &libref2 clear;
|
||||
%end;
|
||||
|
||||
/* set up the body of the request to create the service */
|
||||
%local fname3;
|
||||
%let fname3=%mf_getuniquefileref();
|
||||
data _null_;
|
||||
file &fname3 TERMSTR=' ';
|
||||
length string $32767;
|
||||
string=cats('{"version": 0,"name":"'
|
||||
,"&name"
|
||||
,'","type":"Compute","parameters":[{"name":"_addjesbeginendmacros"'
|
||||
,',"type":"CHARACTER","defaultValue":"false"}');
|
||||
context=quote(cats(symget('contextname')));
|
||||
if context ne '""' then do;
|
||||
string=cats(string,',{"version": 1,"name": "_contextName","defaultValue":'
|
||||
,context,',"type":"CHARACTER","label":"Context Name","required": false}');
|
||||
end;
|
||||
string=cats(string,'],"code":"');
|
||||
put string;
|
||||
run;
|
||||
|
||||
|
||||
/* insert the code, escaping double quotes and carriage returns */
|
||||
%local x fref freflist;
|
||||
%let freflist= &precode &code ;
|
||||
%do x=1 %to %sysfunc(countw(&freflist));
|
||||
%let fref=%scan(&freflist,&x);
|
||||
%put &sysmacroname: adding &fref;
|
||||
data _null_;
|
||||
length filein 8 fileid 8;
|
||||
filein = fopen("&fref","I",1,"B");
|
||||
fileid = fopen("&fname3","A",1,"B");
|
||||
rec = "20"x;
|
||||
do while(fread(filein)=0);
|
||||
rc = fget(filein,rec,1);
|
||||
if rec='"' then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'"');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='0A'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'r');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='0D'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'n');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='09'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'t');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='5C'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
end;
|
||||
else do;
|
||||
rc =fput(fileid,rec);
|
||||
rc =fwrite(fileid);
|
||||
end;
|
||||
end;
|
||||
rc=fclose(filein);
|
||||
rc=fclose(fileid);
|
||||
run;
|
||||
%end;
|
||||
|
||||
/* finish off the body of the code file loaded to JES */
|
||||
data _null_;
|
||||
file &fname3 mod TERMSTR=' ';
|
||||
put '"}';
|
||||
run;
|
||||
|
||||
/* now we can create the job!! */
|
||||
%local fname4;
|
||||
%let fname4=%mf_getuniquefileref();
|
||||
proc http method='POST'
|
||||
in=&fname3
|
||||
out=&fname4
|
||||
&oauth_bearer
|
||||
url="&base_uri/jobDefinitions/definitions?parentFolderUri=&parentFolderUri";
|
||||
headers 'Content-Type'='application/vnd.sas.job.definition+json'
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
"Authorization"="Bearer &&&access_token_var"
|
||||
%end;
|
||||
"Accept"="application/vnd.sas.job.definition+json";
|
||||
%if &debug=1 %then %do;
|
||||
debug level = 3;
|
||||
%end;
|
||||
run;
|
||||
/*data _null_;infile &fname4;input;putlog _infile_;run;*/
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
/* clear refs */
|
||||
filename &fname1 clear;
|
||||
filename &fname2 clear;
|
||||
filename &fname3 clear;
|
||||
filename &fname4 clear;
|
||||
libname &libref1 clear;
|
||||
|
||||
/* get the url so we can give a helpful log message */
|
||||
%local url;
|
||||
data _null_;
|
||||
if symexist('_baseurl') then do;
|
||||
url=symget('_baseurl');
|
||||
if subpad(url,length(url)-9,9)='SASStudio'
|
||||
then url=substr(url,1,length(url)-11);
|
||||
else url="&systcpiphostname";
|
||||
end;
|
||||
else url="&systcpiphostname";
|
||||
call symputx('url',url);
|
||||
run;
|
||||
|
||||
|
||||
%put &sysmacroname: Job &name successfully created in &path;
|
||||
%put &sysmacroname:;
|
||||
%put &sysmacroname: Check it out here:;
|
||||
%put &sysmacroname:;%put;
|
||||
%put &url/SASJobExecution?_PROGRAM=&path/&name;%put;
|
||||
%put &sysmacroname:;
|
||||
%put &sysmacroname:;
|
||||
|
||||
%mend;
|
||||
/**
|
||||
@file
|
||||
@brief Creates a JobExecution web service if it doesn't already exist
|
||||
@details
|
||||
Code is passed in as one or more filerefs.
|
||||
@@ -12278,31 +12714,20 @@ filename &fname1 clear;
|
||||
%mend;/**
|
||||
@file mv_getgroups.sas
|
||||
@brief Creates a dataset with a list of viya groups
|
||||
@details First, be sure you have an access token (which requires an app token).
|
||||
|
||||
Using the macros here:
|
||||
@details First, load the macros:
|
||||
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
An administrator needs to set you up with an access code:
|
||||
Next, execute:
|
||||
|
||||
%mv_registerclient(outds=client)
|
||||
%mv_getgroups(outds=work.groups)
|
||||
|
||||
Navigate to the url from the log (opting in to the groups) and paste the
|
||||
access code below:
|
||||
|
||||
%mv_tokenauth(inds=client,code=wKDZYTEPK6)
|
||||
|
||||
Now we can run the macro!
|
||||
|
||||
%mv_getgroups()
|
||||
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
@param [in] access_token_var= The global macro variable to contain the access token
|
||||
@param [in] grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param outds= The library.dataset to be created that contains the list of groups
|
||||
@param [out] outds= The library.dataset to be created that contains the list of groups
|
||||
|
||||
|
||||
@version VIYA V.03.04
|
||||
|
||||
@@ -3,25 +3,27 @@
|
||||
@brief Create a CARDS file from a SAS dataset.
|
||||
@details Uses dataset attributes to convert all data into datalines.
|
||||
Running the generated file will rebuild the original dataset.
|
||||
usage:
|
||||
Usage:
|
||||
|
||||
%mp_ds2cards(base_ds=sashelp.class
|
||||
, cards_file= "C:\temp\class.sas"
|
||||
, maxobs=5)
|
||||
|
||||
stuff to add
|
||||
TODO:
|
||||
- labelling the dataset
|
||||
- explicity setting a unix LF
|
||||
- constraints / indexes etc
|
||||
|
||||
@param base_ds= Should be two level - eg work.blah. This is the table that
|
||||
@param [in] base_ds= Should be two level - eg work.blah. This is the table that
|
||||
is converted to a cards file.
|
||||
@param tgt_ds= Table that the generated cards file would create. Optional -
|
||||
@param [in] tgt_ds= Table that the generated cards file would create. Optional -
|
||||
if omitted, will be same as BASE_DS.
|
||||
@param cards_file= Location in which to write the (.sas) cards file
|
||||
@param maxobs= to limit output to the first <code>maxobs</code> observations
|
||||
@param showlog= whether to show generated cards file in the SAS log (YES/NO)
|
||||
@param outencoding= provide encoding value for file statement (eg utf-8)
|
||||
@param [out] cards_file= Location in which to write the (.sas) cards file
|
||||
@param [in] maxobs= to limit output to the first <code>maxobs</code> observations
|
||||
@param [in] showlog= whether to show generated cards file in the SAS log (YES/NO)
|
||||
@param [in] outencoding= provide encoding value for file statement (eg utf-8)
|
||||
@param [in] append= If NO then will rebuild the cards file if it already exists,
|
||||
otherwise will append to it. Used by the mp_lib2cards.sas macro.
|
||||
|
||||
|
||||
@version 9.2
|
||||
@@ -34,6 +36,7 @@
|
||||
,random_sample=NO
|
||||
,showlog=YES
|
||||
,outencoding=
|
||||
,append=NO
|
||||
)/*/STORE SOURCE*/;
|
||||
%local i setds nvars;
|
||||
|
||||
@@ -46,6 +49,8 @@
|
||||
%if (&tgt_ds = ) %then %let tgt_ds=&base_ds;
|
||||
%if %index(&tgt_ds,.)=0 %then %let tgt_ds=WORK.%scan(&base_ds,2,.);
|
||||
%if ("&outencoding" ne "") %then %let outencoding=encoding="&outencoding";
|
||||
%if ("&append" = "") %then %let append=;
|
||||
%else %let append=mod;
|
||||
|
||||
/* get varcount */
|
||||
%let nvars=0;
|
||||
@@ -172,7 +177,7 @@ data _null_;
|
||||
run;
|
||||
|
||||
data _null_;
|
||||
file &cards_file. &outencoding lrecl=32767 termstr=nl;
|
||||
file &cards_file. &outencoding lrecl=32767 termstr=nl &append;
|
||||
length __attrib $32767;
|
||||
if _n_=1 then do;
|
||||
put '/*******************************************************************';
|
||||
|
||||
@@ -1,21 +1,35 @@
|
||||
/**
|
||||
@file
|
||||
@brief Convert all library members to CARDS files
|
||||
@details Gets list of members then calls the <code>%mp_ds2cards()</code>
|
||||
macro
|
||||
usage:
|
||||
@details Gets list of members then calls the <code>%mp_ds2cards()</code> macro.
|
||||
Usage:
|
||||
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= C:\temp )
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= C:\temp )
|
||||
|
||||
The output will be one cards file in the `outloc` directory per dataset in the
|
||||
input `lib` library. If the `outloc` directory does not exist, it is created.
|
||||
|
||||
To create a single SAS file with the first 1000 records of each table in a
|
||||
library you could use this syntax:
|
||||
|
||||
%mp_lib2cards(lib=sashelp
|
||||
, outloc= /tmp
|
||||
, outfile= myfile.sas
|
||||
, maxobs= 1000
|
||||
)
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mf_mkdir.sas
|
||||
@li mf_trimstr.sas
|
||||
@li mp_ds2cards.sas
|
||||
|
||||
@param lib= Library in which to convert all datasets
|
||||
@param outloc= Location in which to store output. Defaults to WORK library.
|
||||
Do not use a trailing slash (my/path not my/path/). No quotes.
|
||||
@param maxobs= limit output to the first <code>maxobs</code> observations
|
||||
@param [in] lib= Library in which to convert all datasets
|
||||
@param [out] outloc= Location in which to store output. Defaults to WORK
|
||||
library. No quotes.
|
||||
@param [out] outfile= Optional output file NAME - if provided, then will create
|
||||
a single output file instead of one file per input table.
|
||||
@param [in] maxobs= limit output to the first <code>maxobs</code> observations
|
||||
|
||||
@version 9.2
|
||||
@author Allan Bowe
|
||||
@@ -25,6 +39,7 @@
|
||||
,outloc=%sysfunc(pathname(work)) /* without trailing slash */
|
||||
,maxobs=max
|
||||
,random_sample=NO
|
||||
,outfile=0
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
/* Find the tables */
|
||||
@@ -36,16 +51,28 @@ select distinct lowcase(memname)
|
||||
from dictionary.tables
|
||||
where upcase(libname)="%upcase(&lib)";
|
||||
|
||||
/* trim trailing slash, if provided */
|
||||
%let outloc=%mf_trimstr(&outloc,/);
|
||||
%let outloc=%mf_trimstr(&outloc,\);
|
||||
|
||||
/* create the output directory */
|
||||
%mf_mkdir(&outloc)
|
||||
|
||||
/* create the cards files */
|
||||
%do x=1 %to %sysfunc(countw(&memlist));
|
||||
%let ds=%scan(&memlist,&x);
|
||||
%mp_ds2cards(base_ds=&lib..&ds
|
||||
,cards_file="&outloc/&ds..sas"
|
||||
,maxobs=&maxobs
|
||||
,random_sample=&random_sample)
|
||||
%let ds=%scan(&memlist,&x);
|
||||
%mp_ds2cards(base_ds=&lib..&ds
|
||||
,maxobs=&maxobs
|
||||
,random_sample=&random_sample
|
||||
%if "&outfile" ne "0" %then %do;
|
||||
,append=YES
|
||||
,cards_file="&outloc/&outfile"
|
||||
%end;
|
||||
%else %do;
|
||||
,append=NO
|
||||
,cards_file="&outloc/&ds..sas"
|
||||
%end;
|
||||
)
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
95
meta/mm_getfoldermembers.sas
Normal file
95
meta/mm_getfoldermembers.sas
Normal file
@@ -0,0 +1,95 @@
|
||||
/**
|
||||
@file
|
||||
@brief Returns all direct child members of a particular folder
|
||||
@details Displays the children for a particular folder, in a similar fashion
|
||||
to the viya counterpart (mv_getfoldermembers.sas)
|
||||
|
||||
Usage:
|
||||
|
||||
%mm_getfoldermembers(root=/, outds=rootfolders)
|
||||
|
||||
%mm_getfoldermembers(root=/User Folders/&sysuserid, outds=usercontent)
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> Data Outputs </h4>
|
||||
|
||||
Example for `root=/`:
|
||||
|
||||
|metauri $17|metaname $256|metatype $32|
|
||||
|---|---|---|
|
||||
|A5XLSNXI.AA000001|Products |Folder|
|
||||
|A5XLSNXI.AA000002|Shared Data |Folder|
|
||||
|A5XLSNXI.AA000003|User Folders |Folder|
|
||||
|A5XLSNXI.AA000004|System |Folder|
|
||||
|A5XLSNXI.AA00003K|30.SASApps |Folder|
|
||||
|A5XLSNXI.AA00006A|Public|Folder|
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mm_getfoldertree.sas
|
||||
@li mf_getuniquefileref.sas
|
||||
@li mf_getuniquelibref.sas
|
||||
|
||||
@version 9.4
|
||||
@author Allan Bowe
|
||||
|
||||
**/
|
||||
%macro mm_getfoldermembers(
|
||||
root=
|
||||
,outds=work.mm_getfoldertree
|
||||
)/*/STORE SOURCE*/;
|
||||
|
||||
%if "&root" = "/" %then %do;
|
||||
%local fname1 fname2 fname3;
|
||||
%let fname1=%mf_getuniquefileref();
|
||||
%let fname2=%mf_getuniquefileref();
|
||||
%let fname3=%mf_getuniquefileref();
|
||||
data _null_ ;
|
||||
file &fname1 ;
|
||||
put '<GetMetadataObjects>' ;
|
||||
put '<Reposid>$METAREPOSITORY</Reposid>' ;
|
||||
put '<Type>Tree</Type>' ;
|
||||
put '<NS>SAS</NS>' ;
|
||||
put '<Flags>388</Flags>' ;
|
||||
put '<Options>' ;
|
||||
put '<XMLSelect search="Tree[SoftwareComponents/SoftwareComponent'@;
|
||||
put '[@Name=''BIP Service'']]"/>';
|
||||
put '</Options>' ;
|
||||
put '</GetMetadataObjects>' ;
|
||||
run ;
|
||||
proc metadata in=&fname1 out=&fname2 verbose;run;
|
||||
|
||||
/* create an XML map to read the response */
|
||||
data _null_;
|
||||
file &fname3;
|
||||
put '<SXLEMAP version="1.2" name="SASFolders">';
|
||||
put '<TABLE name="SASFolders">';
|
||||
put '<TABLE-PATH syntax="XPath">//Objects/Tree</TABLE-PATH>';
|
||||
put '<COLUMN name="metauri">><LENGTH>17</LENGTH>';
|
||||
put '<PATH syntax="XPath">//Objects/Tree/@Id</PATH></COLUMN>';
|
||||
put '<COLUMN name="metaname"><LENGTH>256</LENGTH>>';
|
||||
put '<PATH syntax="XPath">//Objects/Tree/@Name</PATH></COLUMN>';
|
||||
put '</TABLE></SXLEMAP>';
|
||||
run;
|
||||
%local libref1;
|
||||
%let libref1=%mf_getuniquelibref();
|
||||
libname &libref1 xml xmlfileref=&fname2 xmlmap=&fname3;
|
||||
|
||||
data &outds;
|
||||
length metatype $32;
|
||||
retain metatype 'Folder';
|
||||
set &libref1..sasfolders;
|
||||
run;
|
||||
|
||||
%end;
|
||||
%else %do;
|
||||
%mm_getfoldertree(root=&root, outds=&outds,depth=1)
|
||||
data &outds;
|
||||
set &outds(rename=(name=metaname publictype=metatype));
|
||||
keep metaname metauri metatype;
|
||||
run;
|
||||
%end;
|
||||
|
||||
%mend;
|
||||
@@ -1,18 +1,20 @@
|
||||
/**
|
||||
@file mm_getfoldertree.sas
|
||||
@file
|
||||
@brief Returns all folders / subfolder content for a particular root
|
||||
@details Shows all members and SubTrees recursively for a particular root.
|
||||
Note - for big sites, this returns a lot of data! So you may wish to reduce
|
||||
the logging to speed up the process (see example below)
|
||||
the logging to speed up the process (see example below), OR - use mm_tree.sas
|
||||
which uses proc metadata and is far more efficient.
|
||||
|
||||
Usage:
|
||||
|
||||
options ps=max nonotes nosource;
|
||||
%mm_getfoldertree(root=/My/Meta/Path, outds=iwantthisdataset)
|
||||
options notes source;
|
||||
|
||||
@param root= the parent folder under which to return all contents
|
||||
@param outds= the dataset to create that contains the list of directories
|
||||
@param mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
@param [in] root= the parent folder under which to return all contents
|
||||
@param [out] outds= the dataset to create that contains the list of directories
|
||||
@param [in] mDebug= set to 1 to show debug messages in the log
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
|
||||
@@ -60,7 +62,7 @@ data &outds.TMP/view=&outds.TMP;
|
||||
__n1+1;
|
||||
/* Walk through all possible associations of this object. */
|
||||
__n2=1;
|
||||
if assoctype in ('Members','SubTrees') then
|
||||
if assoctype in ('Members','SubTrees') then
|
||||
do while(metadata_getnasn(pathuri,assoctype,__n2,metauri)>0);
|
||||
__n2+1;
|
||||
call missing(name,publictype,MetadataUpdated,MetadataCreated);
|
||||
|
||||
@@ -20,7 +20,7 @@ HTML_EXTRA_STYLESHEET = $(DOXY_CONTENT)new_stylesheet.css
|
||||
INHERIT_DOCS = NO
|
||||
INLINE_INFO = NO
|
||||
INPUT = $(DOXY_CONTENT)../../README.md \
|
||||
$(DOXY_CONTENT)../../CONTRIBUTING.md \
|
||||
= $(DOXY_CONTENT)../../main.dox \
|
||||
$(DOXY_INPUT)
|
||||
USE_MDFILE_AS_MAINPAGE = README.md
|
||||
LAYOUT_FILE = $(DOXY_CONTENT)DoxygenLayout.xml
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
<!-- Navigation index tabs for HTML output -->
|
||||
<navindex>
|
||||
<tab type="mainpage" visible="yes" title="Home"/>
|
||||
<tab type="user" url="/contributing" title="Contributing"/>
|
||||
<tab type="pages" visible="no" title="" intro=""/>
|
||||
<tab type="modules" visible="no" title="" intro=""/>
|
||||
<tab type="namespaces" visible="no" title="">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"$schema": "https://cli.sasjs.io/sasjsconfig-schema.json",
|
||||
"macroFolders": ["../base", "../meta", "../metax", "../viya", "../lua"],
|
||||
"macroFolders": ["base", "meta", "metax", "viya", "lua"],
|
||||
"docConfig":{
|
||||
"displayMacroCore": false
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
# PROJECT: Macro Core Docs Build #
|
||||
####################################################################
|
||||
|
||||
cd ../..
|
||||
|
||||
sasjs doc
|
||||
|
||||
# refresh github pages site
|
||||
|
||||
307
viya/mv_createjob.sas
Normal file
307
viya/mv_createjob.sas
Normal file
@@ -0,0 +1,307 @@
|
||||
/**
|
||||
@file
|
||||
@brief Creates a Viya Job
|
||||
@details
|
||||
Code is passed in as one or more filerefs.
|
||||
|
||||
%* Step 1 - compile macros ;
|
||||
filename mc url "https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
%* Step 2 - Create some SAS code and add it to a job;
|
||||
filename ft15f001 temp;
|
||||
parmcards4;
|
||||
data some_code;
|
||||
set sashelp.class;
|
||||
run;
|
||||
;;;;
|
||||
%mv_createjob(path=/Public/app/sasjstemp/jobs/myjobs,name=myjob)
|
||||
|
||||
The path to the job will then be shown in the log, eg as follows:
|
||||
|
||||

|
||||
|
||||
|
||||
<h4> SAS Macros </h4>
|
||||
@li mp_abort.sas
|
||||
@li mv_createfolder.sas
|
||||
@li mf_getuniquelibref.sas
|
||||
@li mf_getuniquefileref.sas
|
||||
@li mf_getplatform.sas
|
||||
@li mf_isblank.sas
|
||||
@li mv_deletejes.sas
|
||||
|
||||
@param path= The full path (on SAS Drive) where the job will be created
|
||||
@param name= The name of the job
|
||||
@param desc= The description of the job
|
||||
@param precode= Space separated list of filerefs, pointing to the code that
|
||||
needs to be attached to the beginning of the job
|
||||
@param code= Fileref(s) of the actual code to be added
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param replace= select NO to avoid replacing any existing job in that location
|
||||
@param contextname= Choose a specific context on which to run the Job. Leave
|
||||
blank to use the default context. From Viya 3.5 it is possible to configure
|
||||
a shared context - see
|
||||
https://go.documentation.sas.com/?docsetId=calcontexts&docsetTarget=n1hjn8eobk5pyhn1wg3ja0drdl6h.htm&docsetVersion=3.5&locale=en
|
||||
|
||||
@version VIYA V.03.04
|
||||
@author [Allan Bowe](https://www.linkedin.com/in/allanbowe)
|
||||
|
||||
**/
|
||||
|
||||
%macro mv_createjob(path=
|
||||
,name=
|
||||
,desc=Created by the mv_createjob.sas macro
|
||||
,precode=
|
||||
,code=ft15f001
|
||||
,access_token_var=ACCESS_TOKEN
|
||||
,grant_type=sas_services
|
||||
,replace=YES
|
||||
,debug=0
|
||||
,contextname=
|
||||
);
|
||||
%local oauth_bearer;
|
||||
%if &grant_type=detect %then %do;
|
||||
%if %symexist(&access_token_var) %then %let grant_type=authorization_code;
|
||||
%else %let grant_type=sas_services;
|
||||
%end;
|
||||
%if &grant_type=sas_services %then %do;
|
||||
%let oauth_bearer=oauth_bearer=sas_services;
|
||||
%let &access_token_var=;
|
||||
%end;
|
||||
%put &sysmacroname: grant_type=&grant_type;
|
||||
|
||||
/* initial validation checking */
|
||||
%mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
|
||||
and &grant_type ne sas_services
|
||||
)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(Invalid value for grant_type: &grant_type)
|
||||
)
|
||||
%mp_abort(iftrue=(%mf_isblank(&path)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(path value must be provided)
|
||||
)
|
||||
%mp_abort(iftrue=(%length(&path)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(path value must be provided)
|
||||
)
|
||||
%mp_abort(iftrue=(%mf_isblank(&name)=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(name value must be provided)
|
||||
)
|
||||
|
||||
options noquotelenmax;
|
||||
|
||||
* remove any trailing slash ;
|
||||
%if "%substr(&path,%length(&path),1)" = "/" %then
|
||||
%let path=%substr(&path,1,%length(&path)-1);
|
||||
|
||||
/* ensure folder exists */
|
||||
%put &sysmacroname: Path &path being checked / created;
|
||||
%mv_createfolder(path=&path)
|
||||
|
||||
%local base_uri; /* location of rest apis */
|
||||
%let base_uri=%mf_getplatform(VIYARESTAPI);
|
||||
|
||||
/* fetching folder details for provided path */
|
||||
%local fname1;
|
||||
%let fname1=%mf_getuniquefileref();
|
||||
proc http method='GET' out=&fname1 &oauth_bearer
|
||||
url="&base_uri/folders/folders/@item?path=&path";
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
headers "Authorization"="Bearer &&&access_token_var";
|
||||
%end;
|
||||
run;
|
||||
%if &debug %then %do;
|
||||
data _null_;
|
||||
infile &fname1;
|
||||
input;
|
||||
putlog _infile_;
|
||||
run;
|
||||
%end;
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
|
||||
/* path exists. Grab follow on link to check members */
|
||||
%local libref1;
|
||||
%let libref1=%mf_getuniquelibref();
|
||||
libname &libref1 JSON fileref=&fname1;
|
||||
|
||||
data _null_;
|
||||
set &libref1..links;
|
||||
if rel='members' then call symputx('membercheck',quote("&base_uri"!!trim(href)),'l');
|
||||
else if rel='self' then call symputx('parentFolderUri',href,'l');
|
||||
run;
|
||||
data _null_;
|
||||
set &libref1..root;
|
||||
call symputx('folderid',id,'l');
|
||||
run;
|
||||
%local fname2;
|
||||
%let fname2=%mf_getuniquefileref();
|
||||
proc http method='GET'
|
||||
out=&fname2
|
||||
&oauth_bearer
|
||||
url=%unquote(%superq(membercheck));
|
||||
headers
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
"Authorization"="Bearer &&&access_token_var"
|
||||
%end;
|
||||
'Accept'='application/vnd.sas.collection+json'
|
||||
'Accept-Language'='string';
|
||||
%if &debug=1 %then %do;
|
||||
debug level = 3;
|
||||
%end;
|
||||
run;
|
||||
/*data _null_;infile &fname2;input;putlog _infile_;run;*/
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
|
||||
%if %upcase(&replace)=YES %then %do;
|
||||
%mv_deletejes(path=&path, name=&name)
|
||||
%end;
|
||||
%else %do;
|
||||
/* check that job does not already exist in that folder */
|
||||
%local libref2;
|
||||
%let libref2=%mf_getuniquelibref();
|
||||
libname &libref2 JSON fileref=&fname2;
|
||||
%local exists; %let exists=0;
|
||||
data _null_;
|
||||
set &libref2..items;
|
||||
if contenttype='jobDefinition' and upcase(name)="%upcase(&name)" then
|
||||
call symputx('exists',1,'l');
|
||||
run;
|
||||
%mp_abort(iftrue=(&exists=1)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(Job &name already exists in &path)
|
||||
)
|
||||
libname &libref2 clear;
|
||||
%end;
|
||||
|
||||
/* set up the body of the request to create the service */
|
||||
%local fname3;
|
||||
%let fname3=%mf_getuniquefileref();
|
||||
data _null_;
|
||||
file &fname3 TERMSTR=' ';
|
||||
length string $32767;
|
||||
string=cats('{"version": 0,"name":"'
|
||||
,"&name"
|
||||
,'","type":"Compute","parameters":[{"name":"_addjesbeginendmacros"'
|
||||
,',"type":"CHARACTER","defaultValue":"false"}');
|
||||
context=quote(cats(symget('contextname')));
|
||||
if context ne '""' then do;
|
||||
string=cats(string,',{"version": 1,"name": "_contextName","defaultValue":'
|
||||
,context,',"type":"CHARACTER","label":"Context Name","required": false}');
|
||||
end;
|
||||
string=cats(string,'],"code":"');
|
||||
put string;
|
||||
run;
|
||||
|
||||
|
||||
/* insert the code, escaping double quotes and carriage returns */
|
||||
%local x fref freflist;
|
||||
%let freflist= &precode &code ;
|
||||
%do x=1 %to %sysfunc(countw(&freflist));
|
||||
%let fref=%scan(&freflist,&x);
|
||||
%put &sysmacroname: adding &fref;
|
||||
data _null_;
|
||||
length filein 8 fileid 8;
|
||||
filein = fopen("&fref","I",1,"B");
|
||||
fileid = fopen("&fname3","A",1,"B");
|
||||
rec = "20"x;
|
||||
do while(fread(filein)=0);
|
||||
rc = fget(filein,rec,1);
|
||||
if rec='"' then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'"');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='0A'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'r');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='0D'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'n');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='09'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'t');rc =fwrite(fileid);
|
||||
end;
|
||||
else if rec='5C'x then do;
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
rc =fput(fileid,'\');rc =fwrite(fileid);
|
||||
end;
|
||||
else do;
|
||||
rc =fput(fileid,rec);
|
||||
rc =fwrite(fileid);
|
||||
end;
|
||||
end;
|
||||
rc=fclose(filein);
|
||||
rc=fclose(fileid);
|
||||
run;
|
||||
%end;
|
||||
|
||||
/* finish off the body of the code file loaded to JES */
|
||||
data _null_;
|
||||
file &fname3 mod TERMSTR=' ';
|
||||
put '"}';
|
||||
run;
|
||||
|
||||
/* now we can create the job!! */
|
||||
%local fname4;
|
||||
%let fname4=%mf_getuniquefileref();
|
||||
proc http method='POST'
|
||||
in=&fname3
|
||||
out=&fname4
|
||||
&oauth_bearer
|
||||
url="&base_uri/jobDefinitions/definitions?parentFolderUri=&parentFolderUri";
|
||||
headers 'Content-Type'='application/vnd.sas.job.definition+json'
|
||||
%if &grant_type=authorization_code %then %do;
|
||||
"Authorization"="Bearer &&&access_token_var"
|
||||
%end;
|
||||
"Accept"="application/vnd.sas.job.definition+json";
|
||||
%if &debug=1 %then %do;
|
||||
debug level = 3;
|
||||
%end;
|
||||
run;
|
||||
/*data _null_;infile &fname4;input;putlog _infile_;run;*/
|
||||
%mp_abort(iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 201)
|
||||
,mac=&sysmacroname
|
||||
,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
|
||||
)
|
||||
/* clear refs */
|
||||
filename &fname1 clear;
|
||||
filename &fname2 clear;
|
||||
filename &fname3 clear;
|
||||
filename &fname4 clear;
|
||||
libname &libref1 clear;
|
||||
|
||||
/* get the url so we can give a helpful log message */
|
||||
%local url;
|
||||
data _null_;
|
||||
if symexist('_baseurl') then do;
|
||||
url=symget('_baseurl');
|
||||
if subpad(url,length(url)-9,9)='SASStudio'
|
||||
then url=substr(url,1,length(url)-11);
|
||||
else url="&systcpiphostname";
|
||||
end;
|
||||
else url="&systcpiphostname";
|
||||
call symputx('url',url);
|
||||
run;
|
||||
|
||||
|
||||
%put &sysmacroname: Job &name successfully created in &path;
|
||||
%put &sysmacroname:;
|
||||
%put &sysmacroname: Check it out here:;
|
||||
%put &sysmacroname:;%put;
|
||||
%put &url/SASJobExecution?_PROGRAM=&path/&name;%put;
|
||||
%put &sysmacroname:;
|
||||
%put &sysmacroname:;
|
||||
|
||||
%mend;
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
@file mv_createwebservice.sas
|
||||
@file
|
||||
@brief Creates a JobExecution web service if it doesn't already exist
|
||||
@details
|
||||
Code is passed in as one or more filerefs.
|
||||
|
||||
@@ -1,31 +1,20 @@
|
||||
/**
|
||||
@file mv_getgroups.sas
|
||||
@brief Creates a dataset with a list of viya groups
|
||||
@details First, be sure you have an access token (which requires an app token).
|
||||
|
||||
Using the macros here:
|
||||
@details First, load the macros:
|
||||
|
||||
filename mc url
|
||||
"https://raw.githubusercontent.com/sasjs/core/main/all.sas";
|
||||
%inc mc;
|
||||
|
||||
An administrator needs to set you up with an access code:
|
||||
Next, execute:
|
||||
|
||||
%mv_registerclient(outds=client)
|
||||
%mv_getgroups(outds=work.groups)
|
||||
|
||||
Navigate to the url from the log (opting in to the groups) and paste the
|
||||
access code below:
|
||||
|
||||
%mv_tokenauth(inds=client,code=wKDZYTEPK6)
|
||||
|
||||
Now we can run the macro!
|
||||
|
||||
%mv_getgroups()
|
||||
|
||||
@param access_token_var= The global macro variable to contain the access token
|
||||
@param grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
@param [in] access_token_var= The global macro variable to contain the access token
|
||||
@param [in] grant_type= valid values are "password" or "authorization_code" (unquoted).
|
||||
The default is authorization_code.
|
||||
@param outds= The library.dataset to be created that contains the list of groups
|
||||
@param [out] outds= The library.dataset to be created that contains the list of groups
|
||||
|
||||
|
||||
@version VIYA V.03.04
|
||||
|
||||
Reference in New Issue
Block a user