/** @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: ![viya job location](https://i.imgur.com/XRUDHgA.png)

SAS Macros

@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; /* 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; /* DOUBLE QUOTE */ rc =fput(fileid,'\');rc =fwrite(fileid); rc =fput(fileid,'"');rc =fwrite(fileid); end; else if rec='0A'x then do; /* LF */ rc =fput(fileid,'\');rc =fwrite(fileid); rc =fput(fileid,'n');rc =fwrite(fileid); end; else if rec='0D'x then do; /* CR */ rc =fput(fileid,'\');rc =fwrite(fileid); rc =fput(fileid,'r');rc =fwrite(fileid); end; else if rec='09'x then do; /* TAB */ rc =fput(fileid,'\');rc =fwrite(fileid); rc =fput(fileid,'t');rc =fwrite(fileid); end; else if rec='5C'x then do; /* BACKSLASH */ 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;