Refactored generator and config

This commit is contained in:
David Allen 2024-06-26 10:14:40 -06:00
parent 2a2185ded0
commit 926062124a
No known key found for this signature in database
GPG key ID: 717C593FF60A2ACC
4 changed files with 108 additions and 103 deletions

View file

@ -10,6 +10,7 @@ import (
"path/filepath"
"github.com/OpenCHAMI/configurator/internal/generator"
"github.com/OpenCHAMI/configurator/internal/util"
"github.com/spf13/cobra"
)
@ -70,32 +71,45 @@ var generateCmd = &cobra.Command{
Target: target,
Verbose: verbose,
}
output, err := generator.Generate(&config, params)
outputBytes, err := generator.Generate(&config, params)
if err != nil {
fmt.Printf("failed to generate config: %v\n", err)
os.Exit(1)
}
// write config output if no specific targetPath is set
outputMap := util.ConvertMapOutput(outputBytes)
// b, err := json.Marshal(outputMap)
// if err != nil {
// fmt.Printf("failed to marshal output: %v\n", err)
// os.Exit(1)
// }
if outputPath == "" {
// write only to stdout
fmt.Printf("%s\n", string(output))
} else if outputPath != "" && targetCount == 1 {
// write only to stdout by default
for _, contents := range outputMap {
fmt.Printf("%s\n", string(contents))
}
} else if outputPath != "" && targetCount == 1 && len(outputMap) == 1 {
// write just a single file using template name
err := os.WriteFile(outputPath, output, 0o644)
for _, contents := range outputBytes {
// FIXME: fix output paths to not overwrite each other with multiple templates
err := os.WriteFile(outputPath, contents, 0o644)
if err != nil {
fmt.Printf("failed to write config to file: %v", err)
os.Exit(1)
}
}
} else if outputPath != "" && targetCount > 1 {
// write multiple files in directory using template name
err := os.WriteFile(fmt.Sprintf("%s/%s.%s", filepath.Clean(outputPath), target, ".conf"), output, 0o644)
for _, contents := range outputBytes {
// FIXME: fix output paths to not overwrite each other with multiple templates
err := os.WriteFile(fmt.Sprintf("%s/%s.%s", filepath.Clean(outputPath), target, ".conf"), contents, 0o644)
if err != nil {
fmt.Printf("failed to write config to file: %v", err)
os.Exit(1)
}
}
}
}
},
}

View file

