Skip to content

Commit 6a929ce

Browse files
committed
Add option to provide custom template command
1 parent 8acc762 commit 6a929ce

File tree

3 files changed

+86
-36
lines changed

3 files changed

+86
-36
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,23 @@ storage:
6262
{{ call .ReadFile "LICENSE" | call .Indent 12 }}
6363
```
6464

65+
### Custom template command
66+
Instead of using the native go template, you can also use any other command (for example [Helm](https://helm.sh)).
67+
To do that provide your custom command in the configuration option `flatcar.template_command`.
68+
It will get passed the hostname as the first argument and `Server` and `SSHKey` in YAML format on stdin.
69+
```
70+
hetzner:
71+
server:
72+
name: ...
73+
sshkey:
74+
publickey: ...
75+
```
76+
Example script to render a helm template with a values file based on the hostname:
77+
```sh
78+
#!/bin/sh
79+
cat - common.yaml "${1}.yaml" | yq -y . | helm template ignition -f -
80+
```
81+
6582
## Deployment procedure
6683
1. check whether vm with the name given as first parameter already exists
6784
2. create VM (if not already exists)

config.go

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@ type hcloudConfig struct {
1717
}
1818

1919
type flatcarConfig struct {
20-
InstallScript string `toml:"install_script"`
21-
Version string
22-
ConfigTemplate string `toml:"config_template"`
23-
TemplateStatic map[string]string `toml:"template_static"`
20+
InstallScript string `toml:"install_script"`
21+
Version string
22+
ConfigTemplate string `toml:"config_template"`
23+
TemplateStatic map[string]string `toml:"template_static"`
24+
TemplateCommand string `toml:"template_command"`
2425
}
2526

2627
type config struct {

main.go

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"log"
1212
"net"
1313
"os"
14+
"os/exec"
1415
"path/filepath"
1516
"strings"
1617
"text/template"
@@ -19,6 +20,7 @@ import (
1920
clconfig "github.com/flatcar-linux/container-linux-config-transpiler/config"
2021
"github.com/hetznercloud/hcloud-go/hcloud"
2122
"github.com/melbahja/goph"
23+
"gopkg.in/yaml.v3"
2224
)
2325

2426
var installScriptSource = "https://raw.githubusercontent.com/flatcar-linux/init/flatcar-master/bin/flatcar-install"
@@ -74,6 +76,15 @@ type templateData struct {
7476
Indent func(int, string) string
7577
}
7678

79+
type customTemplateDataHetzner struct {
80+
Server hcloud.Server
81+
SSHKey hcloud.SSHKey
82+
}
83+
84+
type customTemplateData struct {
85+
Hetzner customTemplateDataHetzner
86+
}
87+
7788
func main() {
7889
// TODO: cli parser...
7990
if len(os.Args) == 1 {
@@ -196,40 +207,61 @@ func main() {
196207
}
197208
}
198209

199-
// render container linux config template
200-
// TODO: support name replacement in template path
201-
ignitionTemplate := cfg.Flatcar.ConfigTemplate
202-
buffer := &bytes.Buffer{}
203-
tmpl, err := template.New(filepath.Base(ignitionTemplate)).ParseFiles(ignitionTemplate)
204-
if err != nil {
205-
log.Fatalf("error loading template: %v\n", err)
206-
}
207-
err = tmpl.Execute(buffer, templateData{
208-
Server: *server,
209-
SSHKey: *sshKey,
210-
Static: cfg.Flatcar.TemplateStatic,
211-
ReadFile: func(filename string) (string, error) {
212-
content, err := ioutil.ReadFile(filename)
213-
return string(content), err
214-
},
215-
Indent: func(indent int, input string) string {
216-
lines := strings.Split(input, "\n")
217-
output := make([]string, len(lines))
218-
indentString := strings.Repeat(" ", indent)
219-
for i := 0; i < len(output); i++ {
220-
output[i] = indentString + lines[i]
221-
}
222-
return strings.Join(output, "\n")
223-
},
224-
})
225-
if err != nil {
226-
log.Fatalf("error rendering template: %v\n", err)
227-
}
210+
var templateContent []byte
211+
if cfg.Flatcar.TemplateCommand == "" {
212+
ignitionTemplate := cfg.Flatcar.ConfigTemplate
213+
buffer := &bytes.Buffer{}
214+
tmpl, err := template.New(filepath.Base(ignitionTemplate)).ParseFiles(ignitionTemplate)
215+
if err != nil {
216+
log.Fatalf("error loading template: %v\n", err)
217+
}
218+
err = tmpl.Execute(buffer, templateData{
219+
Server: *server,
220+
SSHKey: *sshKey,
221+
Static: cfg.Flatcar.TemplateStatic,
222+
ReadFile: func(filename string) (string, error) {
223+
content, err := ioutil.ReadFile(filename)
224+
return string(content), err
225+
},
226+
Indent: func(indent int, input string) string {
227+
lines := strings.Split(input, "\n")
228+
output := make([]string, len(lines))
229+
indentString := strings.Repeat(" ", indent)
230+
for i := 0; i < len(output); i++ {
231+
output[i] = indentString + lines[i]
232+
}
233+
return strings.Join(output, "\n")
234+
},
235+
})
236+
if err != nil {
237+
log.Fatalf("error rendering template: %v\n", err)
238+
}
228239

229-
// transpile rendered container linux config template into ignition
230-
bufferContent, _ := ioutil.ReadAll(buffer)
240+
templateContent, _ = ioutil.ReadAll(buffer)
241+
} else {
242+
// marshal template data for passing it to the custom command
243+
templateData := customTemplateData{
244+
Hetzner: customTemplateDataHetzner{
245+
Server: *server,
246+
SSHKey: *sshKey,
247+
},
248+
}
249+
templateDataYAML, err := yaml.Marshal(templateData)
250+
if err != nil {
251+
log.Fatalf("error marshaling hcloud data to yaml: %v\n", err)
252+
}
253+
254+
// execute custom template command
255+
tmplCmd := exec.Command(cfg.Flatcar.TemplateCommand, server.Name)
256+
tmplCmd.Stdin = bytes.NewReader(templateDataYAML)
257+
templateContent, err = tmplCmd.Output()
258+
if err != nil {
259+
log.Println(string(err.(*exec.ExitError).Stderr))
260+
log.Fatalf("error running template command: %v\n", err)
261+
}
262+
}
231263

232-
renderedPath, err := transpileConfig(bufferContent)
264+
renderedPath, err := transpileConfig(templateContent)
233265
if err != nil {
234266
log.Fatalf("error transpiling config: %v\n", err)
235267
}

0 commit comments

Comments
 (0)