Files
dc/sas/sasjs/targets/server/services_server/admin/makedata.sas
T
dc c0ea810766
Build / Build-and-ng-test (pull_request) Successful in 4m54s
Lighthouse Checks / lighthouse (pull_request) Successful in 20m1s
Build / Build-and-test-development (pull_request) Successful in 32m10s
fix(makedata): pair the %else of the keepme block so it parses in open code
The self-destruct block ends with a single-statement %else in open code:

    %if &keepme ne 1 %then %do;
      %mv_deletejes(path=&root/admin, name=makedata);
    %end;
    %else %put NOTE: &_program retained, as KEEPME was requested;

Outside a macro SAS pairs %else only with a %do branch, so this stops with
'ERROR: Expected %DO not found' and 'ERROR: Skipping to next %END statement'
after the deployment has completed. On Viya the job then reports state error
with jobConditionCode 1012, so a successful deployment looks like a failure
exactly when someone is watching a first install.

Both branches now use %do/%end, which is the pattern the repo uses elsewhere
for this reason - see db/migrations/20261003_row_and_cell_limits.sas.

The same block is fixed in the server variant. The two delete calls also gain
their terminating semicolons: the macro call worked without them, but their
absence is what made the block look responsible for the error.

Behaviour is unchanged: the program still deletes itself unless KEEPME was
requested.
2026-10-28 16:38:21 +00:00

228 lines
6.5 KiB
SAS