@ -10,6 +10,12 @@ import (
type Options struct{}
type Target struct {
Templates []string `yaml:"templates,omitempty"`
FilePaths []string `yaml:"files,omitempty"`
RunTargets []string `yaml:"targets,omitempty"`
}
type Jwks struct {
Uri string `yaml:"uri"`
Retries int `yaml:"retries"`
@ -26,7 +32,7 @@ type Config struct {
Server Server `yaml:"server"`
SmdClient SmdClient `yaml:"smd"`
AccessToken string `yaml:"access-token"`
TemplatePaths map[string]string `yaml:"templates"`
Targets map[string]Target `yaml:"targets"`
PluginDirs []string `yaml:"plugins"`
Options Options `yaml:"options"`
}
@ -38,13 +44,21 @@ func NewConfig() Config {
Host: "http://127.0.0.1",
Port: 27779,
},
TemplatePaths: map[string]string{
"dnsmasq": "templates/dnsmasq.jinja",
"syslog": "templates/syslog.jinja",
"ansible": "templates/ansible.jinja",
"powerman": "templates/powerman.jinja",
"conman": "templates/conman.jinja",
Targets: map[string]Target{
"dnsmasq": Target{
Templates: []string{},
},
"conman": Target{
Templates: []string{},
},
"warewulf": Target{
Templates: []string{
"templates/warewulf/defaults/node.jinja",
"templates/warewulf/defaults/provision.jinja",
},
},
},
PluginDirs: []string{},
Server: Server{
Host: "127.0.0.1",

View file

@ -1,56 +0,0 @@
version: "0.0.1"
server:
host: "127.0.0.1"
port: 3333
callback: "/oidc/callback"
providers:
facebook: "http://facebook.com"
forgejo: "http://git.towk.local:3000"
gitlab: "https://gitlab.newmexicoconsortium.org"
github: "https://github.com"
authentication:
clients:
- id: "7527e7b4-c96a-4df0-8fc5-00fde18bb65d"
secret: "gto_cc5uvpb5lsdczkwnbarvwmbpv5kcjwg7nhbc75zt65yrfh2ldenq"
name: "forgejo"
issuer: "http://git.towk.local:3000"
scope:
- "openid"
- "profile"
- "read"
- "email"
redirect-uris:
- "http://127.0.0.1:3333/oidc/callback"
- id: "7c0fab1153674a258a705976fcb9468350df3addd91de4ec622fc9ed24bfbcdd"
secret: "a9a8bc55b0cd99236756093adc00ab17855fa507ce106b8038e7f9390ef2ad99"
name: "gitlab"
issuer: "http://gitlab.newmexicoconsortium.org"
scope:
- "openid"
- "profile"
- "email"
redirect-uris:
- "http://127.0.0.1:3333/oidc/callback"
flows:
authorization-code:
state: ""
client-credentials:
authorization:
urls:
#identities: http://127.0.0.1:4434/admin/identities
trusted-issuers: http://127.0.0.1:4445/admin/trust/grants/jwt-bearer/issuers
login: http://127.0.0.1:4433/self-service/login/api
clients: http://127.0.0.1:4445/admin/clients
authorize: http://127.0.0.1:4444/oauth2/auth
register: http://127.0.0.1:4444/oauth2/register
token: http://127.0.0.1:4444/oauth2/token
options:
decode-id-token: true
decode-access-token: true
run-once: true
open-browser: false

View file

@ -5,6 +5,7 @@ import (
"fmt"
"maps"
"os"
"path/filepath"
"plugin"
configurator "github.com/OpenCHAMI/configurator/internal"
@ -15,10 +16,10 @@ import (
)
type Mappings = map[string]any
type Files = map[string][]byte
type Generator interface {
GetName() string
GetGroups() []string
Generate(config *configurator.Config, opts ...util.Option) ([]byte, error)
Generate(config *configurator.Config, opts ...util.Option) (Files, error)
}
type Params struct {
@ -34,14 +35,16 @@ func LoadPlugin(path string) (Generator, error) {
return nil, fmt.Errorf("failed to load plugin: %v", err)
}
// load the "Generator" symbol from plugin
symbol, err := p.Lookup("Generator")
if err != nil {
return nil, fmt.Errorf("failed to look up symbol: %v", err)
return nil, fmt.Errorf("failed to look up symbol at path '%s': %v", path, err)
}
// assert that the plugin loaded has a valid generator
gen, ok := symbol.(Generator)
if !ok {
return nil, fmt.Errorf("failed to load the correct symbol type")
return nil, fmt.Errorf("failed to load the correct symbol type at path '%s'", path)
}
return gen, nil
}
@ -90,10 +93,10 @@ func LoadPlugins(dirpath string, opts ...util.Option) (map[string]Generator, err
return gens, nil
}
func WithTemplate(_template string) util.Option {
func WithTarget(target string) util.Option {
return func(p util.Params) {
if p != nil {
p["template"] = _template
p["target"] = target
}
}
}
@ -123,6 +126,10 @@ func GetClient(params util.Params) *configurator.SmdClient {
return util.Get[configurator.SmdClient](params, "client")
}
func GetTarget(config *configurator.Config, key string) configurator.Target {
return config.Targets[key]
}
func GetParams(opts ...util.Option) util.Params {
params := util.Params{}
for _, opt := range opts {
@ -131,9 +138,13 @@ func GetParams(opts ...util.Option) util.Params {
return params
}
func ApplyTemplate(path string, mappings map[string]any) ([]byte, error) {
data := exec.NewContext(mappings)
func ApplyTemplates(mappings map[string]any, paths ...string) (Files, error) {
var (
data = exec.NewContext(mappings)
outputs = Files{}
)
for _, path := range paths {
// load jinja template from file
t, err := gonja.FromFile(path)
if err != nil {
@ -145,11 +156,33 @@ func ApplyTemplate(path string, mappings map[string]any) ([]byte, error) {
if err = t.Execute(&b, data); err != nil {
return nil, fmt.Errorf("failed to execute: %v", err)
}
return b.Bytes(), nil
outputs[path] = b.Bytes()
}
func Generate(config *configurator.Config, params Params) ([]byte, error) {
return outputs, nil
}
func LoadFiles(paths ...string) (Files, error) {
var outputs = Files{}
for _, path := range paths {
expandedPaths, err := filepath.Glob(path)
if err != nil {
return nil, fmt.Errorf("failed to expand path: %v", err)
}
for _, expandedPath := range expandedPaths {
b, err := os.ReadFile(expandedPath)
if err != nil {
return nil, fmt.Errorf("failed to read file: %v", err)
}
outputs[path] = b
}
}
return outputs, nil
}
func Generate(config *configurator.Config, params Params) (Files, error) {
// load generator plugins to generate configs or to print
var (
generators = make(map[string]Generator)
@ -194,7 +227,7 @@ func Generate(config *configurator.Config, params Params) ([]byte, error) {
}
return gen.Generate(
config,
WithTemplate(gen.GetName()),
WithTarget(gen.GetName()),
WithClient(client),
)
}