JCL Templates
Use templates to generate JCL dynamically in Grace workflows.
Grace offers powerful JCL templating capabilities, allowing you to customize the Job Control Language (JCL) generated for your z/OS job modules (compile
, linkedit
, execute
). While Grace provides sensible default JCL templates for these job types, you can supply your own template files using the job.jcl
field with a file://
prefix.
When Grace processes a job with jcl: file://path/to/mytemplate.jcl.tmpl
(and the --no-compile
flag is not used), it reads this file and processes it using Go's built-in text/template
engine. This allows you to use template variables and functions to dynamically construct your JCL based on data exposed by Grace from your grace.yml
and resolved values.
If your
file://
JCL source does not contain any Go template directives ({{ ... }}
), Grace will treat it as a static JCL file, and the "rendering" process will output its content verbatim.
Enabling JCL templating
To use JCL templating for a specific z/OS job:
-
Create a JCL template file (e.g.,
my_compile_job.jcl.tmpl
) in your project, typically within a./templates
or./jcl
subdirectory. -
In your
grace.yml
for the desired job, set thejcl
field to point to this file:
When grace deck
runs (without --no-compile
), it will read mycomp.jcl.tmpl
, populate it with the available data context, and write the rendered JCL to .grace/deck/MYCOMP.jcl
Available data context (JCLTemplateData
)
Grace exposes a structured set of data to your JCL templates. This data, referred to internally as JCLTemplateData
, allows you to access resolved values from your grace.yml
and Grace's internal processing.
Here are the top-level fields available:
General job data
-
{{ .JobName }}
(String) : Thename
of the current job fromgrace.yml
.- e.g.
MYCOMPILE
- e.g.
-
{{ .WorkflowId }}
(String) : The unique UUID of the current workflow run.- Note: This will be an empty string if
grace deck
is run outside the context of a fullgrace run
orgrace submit
(asdeck
itself doesn't produce a workflow UUID). Useful for adding unique qualifiers if needed, but rely on Grace'szos-temp://
hashing for DSN uniqueness.
- Note: This will be an empty string if
-
{{ .Type }}
(String) : Thetype
of the current job (e.g.,compile
,linkedit
,execute
).
Program and library data
These are resolved considering global config.defaults
and job-level overrides
.
-
{{ .ProgramName }}
(String) :- For
type: execute
: The name of the program to execute (fromjob.program
). - For
type: linkedit
: The name of the output load module (fromjob.program
). - For
type: compile
: The value ofjob.program
if specified (often for metadata or if a subsequent link-edit uses it by convention).
- For
-
{{ .LoadLib }}
(String) : The DSN of the resolved load library (fromdatasets.loadlib
or job-leveldatasets
override). -
Compiler specific (available for all z/OS job types, but most relevant for
type: compile
):{{ .CompilerPgm }}
(String) : Resolved program name for the compiler (e.g.IGYCRCTL
).{{ .CompilerParms }}
(String) : Resolved compiler parameters.{{ .CompilerSteplib }}
(String) : ResolvedSTEPLIB
DSN for the compiler (can be empty).
-
Linker specific (available for all z/OS job types, but most relevant for
type: linkedit
):{{ .LinkerPgm }}
(String) : Resolved program name for the linkage editor (e.g.IEWL
).{{ .LinkerParms }}
(String) : Resolved linkage editor parameters.{{ .LinkerSteplib }}
(String) : ResolvedSTEPLIB
DSN for the linkage editor (can be empty).
Input and output DD data
You have two way to include DD statements for your job's inputs
and outputs
:
-
{{ .DDStatements }}
- Type:
String
- Description: A pre-rendered block of JCL DD statements for all
inputs
andoutputs
defined for the job. Grace generates this block using standard JCL formatting and the resolved DSNs, dispositions, DCB, and space parameters. - Usage: Simply place
{{ .DDStatements }}
where you want these DDs to appear. This is the easiest way if you don't need to heavily customize individual DDs or intersperse them with other custom DD statements. - Example in template:
- Type:
-
{{ .Inputs }}
/{{ .Outputs }}
(granular control)- Type:
[]Object
- These are arrays of
ResolvedDD
objects.
- These are arrays of
- Description: These provide access to each resolved input and output individually, allowing you to loop through them and construct DD statements with custom formatting or logic.
- Structure:
{{ .Name }}
(String) : The DDName (e.g.SYSIN
,CUSTFILE
).{{ .DSN }}
(String) : The fully resolved physical DSN (e.g.IBMUSER.PROJ.SRC(MYPROG)
,IBMUSER.TEMP.H123AB.SYSLIN
).{{ .DISP }}
(String) : The resolved JCL disposition (e.g.SHR
,(NEW,CATLG,DELETE)
). This considersjob.disp
for outputs, and is overridden bykeep
.{{ .Space }}
(String,outputs
only) : The resolved JCLSPACE
parameter (e.g.(TRK,(5,2),RLSE)
).{{ .DCB }}
(String,outputs
only) : The resolved JCLDCB
parameter (e.g.RECFM=FB,LRECL=80
).{{ .IsOutput }}
(Boolean) :true
if this is from theoutputs
array,false
if frominputs
. (Useful if you process them in a combined loop, though ranging separately is common practice).
- Example in template:
Choose either
{{ .DDStatements }}
or the{{ range .Inputs/Outputs - }}
method for defining your data DDs. Using both for the same set of inputs/outputs will lead to duplicate DD statements. - Type:
Available template functions
Grace makes a few utility functions available in JCL templates:
{{ ToUpper .StringValue }}
Converts a string to uppercase.
- e.g.
//{{ .JobName | ToUpper }} JOB ...
results in//MYJOB JOB ...
{{ Default "fallback" .PossiblyEmptyValue }}
Provides a fallback value if .PossiblyEmptyValue
is null or an empty string.
- e.g.
//PARM='{{ Default "NOLIST" .LinkerParms }}'
- If
.LinkerParms
is""
, this becomesPARM='NOLIST'
. - If
.LinkerParms
is"LIST,MAP"
, this becomesPARM='LIST,MAP'
.
- If
Example JCL template (mycomp.jcl.tmpl
)
Tips for writing JCL templates
- Start simple: Begin by copying one of Grace's internal templates (from the
internal/templates/files/
directory in the Grace source code) and modify it. - Test iteratively: Use
grace deck --only JOBNAME
to quickly regenerate and inspect the JCL in.grace/deck/JOBNAME.jcl
after making changes to your template. - Refer to Go's
text/template
docs: For advanced templating logic (conditionals, loops, custom functions) beyond what is described here, consult the official Gotext/template
documentation. - Whitespace control: Use
{{ - ... - }}
(hyphens) to control whitespace around template actions if needed, to keep your generated JCL clean.
By leveraging JCL templating, you gain precise control and extensibility over the JCL submitted for your z/OS jobs while still benefitting from Grace's data resolution and workflow orchestration mechanisms.