# Templating with F5 BIG-IP FAST

BIG-IP FAST leverages existing, familiar technologies such as Mustache and JSON Schema to provide a complete templating solution that supports comprehensive parameter validation. 
Template text is written in [Mustache](https://mustache.github.io/mustache.5.html). 
That template text is then parsed to extract any parameters and provide basic JSON Schema for them. 
Users can write their own JSON Schema for each parameter to expand on the basic schema that is auto-generated by BIG-IP FAST. 
When rendering templates, this combined schema is then used to validate any inputs (parameters) to the template.

## Mustache
Mustache is not the templating engine.
Mustache is a specification for a templating language, and it specifies how the template file must look. 
You write templates adhering to the Mustache specification, and it works by expanding tags in a template using values provided in a hash or object. 
The template is then rendered to create an output.

[Here](getting_started.md#cli) is a simple example of rendering a template with the FAST CLI.

## Tags
Variables are expanded in a FAST template with the various [Mustache Tag Types](https://mustache.github.io/mustache.5.html#TAG-TYPES) -- which are easily identified by the double mustache of opening and closing curley braces {{ }}. 

A {{tenant}} tag in a template renders the value of the tenant parameter definition.

Template:
```yaml
definitions:
  template:
    type: string
    default: Tenant_1
  application_name:
    type: string
    default: App_1
  template: |
    {
        "{{tenant}}": {
            "class": "Tenant",
            "{{application_name}}": {
                "class": "Application"
            }
        }
    }
```

Parameters:
```yaml
{
    "tenant": "Tenant_2",
    "application_name": "App_2"
}
```

Outputs:
```javascript
    {
        "Tenant_2": {
            "class": "Tenant",
            "App_2": {
                "class": "Application"
            }
        }
    }
```

## Sections
For iterating over a list of data, we make use of [Mustache Sections](https://mustache.github.io/mustache.5.html#Sections).
The behavior of the section is determined by the value of the key.
Two types of lists can be created: Empty List or Non-Empty List.

### False Values or Empty Lists

If the parameter defition exists, and has a value of false, or an empty list, it will not be displayed. 
In the following example, the members' property definition has false assigned to it, so it will not be displayed.
Instead, the message indicating that members is missing or false will display in the [Inverted Section](https://mustache.github.io/mustache.5.html#Inverted-Sections).

Template:
```yaml
template: |
  Members:
  {{#members}} 
    "{{ . }}",
  {{/members}}
  {{^members}}
    "No members exist."
  {{/members}}
```

Parameters:
```yaml
  members: false
```

Output:
```
  Members:
    No members exist.
```

### Non-Empty Lists
When the members definition has a value that is a [Non-Empty Mustache List](https://mustache.github.io/mustache.5.html#Sections), the text in the block will be displayed once for each item in the list. 
The context of the block will be set to the current item for each iteration. 
The template in the previous example will loop over a collection of members, with the following parameter definition and output.

Parameters:
```yaml
  members: 
    - 10.0.0.1
    - 10.0.0.2
    - 10.0.0.3
```

Output:
```
  Members:
    10.0.0.1,
    10.0.0.2,
    10.0.0.3,
```


## Partials
Along with sections, Mustache utilizes partials. 
Mustache partials can be thought of as a way to insert template snippets. 
The syntax for including a partial uses curley braces and an angle bracket {{> }}.

For BIG-IP FAST, a partial definition must contain template text, i.e., define a template property
```yaml
definitions:
  partialDef:
    template: |
      {{#useVar}}
        {{var}}
      {{/useVar}}
  useVar:
    type: boolean
  template: |
  {{> partialDef}}
  {{> partialDef}}
```

Parameters:
```yaml
{
    "useVar": true,
    "var": "sample"
}
```

Outputs:
```yaml
    sample
    sample
```

> **See Also:** [Mustache Manual](https://mustache.github.io/mustache.5.html) for more information on Partials.


# Template Data Files

Sometimes it is desirable to keep a portion of a template in a separate file and include it into the template text.
This can be done with parameters and the `dataFile` property:

```javascript
const fast = require('@f5devcentral/f5-fast-core');

const templatesPath = '/path/to/templatesdir'; // directory containing example.data
const dataProvider = new fast.FsDataProvider(templatesPath);
const yamldata = `
    definitions:
        var:
            dataFile: example
    template: |
        {{var}}
`;

fast.Template.loadYaml(yamldata, { dataProvider })
    .then((template) => {
        console.log(template.getParametersSchema());
        console.log(template.render({virtual_port: 443});
    });
```
The `FsDataProvider` will pick up on any files with the `.data` extension in the template set directory.
When referencing the file in a template, use the filename (without the extension) as a key.

Parameters with a `dataFile` property:

* are removed from `required`
* have their `default` set to the contents of the file
* given a default `format` of `hidden`

Additionally, the contents of the data file can be base64-encoded before being used as for `default` by setting the `toBase64` property to `true`:

```yaml
definitions:
    var:
        dataFile: example
        toBase64: true
    template: |
        {{var}}
```

Similarly, if the data file is base64-encoded, it can be decoded using `fromBase64`.
If both `toBase64` and `fromBase64` are set, then `toBase64` takes precedence.

> **See Also:** [AS3 Schema Reference](https://clouddocs.f5.com/products/extensions/f5-appsvcs-extension/latest/refguide/schema-reference.html) for a full list of f5base64 fields.
