package main import ( "bytes" "encoding/json" "fmt" makeshift "git.towk2.me/towk/makeshift/pkg" "git.towk2.me/towk/makeshift/pkg/storage" "github.com/nikolalohinski/gonja/v2" "github.com/nikolalohinski/gonja/v2/exec" "github.com/rs/zerolog/log" ) type Jinja2 struct{} func (p *Jinja2) Name() string { return "jinja2" } func (p *Jinja2) Version() string { return "v0.0.1-alpha" } func (p *Jinja2) Description() string { return "Renders Jinja 2 templates" } func (p *Jinja2) Metadata() makeshift.Metadata { return makeshift.Metadata{ "author": map[string]any{ "name": "David J. Allen", "email": "davidallendj@gmail.com", "links": []string{ "https://github.com/davidallendj", "https://git.towk2.me/towk", }, }, } } func (p *Jinja2) Init() error { // nothing to initialize log.Debug().Str("plugin", p.Name()).Msg("jinja2.Init()") return nil } func (p *Jinja2) Run(store storage.KVStore, args []string) error { // render the files using Jinja 2 from args var ( mappings struct { Data map[string]any `json:"data"` } context *exec.Context template *exec.Template profiles any // makeshift.ProfileMap input any // []byte output bytes.Buffer err error ) log.Debug(). Str("plugin", p.Name()). Any("store", store). Strs("args", args). Int("arg_count", len(args)). Msg("(jinja2) Run()") profiles, err = store.Get("profiles") if err != nil { return fmt.Errorf("(jinja2) failed to get profiles: %v", err) } input, err = store.Get("file") if err != nil { return fmt.Errorf("(jinja2) failed to get input data: %v", err) } // get the templates provided as args to the plugin template, err = gonja.FromBytes(input.([]byte)) if err != nil { return fmt.Errorf("(jinja2) failed to get template from args: %v", err) } // get mappings from shared data (optional) shared, err := store.Get("shared") if err != nil { log.Warn().Err(err).Msg("(jinja2) could not retrieve shared data") } else { err = json.Unmarshal(shared.([]byte), &mappings) if err != nil { return fmt.Errorf("(jinja2) failed to unmarshal mappings from shared data: %v", err) } } var ps = make(map[string]any) for profileID, profile := range profiles.(makeshift.ProfileMap) { ps[profileID] = map[string]any{ "id": profile.ID, "description": profile.Description, "data": profile.Data, } } // inject profiles and plugin-specific mapping mappings.Data = map[string]any{ "makeshift": map[string]any{ "profiles": ps, "plugin": map[string]any{ "name": p.Name(), "version": p.Version(), "description": p.Description(), "metadata": p.Metadata(), }, }, } log.Debug().Any("mappings", mappings).Send() // use the provided data in the store to render templates // NOTE: this may be changed to specifically use "shared" data instead context = exec.NewContext(mappings.Data) if err = template.Execute(&output, context); err != nil { // Prints: Hello Bob! return fmt.Errorf("(jinja2) failed to render template: %v", err) } // write render templates to data store output store.Set("out", output.Bytes()) return nil } func (p *Jinja2) Cleanup() error { // nothing to clean up log.Debug().Str("plugin", p.Name()).Msg("(jinja2) Cleanup()") return nil } var Makeshift Jinja2