func (s *ShoelacesTemplates) ParseTemplates(logger log.Logger, dataDir string, envDir string, envs []string, tplExt string) {
	s.dataDir = dataDir
	s.envDir = envDir
	s.tplExt = tplExt
	logger.Debug("component", "template", "msg", "Template parsing started", "dir", dataDir)
	tplScannerDefault := func(p string, info os.FileInfo, err error) error {
		if strings.HasPrefix(p, path.Join(dataDir, envDir)) {
			return err
		}
		if strings.HasSuffix(p, tplExt) {
			logger.Info("component", "template", "msg", "Parsing file", "file", p)
			if err := s.addTemplate(logger, p, defaultEnvironment); err != nil {
				logger.Error("component", "template", "err", err.Error())
				os.Exit(1)
			}
		}
		return err
	}
	tplScannerOverride := func(p string, info os.FileInfo, err error) error {
		if strings.HasSuffix(p, tplExt) {
			env := s.getEnvFromPath(p)
			logger.Info("component", "template", "msg", "Parsing ovveride", "environment", env, "file", p)
			if err := s.addTemplate(logger, p, env); err != nil {
				logger.Error("component", "template", "err", err.Error())
				os.Exit(1)
			}
		}
		return err
	}
	if err := filepath.Walk(dataDir, tplScannerDefault); err != nil {
		panic(err)
	}
	logger.Info("component", "template", "msg", "Parsing override files", "dir", path.Join(dataDir, envDir))
	if err := filepath.Walk(path.Join(dataDir, envDir), tplScannerOverride); err != nil {
		logger.Info("component", "template", "msg", "No overrides found")
	}
	logger.Debug("component", "template", "msg", "Parsing ended")
}
ParseTemplates travels the dataDir and loads in an internal structure
all the templates found.
package templates
import (
	"bufio"
	"bytes"
	"errors"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"
	"text/template"
	"github.com/thousandeyes/shoelaces/internal/log"
	"github.com/thousandeyes/shoelaces/internal/utils"
)
const defaultEnvironment = "default"
var varRegex = regexp.MustCompile(`{{\.(.*?)}}`)
var configNameRegex = regexp.MustCompile(`{{define\s+"(.*?)".*}}`)
type ShoelacesTemplates struct {
	envTemplates map[string]shoelacesTemplateEnvironment
	dataDir      string
	envDir       string
	tplExt       string
}
type shoelacesTemplateEnvironment struct {
	templateObj  *template.Template
	templateVars map[string][]string
}
type shoelacesTemplateInfo struct {
	name      string
	variables []string
}
func New() *ShoelacesTemplates {
	e := make(map[string]shoelacesTemplateEnvironment)
	e[defaultEnvironment] = shoelacesTemplateEnvironment{
		templateObj:  template.New(""),
		templateVars: make(map[string][]string),
	}
	return &ShoelacesTemplates{envTemplates: e}
}
func (s *ShoelacesTemplates) parseTemplateInfo(logger log.Logger, path string) shoelacesTemplateInfo {
	fh, err := os.Open(path)
	if err != nil {
		logger.Error("component", "template", "err", err.Error())
		os.Exit(1)
	}
	defer fh.Close()
	templateVars := make([]string, 0)
	scanner := bufio.NewScanner(fh)
	templateName := ""
	i := 0
	for scanner.Scan() {
		result := varRegex.FindAllStringSubmatch(scanner.Text(), -1)
		if varRegex.MatchString(scanner.Text()) {
			for _, v := range result {
				if !utils.StringInSlice(v[1], templateVars) {
					templateVars = append(templateVars, v[1])
				}
			}
		}
		if i == 0 {
			nameResult := configNameRegex.FindAllStringSubmatch(scanner.Text(), -1)
			templateName = nameResult[0][1]
		}
		i++
	}
	return shoelacesTemplateInfo{name: templateName, variables: templateVars}
}
func (s *ShoelacesTemplates) checkAddEnvironment(logger log.Logger, environment string) {
	if _, ok := s.envTemplates[environment]; !ok {
		c, e := s.envTemplates[defaultEnvironment].templateObj.Clone()
		if e != nil {
			logger.Error("component", "template", "msg", "Template for environment already executed", "environment", environment)
			os.Exit(1)
		}
		s.envTemplates[environment] = shoelacesTemplateEnvironment{
			templateObj:  c,
			templateVars: make(map[string][]string),
		}
	}
}
func (s *ShoelacesTemplates) addTemplate(logger log.Logger, path string, environment string) error {
	s.checkAddEnvironment(logger, environment)
	i := s.parseTemplateInfo(logger, path)
	_, err := s.envTemplates[environment].templateObj.ParseFiles(path)
	if err != nil {
		return err
	}
	s.envTemplates[environment].templateVars[i.name] = i.variables
	return nil
}
func (s *ShoelacesTemplates) getEnvFromPath(path string) string {
	envPath := filepath.Join(s.dataDir, s.envDir)
	if strings.HasPrefix(path, envPath) {
		return strings.Split(strings.TrimPrefix(path, envPath), "/")[1]
	}
	return defaultEnvironment
}