Skip to content

Commit 5ae91e8

Browse files
authored
Merge pull request Cloud-Foundations#168 from rgooch/master
filegen-server: add LookupGeneratorVariable and Contains template functions.
2 parents 147d356 + 6248d12 commit 5ae91e8

File tree

4 files changed

+81
-24
lines changed

4 files changed

+81
-24
lines changed

cmd/filegen-server/README.md

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,13 @@ The configuration file contains zero or more lines of the form:
7777
use to generate data for the specified *pathname*. The following generator types
7878
are supported:
7979

80-
- **DynamicTemplateFile** pathname *filename*: the contents of *filename* are
81-
used as a template to generate the file data. If the file contains sections of
82-
the form `{{.MyVar}}` then the value of the `MyVar` variable from the MDB for
83-
the host are used to replace the section. If *filename* changes (replaced with
84-
a different inode), then the data are regenerated and distributed to all
85-
machines
80+
- **DynamicTemplateFile** pathname *filename* [*variablesFile*]: the contents of
81+
*filename* are used as a template to generate the file data. If the file
82+
contains sections of the form `{{.MyVar}}` then the value of the `MyVar`
83+
variable from the MDB for the host are used to replace the section. If
84+
*filename* changes (replaced with a different inode), then the data are
85+
regenerated and distributed to all machines. If specified, optional key:value
86+
pairs are loaded from the *variablesFile* in JSON format
8687

8788
- **File** pathname *filename*: the contents of *filename* are used to provide
8889
the file data. If *filename* changes (replaced with a different inode), then
@@ -108,10 +109,12 @@ are supported:
108109
be written to the standard output in JSON format, stored in the `Data` and
109110
`SecondsValid` fields.
110111

111-
- **StaticTemplateFile** pathname *filename*: the contents of *filename* are
112-
used as a template to generate the file data. If the file contains sections of
113-
the form `{{.MyVar}}` then the value of the `MyVar` variable from the MDB for
114-
the host are used to replace the section
112+
- **StaticTemplateFile** pathname *filename* [*variablesFile*]: the contents of
113+
*filename* are used as a template to generate the file data. If the file
114+
contains sections of the form `{{.MyVar}}` then the value of the `MyVar`
115+
variable from the MDB for the host are used to replace the section. If
116+
specified, optional key:value pairs are loaded from the *variablesFile* in
117+
JSON format
115118

