mv_getjobcode.sas
Go to the documentation of this file.
1 /**
2  @file
3  @brief Extract the source code from a SAS Viya Job
4  @details Extracts the SAS code from a Job into a fileref or physical file.
5  Example:
6 
7  %mv_getjobcode(
8  path=/Public/jobs
9  ,name=some_job
10  ,outfile=/tmp/some_job.sas
11  )
12 
13  @param [in] access_token_var= The global macro variable to contain the access
14  token
15  @param [in] grant_type= valid values:
16  @li password
17  @liauthorization_code
18  @li detect - will check if access_token exists, if not will use sas_services
19  if a SASStudioV session else authorization_code. Default option.
20  @li sas_services - will use oauth_bearer=sas_services
21  @param [in] path= The SAS Drive path of the job
22  @param [in] name= The name of the job
23  @param [in] mdebug=(0) set to 1 to enable DEBUG messages
24  @param [out] outref=(0) A fileref to which to write the source code (will be
25  created with a TEMP engine)
26  @param [out] outfile=(0) A file to which to write the source code
27 
28  @version VIYA V.03.04
29  @author Allan Bowe, source: https://github.com/sasjs/core
30 
31  <h4> SAS Macros </h4>
32  @li mp_abort.sas
33  @li mf_getplatform.sas
34  @li mf_getuniquefileref.sas
35  @li mv_getfoldermembers.sas
36 
37 **/
38 
39 %macro mv_getjobcode(outref=0,outfile=0
40  ,name=0,path=0
41  ,contextName=SAS Job Execution compute context
42  ,access_token_var=ACCESS_TOKEN
43  ,grant_type=sas_services
44  ,mdebug=0
45  );
46 %local dbg bufsize varcnt fname1 fname2 errmsg;
47 %if &mdebug=1 %then %do;
48  %put &sysmacroname local entry vars:;
49  %put _local_;
50 %end;
51 %else %let dbg=*;
52 
53 %local oauth_bearer;
54 %if &grant_type=detect %then %do;
55  %if %symexist(&access_token_var) %then %let grant_type=authorization_code;
56  %else %let grant_type=sas_services;
57 %end;
58 %if &grant_type=sas_services %then %do;
59  %let oauth_bearer=oauth_bearer=sas_services;
60  %let &access_token_var=;
61 %end;
62 %mp_abort(iftrue=(&grant_type ne authorization_code and &grant_type ne password
63  and &grant_type ne sas_services
64  )
65  ,mac=&sysmacroname
66  ,msg=%str(Invalid value for grant_type: &grant_type)
67 )
68 %mp_abort(iftrue=("&path"="0")
69  ,mac=&sysmacroname
70  ,msg=%str(Job Path not provided)
71 )
72 %mp_abort(iftrue=("&name"="0")
73  ,mac=&sysmacroname
74  ,msg=%str(Job Name not provided)
75 )
76 %mp_abort(iftrue=("&outfile"="0" and "&outref"="0")
77  ,mac=&sysmacroname
78  ,msg=%str(Output destination (file or fileref) must be provided)
79 )
80 options noquotelenmax;
81 %local base_uri; /* location of rest apis */
82 %let base_uri=%mf_getplatform(VIYARESTAPI);
83 data;run;
84 %local foldermembers;
85 %let foldermembers=&syslast;
86 %mv_getfoldermembers(root=&path
87  ,access_token_var=&access_token_var
88  ,grant_type=&grant_type
89  ,outds=&foldermembers
90 )
91 %local joburi;
92 %let joburi=0;
93 data _null_;
94  length name uri $512;
95  call missing(name,uri);
96  set &foldermembers;
97  if name="&name" and uri=:'/jobDefinitions/definitions'
98  then call symputx('joburi',uri);
99 run;
100 %mp_abort(iftrue=("&joburi"="0")
101  ,mac=&sysmacroname
102  ,msg=%str(Job &path/&name not found)
103 )
104 
105 /* prepare request*/
106 %let fname1=%mf_getuniquefileref();
107 proc http method='GET' out=&fname1 &oauth_bearer
108  url="&base_uri&joburi";
109  headers "Accept"="application/vnd.sas.job.definition+json"
110  %if &grant_type=authorization_code %then %do;
111  "Authorization"="Bearer &&&access_token_var"
112  %end;
113  ;
114 run;
115 
116 %if &mdebug=1 %then %do;
117  data _null_;
118  infile &fname1;
119  input;
120  putlog _infile_;
121  run;
122 %end;
123 
124 %mp_abort(
125  iftrue=(&SYS_PROCHTTP_STATUS_CODE ne 200 and &SYS_PROCHTTP_STATUS_CODE ne 201)
126  ,mac=&sysmacroname
127  ,msg=%str(&SYS_PROCHTTP_STATUS_CODE &SYS_PROCHTTP_STATUS_PHRASE)
128 )
129 
130 %let fname2=%mf_getuniquefileref();
131 filename &fname2 temp ;
132 
133 /* cannot use lua IO package as not available in Viya 4 */
134 /* so use data step to read the JSON until the string `"code":"` is found */
135 data _null_;
136  file &fname2 recfm=n;
137  infile &fname1 lrecl=1 recfm=n;
138  input sourcechar $char1. @@;
139  format sourcechar hex2.;
140  retain startwrite 0;
141  if startwrite=0 and sourcechar='"' then do;
142  reentry:
143  input sourcechar $ 1. @@;
144  if sourcechar='c' then do;
145  reentry2:
146  input sourcechar $ 1. @@;
147  if sourcechar='o' then do;
148  input sourcechar $ 1. @@;
149  if sourcechar='d' then do;
150  input sourcechar $ 1. @@;
151  if sourcechar='e' then do;
152  input sourcechar $ 1. @@;
153  if sourcechar='"' then do;
154  input sourcechar $ 1. @@;
155  if sourcechar=':' then do;
156  input sourcechar $ 1. @@;
157  if sourcechar='"' then do;
158  putlog 'code found';
159  startwrite=1;
160  input sourcechar $ 1. @@;
161  end;
162  end;
163  else if sourcechar='c' then goto reentry2;
164  end;
165  end;
166  else if sourcechar='"' then goto reentry;
167  end;
168  else if sourcechar='"' then goto reentry;
169  end;
170  else if sourcechar='"' then goto reentry;
171  end;
172  else if sourcechar='"' then goto reentry;
173  end;
174  /* once the `"code":"` string is found, write until unescaped `"` is found */
175  if startwrite=1 then do;
176  if sourcechar='\' then do;
177  input sourcechar $ 1. @@;
178  if sourcechar in ('"','\') then put sourcechar char1.;
179  else if sourcechar='n' then put '0A'x;
180  else if sourcechar='r' then put '0D'x;
181  else if sourcechar='t' then put '09'x;
182  else if sourcechar='u' then do;
183  length uni $4;
184  input uni $ 4. @@;
185  sourcechar=unicode('\u'!!uni);
186  put sourcechar char1.;
187  end;
188  else do;
189  call symputx('errmsg',"Uncaught escape char: "!!sourcechar,'l');
190  call symputx('syscc',99);
191  stop;
192  end;
193  end;
194  else if sourcechar='"' then stop;
195  else put sourcechar char1.;
196  end;
197 run;
198 
199 %mp_abort(iftrue=("&syscc"="99")
200  ,mac=mv_getjobcode
201  ,msg=%str(&errmsg)
202 )
203 
204 /* export to desired destination */
205 %if "&outref"="0" %then %do;
206  data _null_;
207  file "&outfile" lrecl=32767;
208 %end;
209 %else %do;
210  filename &outref temp;
211  data _null_;
212  file &outref;
213 %end;
214  infile &fname2;
215  input;
216  put _infile_;
217  &dbg. putlog _infile_;
218 run;
219 
220 %if &mdebug=1 %then %do;
221  %put &sysmacroname exit vars:;
222  %put _local_;
223 %end;
224 %else %do;
225  /* clear refs */
226  filename &fname1 clear;
227  filename &fname2 clear;
228 %end;
229 
230 %mend mv_getjobcode;