Refactored generator and config
This commit is contained in:
parent
2a2185ded0
commit
926062124a
4 changed files with 108 additions and 103 deletions
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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)
|
||||
}
|
||||
outputs[path] = b.Bytes()
|
||||
}
|
||||
|
||||
return b.Bytes(), nil
|
||||
return outputs, nil
|
||||
}
|
||||
|
||||
func Generate(config *configurator.Config, params Params) ([]byte, error) {
|
||||
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),
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue