-
Notifications
You must be signed in to change notification settings - Fork 64
/
SAS Content - Create Folder.sas
405 lines (300 loc) · 14.6 KB
/
SAS Content - Create Folder.sas
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
/* templated code goes here*/;
/*-----------------------------------------------------------------------------------------*
START MACRO DEFINITIONS.
*------------------------------------------------------------------------------------------*/
/* -----------------------------------------------------------------------------------------*
Error flag for capture during code execution.
*------------------------------------------------------------------------------------------ */
%global _cf_error_flag;
%let _cf_error_flag=0;
/* -----------------------------------------------------------------------------------------*
Global macro variable for the trigger to run this custom step. A value of 1
(the default) enables this custom step to run. A value of 0 (provided by upstream code)
sets this to disabled.
*------------------------------------------------------------------------------------------ */
%global _cf_run_trigger;
%if %sysevalf(%superq(_cf_run_trigger)=, boolean) %then %do;
%put NOTE: Trigger macro variable _cf_run_trigger does not exist. Creating it now.;
%let _cf_run_trigger=1;
%end;
/* -----------------------------------------------------------------------------------------*
Macro to identify whether a given folder location provided from a
SAS Studio Custom Step folder selector happens to be a SAS Content folder
or a folder on the filesystem (SAS Server).
Inputs:
1. pathReference: A path reference provided by the file or folder selector control in
a SAS Studio Custom step.
Outputs:
1. _path_identifier: Set inside macro, a global variable indicating the prefix of the
path provided.
*------------------------------------------------------------------------------------------ */
%macro _identify_content_or_server(pathReference);
%global _path_identifier;
data _null_;
call symput("_path_identifier", scan(&pathReference.,1,":","MO"));
run;
%mend _identify_content_or_server;
/* -----------------------------------------------------------------------------------------*
Macro to extract the path provided from a SAS Studio Custom Step file or folder selector.
Inputs:
1. pathReference: A path reference provided by the file or folder selector control in
a SAS Studio Custom step.
Outputs:
1. _sas_folder_path: Set inside macro, a global variable containing the path.
*------------------------------------------------------------------------------------------ */
%macro _extract_sas_folder_path(pathReference);
%global _sas_folder_path;
data _null_;
call symput("_sas_folder_path", scan(&pathReference.,2,":","MO"));
run;
%mend _extract_sas_folder_path;
/*-----------------------------------------------------------------------------------------*
Macro to obtain the URI of a desired SAS Content folder if it exists.
This macro will check a given path in SAS Content and set a macro variable to folder URI
if it exists, or a direction to the error code if not.
Inputs:
1. targetFolderContent: the full path of the folder to check for
Outputs:
1. targetFolderURI (global variable): set inside macro to the URI of the folder
2. contentFolderExists (global variable): set to 0 if the folder does not exist, 1 if
it does, and 99 in case of other conditions (such as HTTP request failure).
Note this is a side objective / additional objective of the current macro.
Also available standalone at:
https://github.com/SundareshSankaran/sas_utility_programs/blob/main/code/Obtain%20SAS%20Content%20Folder%20URI/macro_obtain_sas_content_folder_uri.sas
*------------------------------------------------------------------------------------------*/
%macro _obtain_sas_content_folder_uri(targetFolderContent);
%global targetFolderURI;
%global contentFolderExists;
/*-----------------------------------------------------------------------------------------*
Create a JSON payload containing the folder to check for.
*------------------------------------------------------------------------------------------*/
%local targetPathJSON;
data _null_;
call symput("targetPathJSON",'{"items": ['||'"'||transtrn(strip(transtrn(&targetFolderContent.,"/"," "))," ",'","')||'"'||'], "contentType": "folder"}');
run;
filename pathData temp;
filename outResp temp;
data _null_;
length inputData $32767.;
inputData = symget("targetPathJSON");
file pathData;
put inputData;
run;
/*-----------------------------------------------------------------------------------------*
Call the /folders/paths endpoint to obtain the URI of the desired folder.
*------------------------------------------------------------------------------------------*/
%local viyaHost;
%let viyaHost=%sysfunc(getoption(SERVICESBASEURL));
%put NOTE: The Viya host resolves to &viyaHost.;
proc http
method='POST'
url="&viyaHost./folders/paths"
in=pathData
oauth_bearer=sas_services
out=outResp;
;
headers 'Content-Type'='application/vnd.sas.content.folder.path+json';
quit;
filename pathData clear;
filename outResp clear;
/*-----------------------------------------------------------------------------------------*
In the event of a successful request, extract the URI
*------------------------------------------------------------------------------------------*/
%if "&SYS_PROCHTTP_STATUS_CODE."="200" %then %do;
filename TEMPFNM filesrvc folderpath=&targetFolderContent.;
/*-----------------------------------------------------------------------------------------*
The Filename Filesrvc leads to an automatic macro variable which holds the URI. This
will be assigned to the global variable.
*------------------------------------------------------------------------------------------*/
data _null_;
call symput("targetFolderURI", "&_FILESRVC_TEMPFNM_URI.");
call symputx("contentFolderExists", 1);
run;
filename TEMPFNM clear;
%symdel _FILESRVC_TEMPFNM_URI;
%end;
%else %do;
data _null_;
call symput("targetFolderURI", "Refer SYS_PROCHTTP_STATUS_CODE macro variable.");
call symputx("_cf_error_flag",1);
run;
/*-----------------------------------------------------------------------------------------*
Note that this macro also doubles up as a check for a desired folder inside
SAS Content. While it's desirable to have separate code/macros for every single desired
operation, we are adding this additional output because it does not require significant
computation (beyond the code below).
*------------------------------------------------------------------------------------------*/
%if "&SYS_PROCHTTP_STATUS_CODE."="404" %then %do;
%put NOTE: Folder is not found. ;
data _null_;
call symputx("contentFolderExists",0);
run;
%end;
%else %do;
%put ERROR: The HTTP request returned &SYS_PROCHTTP_STATUS_CODE. ;
data _null_;
call symputx("contentFolderExists",99);
run;
%end;
%end;
%mend _obtain_sas_content_folder_uri;
/*-----------------------------------------------------------------------------------------*
This macro will create a desired SAS Content folder based on given parameter.
Inputs:
1. parentFolderURI: URI of the parent folder to the desired folder
2. folderName: Desired name for the folder to be created
Outputs:
1. targetFolderURI: Global variable containing URI of the folder that gets created.
2. folderCreated: Indicates that the folder got created (1) or not (0).
The system macro variable SYS_PROCHTTP_STATUS_CODE is surfaced within the log for
debugging.
*------------------------------------------------------------------------------------------*/
%macro _create_sas_content_folder(parentFolderURI,folderName);
/*-----------------------------------------------------------------------------------------*
Create a JSON payload containing the folder to check for.
*------------------------------------------------------------------------------------------*/
%global folderCreated;
%global targetFolderURI;
%local targetPathJSON;
%local folderNameNew;
%local viyaHost;
%local newFolderPath;
data _null_;
call symput("targetPathJSON",'{"name": "'||&folderName.||'","type": "folder"}');
call symput("folderNameNew",compress(&folderName.,'"'));
run;
filename pathData temp;
filename outResp temp;
data _null_;
length inputData $32767.;
inputData = symget("targetPathJSON");
file pathData;
put inputData;
run;
/*-----------------------------------------------------------------------------------------*
Call the /folders/paths endpoint to obtain the URI of the desired folder.
*------------------------------------------------------------------------------------------*/
%let viyaHost=%sysfunc(getoption(SERVICESBASEURL));
%put NOTE: The Viya host resolves to &viyaHost.;
proc http
method='POST'
url="&viyaHost./folders/folders?parentFolderUri=&parentFolderUri."
in=pathData
oauth_bearer=sas_services
out=outResp;
;
headers 'Content-Type'='application/vnd.sas.content.folder+json';
headers 'Accept'='application/vnd.sas.content.folder+json';
quit;
filename pathData clear;
filename outResp clear;
%if "&SYS_PROCHTTP_STATUS_CODE."="201" %then %do;
%put NOTE: Folder has been created.;
%let newFolderPath=%sysfunc(scan("&parentFolder./&folderNameNew.",2,":"));
filename TEMPFNM filesrvc folderpath="&newFolderPath.";
/*-----------------------------------------------------------------------------------------*
The Filename Filesrvc leads to an automatic macro variable which holds the URI. This
will be assigned to the global variable.
*------------------------------------------------------------------------------------------*/
data _null_;
call symput("targetFolderURI", "&_FILESRVC_TEMPFNM_URI.");
call symputx("folderCreated", 1);
run;
filename TEMPFNM clear;
%symdel _FILESRVC_TEMPFNM_URI;
%end;
%else %if "&SYS_PROCHTTP_STATUS_CODE."="409" %then %do;
%put ERROR: Folder already exists. Check location or name.;
%put ERROR: The SYS_PROCHTTP_STATUS_CODE. macro variable is &SYS_PROCHTTP_STATUS_CODE.;
data _null_;
call symput("targetFolderURI", " ");
call symputx("folderCreated", 0);
call symputx("_cf_error_flag",1);
run;
%end;
%else %do;
%put ERROR: The SYS_PROCHTTP_STATUS_CODE. macro variable is &SYS_PROCHTTP_STATUS_CODE.;
data _null_;
call symput("targetFolderURI", " ");
call symputx("folderCreated", 0);
call symputx("_cf_error_flag",1);
run;
%end;
%mend _create_sas_content_folder;
/*-----------------------------------------------------------------------------------------*
EXECUTION CODE MACRO
*------------------------------------------------------------------------------------------*/
%macro _cf_main_execution_code;
%local sasFolderPath;
%local parentFolderURI;
/*-----------------------------------------------------------------------------------------*
Reset values of existing global variables (targetFolderURI and contentFolderExists) to
zero, in case this custom step or macro had been used before. Users may like to
save the values of these global variables prior to running this step.
*------------------------------------------------------------------------------------------*/
%if %symexist(targetFolderURI) %then %do;
%let targetFolderURI=;
%end;
%if %symexist(contentFolderExists) %then %do;
%let contentFolderExists=;
%end;
%if %symexist(folderCreated) %then %do;
%let folderCreated=;
%end;
/*-----------------------------------------------------------------------------------------*
Check if the folder path provided is in fact a SAS Content related path.
*------------------------------------------------------------------------------------------*/
%_identify_content_or_server("&parentFolder.");
%if "&_path_identifier."="sascontent" %then %do;
%put NOTE: The path provided is prefixed with &_path_identifier. ;
%end;
%else %do;
%let _cf_error_flag=1;
%put ERROR: Path provided does not seem to be a SAS Content folder. Check your path. ;
%end;
%if &_cf_error_flag. = 0 %then %do;
/*-----------------------------------------------------------------------------------------*
Extract the folder path from the path reference provided.
*------------------------------------------------------------------------------------------*/
%_extract_sas_folder_path("&parentFolder.");
%let sasFolderPath=&_sas_folder_path.;
%symdel _sas_folder_path;
%_obtain_sas_content_folder_uri("&sasFolderPath.");
%end;
%if &_cf_error_flag. = 0 %then %do;
%let parentFolderURI = &targetFolderURI.;
%_create_sas_content_folder(&parentFolderURI.,"&folderName.");
%end;
%mend _cf_main_execution_code;
/*-----------------------------------------------------------------------------------------*
END MACRO DEFINITIONS.
*------------------------------------------------------------------------------------------*/
/*-----------------------------------------------------------------------------------------*
EXECUTION CODE
The execution code is controlled by the trigger variable defined in this custom step. This
trigger variable is in an "enabled" (value of 1) state by default, but in some cases, as
dictated by logic, could be set to a "disabled" (value of 0) state.
*------------------------------------------------------------------------------------------*/
%if &_cf_run_trigger. = 1 %then %do;
%_cf_main_execution_code;
%end;
%if &_cf_run_trigger. = 0 %then %do;
%put NOTE: This step has been disabled. Nothing to do.;
%end;
/*-----------------------------------------------------------------------------------------*
Clean up existing macro variables and macro definitions.
*------------------------------------------------------------------------------------------*/
%if %symexist(_cf_error_flag) %then %do;
%symdel _cf_error_flag;
%end;
%if %symexist(sasFolderPath) %then %do;
%symdel sasFolderPath;
%end;
%if %symexist(_cf_run_trigger) %then %do;
%symdel _cf_run_trigger;
%end;
%sysmacdelete _identify_content_or_server;
%sysmacdelete _extract_sas_folder_path;
%sysmacdelete _obtain_sas_content_folder_uri;
%sysmacdelete _create_sas_content_folder;
%sysmacdelete _cf_main_execution_code;