/**
@file
@brief service for creating the configuration tables
@details
STP for creating the configuration tables.
It also adds the STAGING directory as subdirectory to the BASE
library location.
@warning This STP self destructs! It will delete itself (and the
configurator) after a successful run, to avoid being executed twice and
overwriting actual data. Pass a KEEPME column in the input data to keep
them - test harnesses reseed before every run and cannot redeploy first.
@sasjslint {"noBannedStrings": false}
<h4> SAS Macros </h4>
@li mf_getapploc.sas
@li mf_mkdir.sas
@li mp_abort.sas
@li mpe_makedata.sas
@li mpe_makedatamodel.sas
@li ms_createfile.sas
@li ms_deletefile.sas
@version 9.2
@author 4GL Apps Ltd
@copyright 4GL Apps Ltd. This code may only be used within Data Controller
and may not be re-distributed or re-sold without the express permission of
4GL Apps Ltd.
**/
%global path ADMIN OUTFMT;
/* response format - HTML (default) or JSON */
%let OUTFMT=HTML;
%webout(FETCH)
/* enable vars to be passed as url params */
%let exist=%sysfunc(exist(work.fromjs));
%let inds=%sysfunc(ifc(&exist=1,fromjs,_null_));
data _null_;
set &inds;
call symputx('path',dcpath);
call symputx('ADMIN',ADMIN);
run;
/* check if a JSON response was requested (OUTFMT column in fromjs) */
%if &exist=1 %then %do;
data _null_;
dsid=open('work.fromjs');
if varnum(dsid,'OUTFMT')>0 then do;
set work.fromjs;
call symputx('OUTFMT',upcase(outfmt));
end;
rc=close(dsid);
stop;
run;
%end;
/* optional KEEPME column - keep this program and the configurator on the drive
* after a successful run. A normal install self-destructs so the seeding
* cannot be run twice over live data; a test harness reseeds before every run
* and wants them to stay put. */
%let keepme=0;
%if &exist=1 %then %do;
data _null_;
dsid=open('work.fromjs');
/* every row, not just the first: KEEPME may be set on any of them */
if varnum(dsid,'KEEPME')>0 then do until(eof);
set work.fromjs end=eof;
if upcase(cats(keepme)) in ('1','Y','YES','TRUE') then call symputx('keepme',1);
end;
rc=close(dsid);
stop;
run;
%end;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(Issue on makedata entry)
)
%let root=%mf_getapploc();
%let dc_libref=%upcase(DC%substr(%sysevalf(%sysfunc(datetime())/60),3,6));
%let dcpath=%trim(&path)/&dc_libref;
%put _all_;
%mf_mkdir(&dcpath)
libname &dc_libref "&dcpath";
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program..sas
,msg=%str(Libref (&dc_libref) could not be assigned to (&dcpath) )
)
/* check we have physical permissions to the DCLIB folder */
data _null_;
putlog "testing write to: &dcpath/permTest.txt";
putlog "sysuserid=&sysuserid";
data _null_;
file "&dcpath/permTest.txt";
run;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(User &sysuserid does not have WRITE permissions on physical
directory: &dcpath )
)
filename delfile "&dcpath/permTest.txt";
data _null_;
rc=fdelete('delfile');
run;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program..sas
,msg=%str(User &sysuserid could create (but not delete) &dcpath/permTest.txt )
)
/* SASAdministrators */
%let admin=%sysfunc(coalescec(&admin,SASAdministrators));
%mpe_makedatamodel(lib=&dc_libref)
%mpe_makedata(lib=&DC_LIBREF,mpeadmins=&admin,path=%str(&dcpath))
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program..sas
,msg=%str(Problem creating tables in &DC_LIBREF library)
)
/* finally, update the app component. The user will need WM perms for this. */
filename stngs temp;
data _null_;
file stngs ;
put ' ';
put '%global dc_repo_users dc_macros dc_libref dc_staging_area dc_admin_group mpelib dc_dttmtfmt;';
put ' ';
put '%let dc_libref=' "&dc_libref;";
put ' ';
put '/* This metadata group has unrestricted access to Data Controller */';
put '%let dc_admin_group=' "&admin;";
put ' ';
put "libname &dc_libref '&dcpath' ;";
put ' ';
put '/* This physical location is used for staging data and audit history */';
put '%let dc_staging_area=' "&dcpath/dc_staging;";
put ' ';
put 'data _null_;';
put ' set &DC_LIBREF..mpe_config(where=(';
put ' var_scope="DC" ';
put ' and &dc_dttmtfmt. lt tx_to';
put ' and var_active=1';
put " ));";
put " call symputx(var_name,var_value,'G');";
put ' putlog var_name "=" var_value;';
put "run;";
put ' ';
put '/* to override any DC macros with client versions, place them below */';
put 'options insert=(sasautos=("&dc_macros"));';
put '%let mpelib=&DC_LIBREF;';
run;
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program
,msg=%str(syscc=syscc=&syscc when preparing data_controller_settings)
)
%ms_deletefile(&root/services/public/settings.sas)
%ms_createfile(&root/services/public/settings.sas, inref=stngs)
%mp_abort(iftrue= (&syscc ne 0)
,mac=&_program..sas
,msg=%str(Problem updating &root/services/public/settings)
)
%if &OUTFMT=JSON %then %do;
data work.makedata_response;
length STATUS $10 MESSAGE $256 DCPATH $256 LIBREF $8 ADMIN $64;
STATUS='SUCCESS';
MESSAGE="Data Controller Config created by &sysuserid";
DCPATH="&dcpath";
LIBREF="&DC_LIBREF";
ADMIN="&admin";
run;
%webout(OPEN)
%webout(OBJ, makedata_response)
%webout(CLOSE)
%end;
%else %do;
data _null_;
file _webout;
put '<h3>Data Controller Config</h3>';
put '<p>The following items have been successfully configured:</p>';
put "<ul><li>Library Location (&dcpath)</li>";
put "<li>Table Creation (&DC_LIBREF library) using the <b>&sysuserid</b> identity</li>";
put "<li>Logs Location (%trim(&dcpath)/logs)</li>";
put "<li>Data Controller Admin Group (&admin)</li>";
put "</ul>";
put 'Future configuration changes can be made <a href="';
put "/#/SASjsDrive?filePath=&root/services/public/settings";
put '">here</a></p>';
put "<p> Next Steps: </p>";
put "<ol><li>Populate<a target='_blank' href='";
put "/SASjsApi/stp/execute?_program=&root/services/admin/refreshcatalog'>";
put "Data Catalog</a></li>";
put "<li><a target='_blank' href='/AppStream/DataController'>Launch!</a>";
put "</li></ol>";
run;
%end;
/* We ran successfully, now remove configurator and makedata STPs, unless the
* caller asked to keep them (KEEPME in the input data). Keeping them is for
* test harnesses, which reseed before every run and cannot redeploy first. */
%if &keepme ne 1 %then %do;
%ms_deletefile(&root/services/admin/configurator.sas);
%ms_deletefile(&_program..sas);
%end;
%else %do;
%put NOTE: &_program retained, as KEEPME was requested;
%end;