1 // Config: parse templates.yaml and expand templates
3 // Copyright (C) 2021 Simon Ruderich
5 // This program is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with this program. If not, see <http://www.gnu.org/licenses/>.
30 "ruderich.org/simon/safcm"
33 func LoadTemplates(group string, files map[string]*safcm.File,
34 host string, groups []string,
35 allHosts *Hosts, allGroups map[string][]string) error {
37 path := filepath.Join(group, "templates.yaml")
39 var templates []string
40 x, err := os.ReadFile(path)
42 if os.IsNotExist(err) {
47 err = yaml.UnmarshalStrict(x, &templates)
49 return fmt.Errorf("%s: failed to load: %v", path, err)
52 groupsMap := make(map[string]bool)
53 for _, x := range groups {
56 allHostsMap := make(map[string]bool)
57 for x := range allHosts.Map {
60 allGroupsMap := make(map[string]bool)
61 for x := range allGroups {
62 allGroupsMap[x] = true
65 for _, x := range templates {
68 return fmt.Errorf("%s: %q does not exist in files/",
71 if f.Mode.Type() != 0 /* regular file */ {
72 return fmt.Errorf("%s: %q is not a regular file",
76 tmplPath := filepath.Join(group, "files", x)
78 // Parse and expand template
80 tmpl, err := template.New(tmplPath).Parse(string(f.Data))
82 return fmt.Errorf("%s: invalid %v", path, err)
84 err = tmpl.Execute(&buf, &templateArgs{
87 allHosts: allHostsMap,
88 allGroups: allGroupsMap,
91 return fmt.Errorf("%s: %v", path, err)
99 // templateArgs is passed to .Execute() of the template.
100 type templateArgs struct {
102 groups map[string]bool
103 allHosts map[string]bool
104 allGroups map[string]bool
107 // TODO: extend data passed to template
109 func (t *templateArgs) IsHost(host string) bool {
110 // Don't permit invalid hosts to detect typos
111 if !t.allHosts[host] {
112 panic(fmt.Sprintf("host %q does not exist", host))
114 return t.host == host
116 func (t *templateArgs) InGroup(group string) bool {
117 // Don't permit invalid groups to detect typos; detected groups cannot
119 if group != GroupAll &&
120 !t.allGroups[group] &&
121 !t.allHosts[group] &&
122 !strings.HasPrefix(group, GroupDetectedPrefix) {
123 panic(fmt.Sprintf("group %q does not exist", group))
125 return t.groups[group]