def ext_pillar(minion_id, pillar, resource, sequence, subkey=False, subkey_only=False):
    '''
    Evaluate Pepa templates
    '''
    roots = __opts__['pepa_roots']

    # Default input
    inp = {}
    inp['default'] = 'default'
    inp['hostname'] = minion_id

    if 'environment' in pillar:
        inp['environment'] = pillar['environment']
    elif 'environment' in __grains__:
        inp['environment'] = __grains__['environment']
    else:
        inp['environment'] = 'base'

    # Load templates
    output = inp
    output['pepa_templates'] = []
    immutable = {}

    for categ, info in [next(six.iteritems(s)) for s in sequence]:
        if categ not in inp:
            log.warning("Category is not defined: %s", categ)
            continue

        alias = None
        if isinstance(info, dict) and 'name' in info:
            alias = info['name']
        else:
            alias = categ

        templdir = None
        if info and 'base_only' in info and info['base_only']:
            templdir = os.path.join(roots['base'], resource, alias)
        else:
            templdir = os.path.join(roots[inp['environment']], resource, alias)

        entries = []
        if isinstance(inp[categ], list):
            entries = inp[categ]
        elif not inp[categ]:
            log.warning("Category has no value set: %s", categ)
            continue
        else:
            entries = [inp[categ]]

        for entry in entries:
            results_jinja = None
            results = None
            fn = os.path.join(templdir, re.sub(r'\W', '_', entry.lower()) + '.yaml')
            if os.path.isfile(fn):
                log.info("Loading template: %s", fn)
                with salt.utils.files.fopen(fn) as fhr:
                    template = jinja2.Template(fhr.read())
                output['pepa_templates'].append(fn)

                try:
                    data = key_value_to_tree(output)
                    data['grains'] = __grains__.copy()
                    data['pillar'] = pillar.copy()
                    results_jinja = template.render(data)
                    results = salt.utils.yaml.safe_load(results_jinja)
                except jinja2.UndefinedError as err:
                    log.error('Failed to parse JINJA template: %s\n%s', fn, err)
                except salt.utils.yaml.YAMLError as err:
                    log.error('Failed to parse YAML in template: %s\n%s', fn, err)
            else:
                log.info("Template doesn't exist: %s", fn)
                continue

            if results is not None:
                for key in results:
                    skey = key.rsplit(__opts__['pepa_delimiter'], 1)
                    rkey = None
                    operator = None
                    if len(skey) > 1 and key.rfind('()') > 0:
                        rkey = skey[0].rstrip(__opts__['pepa_delimiter'])
                        operator = skey[1]

                    if key in immutable:
                        log.warning('Key %s is immutable, changes are not allowed', key)
                    elif rkey in immutable:
                        log.warning("Key %s is immutable, changes are not allowed", rkey)
                    elif operator == 'merge()' or operator == 'imerge()':
                        if operator == 'merge()':
                            log.debug("Merge key %s: %s", rkey, results[key])
                        else:
                            log.debug("Set immutable and merge key %s: %s", rkey, results[key])
                            immutable[rkey] = True
                        if rkey not in output:
                            log.error('Cant\'t merge key %s doesn\'t exist', rkey)
                        elif not isinstance(results[key], type(output[rkey])):
                            log.error('Can\'t merge different types for key %s', rkey)
                        elif isinstance(results[key], dict):
                            output[rkey].update(results[key])
                        elif isinstance(results[key], list):
                            output[rkey].extend(results[key])
                        else:
                            log.error('Unsupported type need to be list or dict for key %s', rkey)
                    elif operator == 'unset()' or operator == 'iunset()':
                        if operator == 'unset()':
                            log.debug("Unset key %s", rkey)
                        else:
                            log.debug("Set immutable and unset key %s", rkey)
                            immutable[rkey] = True
                        if rkey in output:
                            del output[rkey]
                    elif operator == 'immutable()':
                        log.debug("Set immutable and substitute key %s: %s", rkey, results[key])
                        immutable[rkey] = True
                        output[rkey] = results[key]
                    elif operator is not None:
                        log.error('Unsupported operator %s, skipping key %s', operator, rkey)
                    else:
                        log.debug("Substitute key %s: %s", key, results[key])
                        output[key] = results[key]

    tree = key_value_to_tree(output)
    pillar_data = {}
    if subkey_only:
        pillar_data[resource] = tree.copy()
    elif subkey:
        pillar_data = tree
        pillar_data[resource] = tree.copy()
    else:
        pillar_data = tree
    if __opts__['pepa_validate']:
        pillar_data['pepa_keys'] = output.copy()
    return pillar_data