-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSAS Content - Copy File from Filesystem.step
1 lines (1 loc) · 25.5 KB
/
SAS Content - Copy File from Filesystem.step
1
{"creationTimeStamp":"2023-12-07T06:11:57.043Z","modifiedTimeStamp":"2023-12-07T20:39:07.700Z","createdBy":"viya_admin","modifiedBy":"viya_admin","name":"SAS Content - Copy File from Filesystem.step","displayName":"SAS Content - Copy File from Filesystem.step","localDisplayName":"SAS Content - Copy File from Filesystem.step","properties":{},"links":[{"method":"GET","rel":"self","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","type":"application/vnd.sas.data.flow.step"},{"method":"GET","rel":"alternate","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","type":"application/vnd.sas.data.flow.step.summary"},{"method":"GET","rel":"up","href":"/dataFlows/steps","uri":"/dataFlows/steps","type":"application/vnd.sas.collection","itemType":"application/vnd.sas.data.flow.step.summary"},{"method":"PUT","rel":"update","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","type":"application/vnd.sas.data.flow.step","responseType":"application/vnd.sas.data.flow.step"},{"method":"DELETE","rel":"delete","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561"},{"method":"GET","rel":"transferExport","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","responseType":"application/vnd.sas.transfer.object"},{"method":"PUT","rel":"transferImportUpdate","href":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","uri":"/dataFlows/steps/3a9bda49-93f9-4126-a090-8c5d4e85d561","type":"application/vnd.sas.transfer.object","responseType":"application/vnd.sas.summary"}],"metadataVersion":0.0,"version":2,"type":"code","flowMetadata":{"inputPorts":[],"outputPorts":[]},"ui":"{\n\t\"showPageContentOnly\": true,\n\t\"pages\": [\n\t\t{\n\t\t\t\"id\": \"parameters\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"Parameters\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"sourceFile\",\n\t\t\t\t\t\"type\": \"path\",\n\t\t\t\t\t\"label\": \"Provide source file from filesystem:\",\n\t\t\t\t\t\"pathtype\": \"file\",\n\t\t\t\t\t\"placeholder\": \"/Example/Public/Some_Folder\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"targetFolder\",\n\t\t\t\t\t\"type\": \"path\",\n\t\t\t\t\t\"label\": \"Select destination folder:\",\n\t\t\t\t\t\"pathtype\": \"folder\",\n\t\t\t\t\t\"placeholder\": \"/Example/Public/Some_Folder\",\n\t\t\t\t\t\"required\": true,\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"id\": \"about\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"label\": \"About\",\n\t\t\t\"children\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_description\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"SAS Content - Copy File from Filesystem\\n============================\\n\\nThis custom step helps you copy a file from the filsystem (also referred to as \\\"shared storage\\\" or the SAS server) to a target SAS Content (also known as SAS Infrastructure Data Server) folder.\\n\\nThis custom step facilitates operations which require transfer of files from a filesystem location to the SAS Content folder. For example, users may wish to use source code from repositories such as GitHub or GitLab. This code gets pulled to filesystem folders but may be better suited for execution from SAS Content locations. \",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_parameters\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Parameters\",\n\t\t\t\t\t\"open\": 0,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"parameters_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"Note that this step only makes a copy of the file, and does not perform a cut operation. The source file will continue to remain on the filesystem unless explicitly deleted.\\n\\nThis custom step also wraps proc http calls to a SAS Viya endpoint. While it's likely that your environment's administrator has ensured the same, verify that north-south communication among pods is enabled / whitelisted in your environment. Proc http won't work for Viya endpoints (though they may for other endpoints) in such a case. Viya may consider the SAS Studio session pod IP (which is making the call) as not recognizable and therefore timeout the request. A quick check for this would be to run a simple proc http call (e.g. a get request) to your SAS Viya endpoint and note if you are able to get a response code of 200 (OK).\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"parameters_input\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Input Parameters\",\n\t\t\t\t\t\t\t\"open\": 1,\n\t\t\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"input_parameters_text\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"1. Source file from the filesystem (file selector, required): provide the full path of a desired file you wish to transfer to SAS Content. Note that this custom step makes use of the same file name when saving in SAS Content.\\n\\n2. Target folder in SAS Content (folder selector, required): select a folder inside SAS Content. \",\n\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"parameters_output_specs\",\n\t\t\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\t\t\"label\": \"Output Specifications\",\n\t\t\t\t\t\t\t\"open\": 1,\n\t\t\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"id\": \"output_parameters_text\",\n\t\t\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\t\t\"text\": \"The custom step provides a note informing that the file has been transferred. \\n\\nIn addition, there are some additional macro variables created which may be used for downstream tasks.\\n\\n1. targetFolderURI (global macro variable): this macro variable is created to hold the URI of the new folder for any downstream activity.\\n\\n2. contentFolderExists (global macro variable): this macro variable has a value of 1 if the SAS Content folder exists, a value of 0 in case it is not found, and 99 in case of other errors encountered during the check. Downstream code may consume these values.\\n\",\n\t\t\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_runtimecontrol\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Run-time Control\",\n\t\t\t\t\t\"open\": 0,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"runtimecontrol_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"\\nNote: Run-time control is optional. You may choose whether to execute the main code of this step or not, based on upstream conditions set by earlier SAS programs. This includes nodes run prior to this custom step earlier in a SAS Studio Flow, or a previous program in the same session.\\n\\nRefer this blog (https://communities.sas.com/t5/SAS-Communities-Library/Switch-on-switch-off-run-time-control-of-SAS-Studio-Custom-Steps/ta-p/885526) for more details on the concept.\\n\\nThe following macro variable,\\n\\n_cff_run_trigger\\n\\nwill initialize with a value of 1 by default, indicating an \\\"enabled\\\" status and allowing the custom step to run.\\n\\nIf you wish to control execution of this custom step, include code in an upstream SAS program to set this variable to 0. This \\\"disables\\\" execution of the custom step.\\n\\nTo \\\"disable\\\" this step, run the following code upstream:\\n\\n%global _cff_run_trigger;\\n%let _cff_run_trigger =0;\\n\\nTo \\\"enable\\\" this step again, run the following (it's assumed that this has already been set as a global variable):\\n\\n%let _cff_run_trigger =1;\\n\\nIMPORTANT: Be aware that disabling this step means that none of its main execution code will run, and any downstream code which was dependent on this code may fail. Change this setting only if it aligns with the objective of your SAS Studio program.\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"about_documentation\",\n\t\t\t\t\t\"type\": \"section\",\n\t\t\t\t\t\"label\": \"Documentation\",\n\t\t\t\t\t\"open\": 0,\n\t\t\t\t\t\"visible\": \"\",\n\t\t\t\t\t\"children\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"id\": \"documentation_text\",\n\t\t\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\t\t\"text\": \"1. SAS Documentation on the fcopy() function used for copying files: https://go.documentation.sas.com/doc/en/pgmsascdc/default/lefunctionsref/n10dz22b5ixohin1vwzilweetek0.htm\\n\\n2. SAS Communities article by Gerry Nelson which provides an example based on the fcopy() function which is used in this step: https://communities.sas.com/t5/SAS-Communities-Library/Making-SAS-programs-stored-on-the-file-system-available-to-SAS/ta-p/525688\\n\\n3. Reference macro from Bruno Mueller which provides an additional approach toward transferring binary files: https://blogs.sas.com/content/sasdummy/files/2013/09/binaryfilecopy.sas_.txt\\n\\n4. Note this section within the documentation on the filesrvc filename reference method. Note that the filesrvc filename reference results in an automatically generated macro variable containing the URI, which is in fact used within this custom step. However, the direct use of the filesrvc reference on a non-existent folder results in an error, which is handled by this custom step: https://go.documentation.sas.com/doc/en/pgmsascdc/default/lestmtsglobal/p0qapul7pyz9hmn0zfoefj0c278a.htm#p0nscb67k9xhr5n1fqx4pvnoed4f\\n\\n5. The 'proc http' sections of this steps inspired by similar code by David Weik for the purpose of transferring custom steps. His full code is located here: https://github.com/Criptic/sas_snippets/blob/master/Upload-and-Register-all-Custom-Steps.sas\\n\\n6. Identify whether a fileref exists: https://go.documentation.sas.com/doc/en/pgmsascdc/default/lefunctionsref/p0b6qacxrmnzc4n145t9jps0yzdc.htm\",\n\t\t\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"version_text\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"Version: 1.0 (07DEC2023)\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"contact_text\",\n\t\t\t\t\t\"type\": \"text\",\n\t\t\t\t\t\"text\": \"Created/contact: \\n\\n- Sundaresh Sankaran (sundaresh.sankaran@sas.com)\\n\",\n\t\t\t\t\t\"visible\": \"\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t],\n\t\"syntaxversion\": \"1.3.0\"\n}","templates":{"SAS":"/* templated code goes here*/;\n\n/*-----------------------------------------------------------------------------------------*\n START MACRO DEFINITIONS.\n*------------------------------------------------------------------------------------------*/\n\n/* -----------------------------------------------------------------------------------------* \n Error flag for capture during code execution.\n*------------------------------------------------------------------------------------------ */\n\n%global _cff_error_flag;\n%let _cff_error_flag=0;\n\n\n/* -----------------------------------------------------------------------------------------* \n Global macro variable for the trigger to run this custom step. A value of 1 \n (the default) enables this custom step to run. A value of 0 (provided by upstream code)\n sets this to disabled.\n*------------------------------------------------------------------------------------------ */\n\n%global _cff_run_trigger;\n\n%if %sysevalf(%superq(_cff_run_trigger)=, boolean) %then %do;\n\n\t%put NOTE: Trigger macro variable _cff_run_trigger does not exist. Creating it now.;\n %let _cff_run_trigger=1;\n\n%end;\n\n\n/* -----------------------------------------------------------------------------------------* \n Macro to identify whether a given folder location provided from a \n SAS Studio Custom Step folder selector happens to be a SAS Content folder\n or a folder on the filesystem (SAS Server).\n\n Inputs:\n 1. pathReference: A path reference provided by the file or folder selector control in \n a SAS Studio Custom step.\n\n Outputs:\n 1. _path_identifier: Set inside macro, a global variable indicating the prefix of the \n path provided.\n\n*------------------------------------------------------------------------------------------ */\n\n%macro _identify_content_or_server(pathReference);\n %global _path_identifier;\n data _null_;\n call symput(\"_path_identifier\", scan(\"&pathReference.\",1,\":\",\"MO\"));\n run;\n%mend _identify_content_or_server;\n\n\n/* -----------------------------------------------------------------------------------------* \n Macro to extract the path provided from a SAS Studio Custom Step file or folder selector.\n\n Inputs:\n 1. pathReference: A path reference provided by the file or folder selector control in \n a SAS Studio Custom step.\n\n Outputs:\n 1. _sas_folder_path: Set inside macro, a global variable containing the path.\n\n*------------------------------------------------------------------------------------------ */\n\n%macro _extract_sas_folder_path(pathReference);\n %global _sas_folder_path;\n data _null_;\n call symput(\"_sas_folder_path\", scan(\"&pathReference.\",2,\":\",\"MO\"));\n run;\n%mend _extract_sas_folder_path;\n\n\n/*-----------------------------------------------------------------------------------------*\n Macro to obtain the URI of a desired SAS Content folder if it exists.\n This macro will check a given path in SAS Content and set a macro variable to folder URI \n if it exists, or a direction to the error code if not.\n \n Inputs:\n 1. targetFolderContent: the full path of the folder to check for\n \n Outputs:\n 1. targetFolderURI (global variable): set inside macro to the URI of the folder\n 2. contentFolderExists (global variable): set to 0 if the folder does not exist, 1 if\n it does, and 99 in case of other conditions (such as HTTP request failure). \n Note this is a side objective / additional objective of the current macro.\n\n Also available standalone at: \n https://github.com/SundareshSankaran/sas_utility_programs/blob/main/code/Obtain%20SAS%20Content%20Folder%20URI/macro_obtain_sas_content_folder_uri.sas\n*------------------------------------------------------------------------------------------*/\n\n%macro _obtain_sas_content_folder_uri(targetFolderContent);\n\n %global targetFolderURI;\n %global contentFolderExists;\n\n /*-----------------------------------------------------------------------------------------*\n Create a JSON payload containing the folder to check for.\n *------------------------------------------------------------------------------------------*/\n %local targetPathJSON;\n\n data _null_;\n call symput(\"targetPathJSON\",'{\"items\": ['||'\"'||transtrn(strip(transtrn(&targetFolderContent.,\"/\",\" \")),\" \",'\",\"')||'\"'||'], \"contentType\": \"folder\"}');\n run;\n\n filename pathData temp;\n filename outResp temp;\n\n data _null_;\n length inputData $32767.;\n inputData = symget(\"targetPathJSON\");\n file pathData;\n\t put inputData;\n run;\n\n /*-----------------------------------------------------------------------------------------*\n Call the /folders/paths endpoint to obtain the URI of the desired folder.\n *------------------------------------------------------------------------------------------*/\n %local viyaHost;\n %let viyaHost=%sysfunc(getoption(SERVICESBASEURL));\n\n %put NOTE: The Viya host resolves to &viyaHost.;\n\n proc http\n\t method='POST'\n\t url=\"&viyaHost./folders/paths\"\n\t in=pathData \n\toauth_bearer=sas_services\n \tout=outResp;\n ;\n\theaders 'Content-Type'='application/vnd.sas.content.folder.path+json';\n quit;\n \n filename pathData clear;\n filename outResp clear;\n\n /*-----------------------------------------------------------------------------------------*\n In the event of a successful request, extract the URI\n *------------------------------------------------------------------------------------------*/\n\n %if \"&SYS_PROCHTTP_STATUS_CODE.\"=\"200\" %then %do;\n\n filename TEMPFNM filesrvc folderpath=&targetFolderContent.;\n\n /*-----------------------------------------------------------------------------------------*\n The Filename Filesrvc leads to an automatic macro variable which holds the URI. This \n will be assigned to the global variable.\n *------------------------------------------------------------------------------------------*/\n data _null_;\n\t call symput(\"targetFolderURI\", \"&_FILESRVC_TEMPFNM_URI.\");\n call symputx(\"contentFolderExists\", 1);\n run;\n\n filename TEMPFNM clear;\n %symdel _FILESRVC_TEMPFNM_URI;\n\n %end;\n %else %do;\n\n data _null_;\n call symput(\"targetFolderURI\", \"Refer SYS_PROCHTTP_STATUS_CODE macro variable.\");\n call symputx(\"_cff_error_flag\",1);\n run;\n\n /*-----------------------------------------------------------------------------------------*\n Note that this macro also doubles up as a check for a desired folder inside \n SAS Content. While it's desirable to have separate code/macros for every single desired \n operation, we are adding this additional output because it does not require significant \n computation (beyond the code below).\n *------------------------------------------------------------------------------------------*/\n\n %if \"&SYS_PROCHTTP_STATUS_CODE.\"=\"404\" %then %do;\n\n %put NOTE: Folder is not found. ;\n data _null_;\n call symputx(\"contentFolderExists\",0);\n run;\n\n %end;\n %else %do;\n\n %put ERROR: The HTTP request returned &SYS_PROCHTTP_STATUS_CODE. ;\n data _null_;\n call symputx(\"contentFolderExists\",99);\n run;\n\n %end;\n %end;\n\n%mend _obtain_sas_content_folder_uri;\n\n\n/*-----------------------------------------------------------------------------------------*\n EXECUTION CODE MACRO \n*------------------------------------------------------------------------------------------*/\n\n%macro _cff_main_execution_code;\n\n %local sasFolderPath;\n %local parentFolderURI;\n\n /*-----------------------------------------------------------------------------------------*\n Reset values of existing global variables (targetFolderURI and contentFolderExists) to \n zero, in case this custom step or macro had been used before. Users may like to \n save the values of these global variables prior to running this step.\n *------------------------------------------------------------------------------------------*/\n\n %if %symexist(targetFolderURI) %then %do;\n %let targetFolderURI=;\n %end;\n\n %if %symexist(contentFolderExists) %then %do;\n %let contentFolderExists=;\n %end;\n\n /*-----------------------------------------------------------------------------------------*\n Check if the folder path provided is in fact a SAS Content related path.\n *------------------------------------------------------------------------------------------*/\n\n %if &_cff_error_flag.=0 %then %do;\n %_identify_content_or_server(&sourceFile.);\n %if \"&_path_identifier.\"=\"sasserver\" %then %do;\n %put NOTE: The source file is provided from the filesystem and prefixed with &_path_identifier..;\n %end;\n %else %do;\n %let _cff_error_flag=1;\n %put ERROR: Path provided does not seem to be in the filesystem. Check your path. ;\n %end;\n %end;\n\n %if &_cff_error_flag.=0 %then %do;\n %_identify_content_or_server(&targetFolder.);\n %if \"&_path_identifier.\"=\"sascontent\" %then %do;\n %put NOTE: The path provided is prefixed with &_path_identifier. ;\n %end;\n %else %do;\n %let _cff_error_flag=1;\n %put ERROR: Path provided does not seem to be a SAS Content folder. Check your path. ;\n %end;\n %end;\n\n /*-----------------------------------------------------------------------------------------*\n Check if the given target folder actually exists.\n *------------------------------------------------------------------------------------------*/\n\n %if &_cff_error_flag. = 0 %then %do;\n\n %_extract_sas_folder_path(&targetFolder.);\n %let sasFolderPath=&_sas_folder_path.;\n %symdel _sas_folder_path;\n\n %_obtain_sas_content_folder_uri(\"&sasFolderPath.\");\n\n %if &contentFolderExists.=0 %then %do;\n\n %put ERROR: The target folder does not exist on SAS Content. Create the folder upstream.;\n %let _cff_error_flag=1;\n \n %end; \n %else %if &contentFolderExists.=99 %then %do;\n\n %put ERROR: Something went wrong during folder check. Refer SYS_PROCHTTP_STATUS_CODE macro variable as directed.;\n %let _cff_error_flag=1;\n \n %end; \n\n %end;\n\n %if &_cff_error_flag. = 0 %then %do;\n %put NOTE: Value of error: &_cff_error_flag.;\n \n /*-----------------------------------------------------------------------------------------*\n Create a sourceFilePath variable\n *------------------------------------------------------------------------------------------*/\n %_extract_sas_folder_path(&sourceFile.);\n %let sourceFilePath=&_sas_folder_path.;\n %let _sas_folder_path=;\n\n /*-----------------------------------------------------------------------------------------*\n Create source file reference. Use direct recfm=n\n *------------------------------------------------------------------------------------------*/\n\n filename srcfile \"&sourceFilePath.\" recfm=n;\n\n /*-----------------------------------------------------------------------------------------*\n Create a targetFilePath variable. Then extract targetFileName from sourceFilePath\n to use the same name in the filename option.\n *------------------------------------------------------------------------------------------*/\n %_extract_sas_folder_path(&targetFolder.);\n %let targetFilePath=&_sas_folder_path.;\n %let _sas_folder_path=;\n\n %let targetFileName=%sysfunc(substr(&sourceFilePath.,%sysfunc(index(&sourceFilePath.,%sysfunc(scan(\"&sourceFilePath.\",-1,\"/\"))))));\n\n /*-----------------------------------------------------------------------------------------*\n Create destination file reference. Use direct recfm=n\n *------------------------------------------------------------------------------------------*/\n\n filename destfile filesrvc folderpath=\"&targetFilePath.\" filename=\"&targetFileName.\" recfm=n;\n\n /*-----------------------------------------------------------------------------------------*\n Copy the file using the fcopy() function.\n *------------------------------------------------------------------------------------------*/\n data _null_;\n rc=fcopy(\"srcfile\",\"destfile\");\n msg=sysmsg();\n put rc=;\n put msg=;\n call symputx(\"_cff_error_flag\",rc);\n run;\n\n %if &_cff_error_flag.=0 %then %do;\n %put NOTE: The file has been successfully copied.;\n %put NOTE: Check &targetFilePath. for &targetFileName.;\n %end;\n %else %do;\n %put ERROR: Something went wrong during file copy. Check log for messages.;\n %end;\n\n %end;\n\n\n\n%mend _cff_main_execution_code;\n\n/*-----------------------------------------------------------------------------------------*\n END MACRO DEFINITIONS.\n*------------------------------------------------------------------------------------------*/\n\n/*-----------------------------------------------------------------------------------------*\n EXECUTION CODE\n The execution code is controlled by the trigger variable defined in this custom step. This\n trigger variable is in an \"enabled\" (value of 1) state by default, but in some cases, as \n dictated by logic, could be set to a \"disabled\" (value of 0) state.\n*------------------------------------------------------------------------------------------*/\n\n%if &_cff_run_trigger. = 1 %then %do;\n\n %_cff_main_execution_code;\n\n%end;\n%if &_cff_run_trigger. = 0 %then %do;\n\n %put NOTE: This step has been disabled. Nothing to do.;\n\n%end;\n\n\n/*-----------------------------------------------------------------------------------------*\n Clean up existing declarations, macro variables and macro definitions.\n*------------------------------------------------------------------------------------------*/\n\n%if %sysfunc(fileref(srcfile)) < 1 %then %do;\n filename srcfile clear;\n%end;\n%if %sysfunc(fileref(destfile)) < 1 %then %do;\n filename destfile clear;\n%end;\n\n%if %symexist(_cff_error_flag) %then %do;\n %symdel _cff_error_flag;\n%end;\n%if %symexist(sasFolderPath) %then %do;\n %symdel sasFolderPath;\n%end;\n%if %symexist(_cff_run_trigger) %then %do;\n %symdel _cff_run_trigger;\n%end;\n%if %symexist(targetFilePath) %then %do;\n %symdel targetFilePath;\n%end;\n%if %symexist(targetFileName) %then %do;\n %symdel targetFileName;\n%end;\n%if %symexist(sourceFilePath) %then %do;\n %symdel sourceFilePath;\n%end;\n\n\n%sysmacdelete _identify_content_or_server;\n%sysmacdelete _extract_sas_folder_path;\n%sysmacdelete _obtain_sas_content_folder_uri;\n%sysmacdelete _cff_main_execution_code;"}}