116119
- **URL** pathname *url*: a HTTP POST request will be sent to the URL specified
117120
by *url* containing JSON-encoded MDB data in the request body. The *pathname*
@@ -222,8 +225,10 @@ These template files use the go [text/template](https://pkg.go.dev/text/template
222225
standard package. Template functions can be defined and added to the funcMap to process
223226
MDB fields in the template. The following template functions are available:
224227

228+
* `Contains`: returns `true` if the second string is contained in the first
225229
* `GetSplitPart`: splits a string based on the given separator, then returns a
226-
substring given the index of the split array
230+
substring given the index of the split array
231+
* `LookupGeneratorVariable`: lookup value in the generator variables map
227232
* `ToLower`: returns the lowercase version of a string
228233
* `ToUpper`: returns the uppercase version of a string
229234

lib/filegen/api.go

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,8 +128,21 @@ func (m *Manager) RegisterProgrammeForPath(pathname, programmePath string) {
128128
// The template file syntax is defined by the text/template standard package.
129129
func (m *Manager) RegisterTemplateFileForPath(pathname string,
130130
templateFile string, watchForUpdates bool) error {
131-
return m.registerTemplateFileForPath(pathname, templateFile,
132-
watchForUpdates)
131+
return m.registerTemplateFileForPath(pathname, TemplateFileConfig{
132+
TemplateFile: templateFile,
133+
WatchForUpdates: watchForUpdates,
134+
})
135+
}
136+
137+
// RegisterTemplateFileForPathWithConfig registers a template file for a
138+
// specific pathname.
139+
// The template file is used to generate the data, modified by the machine data.
140+
// If the template file changes and WatchForUpdates is true, the template file
141+
// is re-read and the data are regenerated.
142+
// The template file syntax is defined by the text/template standard package.
143+
func (m *Manager) RegisterTemplateFileForPathWithConfig(pathname string,
144+
config TemplateFileConfig) error {
145+
return m.registerTemplateFileForPath(pathname, config)
133146
}
134147

135148
// RegisterUrlForPath registers a URL where a HTTP POST request may be sent to
@@ -149,3 +162,9 @@ func (m *Manager) RegisterUrlForPath(pathname, URL string) {
149162
func (m *Manager) WriteHtml(writer io.Writer) {
150163
m.writeHtml(writer)
151164
}
165+
166+
type TemplateFileConfig struct {
167+
TemplateFile string
168+
VariablesFile string
169+
WatchForUpdates bool
170+
}

lib/filegen/template.go

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,35 +12,47 @@ import (
1212

1313
"github.com/Cloud-Foundations/Dominator/lib/fsutil"
1414
"github.com/Cloud-Foundations/Dominator/lib/hash"
15+
"github.com/Cloud-Foundations/Dominator/lib/json"
1516
"github.com/Cloud-Foundations/Dominator/lib/log"
1617
"github.com/Cloud-Foundations/Dominator/lib/mdb"
1718
"github.com/Cloud-Foundations/Dominator/lib/objectserver/memory"
1819
)
1920

2021
var funcMap = template.FuncMap{
22+
"Contains": strings.Contains,
2123
"GetSplitPart": getSplitPart,
22-
"ToLower": strings.ToLower,
23-
"ToUpper": strings.ToUpper,
24+
"ToLower": strings.ToLower,
25+
"ToUpper": strings.ToUpper,
2426
}
2527

2628
type templateGenerator struct {
2729
objectServer *memory.ObjectServer
2830
logger log.Logger
2931
template *template.Template
32+
variables map[string]string
3033
notifierChannel chan<- string
3134
}
3235

3336
func (m *Manager) registerTemplateFileForPath(pathname string,
34-
templateFile string, watchForUpdates bool) error {
37+
config TemplateFileConfig) error {
3538
tgen := &templateGenerator{
3639
objectServer: m.objectServer,
3740
logger: m.logger}
3841
tgen.notifierChannel = m.registerHashGeneratorForPath(pathname, tgen)
39-
if watchForUpdates {
40-
readCloserChannel := fsutil.WatchFile(templateFile, m.logger)
42+
if config.VariablesFile != "" {
43+
// TODO(rgooch): consider making this watch for updates.
44+
variables := make(map[string]string)
45+
err := json.ReadFromFile(config.VariablesFile, &variables)
46+
if err != nil {
47+
return err
48+
}
49+
tgen.variables = variables
50+
}
51+
if config.WatchForUpdates {
52+
readCloserChannel := fsutil.WatchFile(config.TemplateFile, m.logger)
4153
go tgen.handleReadClosers(readCloserChannel)
4254
} else {
43-
file, err := os.Open(templateFile)
55+
file, err := os.Open(config.TemplateFile)
4456
if err != nil {
4557
return err
4658
}
@@ -90,11 +102,19 @@ func (tgen *templateGenerator) handleReadCloser(
90102
if err != nil {
91103
return err
92104
}
93-
tmpl, err := template.New("generatorTemplate").Funcs(funcMap).Parse(string(data))
105+
tmpl := template.New("generatorTemplate").Funcs(funcMap)
106+
if tgen.variables != nil {
107+
tmpl.Funcs(template.FuncMap{"LookupGeneratorVariable": tgen.lookup})
108+
}
109+
tmpl, err = tmpl.Parse(string(data))
94110
if err != nil {
95111
return err
96112
}
97113
tgen.template = tmpl
98114
tgen.notifierChannel <- ""
99115
return nil
100116
}
117+
118+
func (tgen *templateGenerator) lookup(s string) string {
119+
return tgen.variables[s]
120+
}

lib/filegen/util/load.go

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ type configType struct {
1818
}
1919

2020
var configs = map[string]configType{
21-
"DynamicTemplateFile": {1, 1, dynamicTemplateFileGenerator},
21+
"DynamicTemplateFile": {1, 2, dynamicTemplateFileGenerator},
2222
"File": {1, 1, fileGenerator},
2323
"MdbFieldDirectory": {2, 3, mdbFieldDirectoryGenerator},
2424
"MDB": {0, 0, mdbGenerator},
2525
"Programme": {1, 1, programmeGenerator},
26-
"StaticTemplateFile": {1, 1, staticTemplateFileGenerator},
26+
"StaticTemplateFile": {1, 2, staticTemplateFileGenerator},
2727
"URL": {1, 1, urlGenerator},
2828
}
2929

@@ -58,7 +58,14 @@ func loadConfiguration(manager *filegen.Manager, filename string) error {
5858

5959
func dynamicTemplateFileGenerator(manager *filegen.Manager, pathname string,
6060
params []string) error {
61-
return manager.RegisterTemplateFileForPath(pathname, params[0], true)
61+
config := filegen.TemplateFileConfig{
62+
TemplateFile: params[0],
63+
WatchForUpdates: true,
64+
}
65+
if len(params) > 1 {
66+
config.VariablesFile = params[1]
67+
}
68+
return manager.RegisterTemplateFileForPathWithConfig(pathname, config)
6269
}
6370

6471
func fileGenerator(manager *filegen.Manager, pathname string,
@@ -98,7 +105,13 @@ func programmeGenerator(manager *filegen.Manager, pathname string,
98105

99106
func staticTemplateFileGenerator(manager *filegen.Manager, pathname string,
100107
params []string) error {
101-
return manager.RegisterTemplateFileForPath(pathname, params[0], false)
108+
config := filegen.TemplateFileConfig{
109+
TemplateFile: params[0],
110+
}
111+
if len(params) > 1 {
112+
config.VariablesFile = params[1]
113+
}
114+
return manager.RegisterTemplateFileForPathWithConfig(pathname, config)
102115
}
103116

104117
func urlGenerator(manager *filegen.Manager, pathname string,

0 commit comments

Comments
 (0)