From 50e6b5309182671f844a85e2d4f3f5641286576c Mon Sep 17 00:00:00 2001 From: David Allen Date: Mon, 4 Aug 2025 22:32:41 -0600 Subject: [PATCH] refactor: more implementation to refactor and deleted files --- examples/plugin/test.go | 23 ---- go.mod | 21 +-- go.sum | 86 ++---------- pkg/generator/conman.go | 56 -------- pkg/generator/coredhcp.go | 26 ---- pkg/generator/dhcpd.go | 64 --------- pkg/generator/dnsmasq.go | 71 ---------- pkg/generator/example.go | 31 ----- pkg/generator/generator.go | 264 ------------------------------------- pkg/generator/hostfile.go | 26 ---- pkg/generator/params.go | 43 ------ pkg/generator/powerman.go | 26 ---- pkg/generator/syslog.go | 26 ---- pkg/generator/templates.go | 98 -------------- pkg/generator/warewulf.go | 78 ----------- pkg/service/profile.go | 81 +++++++++--- pkg/service/service.go | 9 +- 17 files changed, 84 insertions(+), 945 deletions(-) delete mode 100644 examples/plugin/test.go delete mode 100644 pkg/generator/conman.go delete mode 100644 pkg/generator/coredhcp.go delete mode 100644 pkg/generator/dhcpd.go delete mode 100644 pkg/generator/dnsmasq.go delete mode 100644 pkg/generator/example.go delete mode 100644 pkg/generator/generator.go delete mode 100644 pkg/generator/hostfile.go delete mode 100644 pkg/generator/params.go delete mode 100644 pkg/generator/powerman.go delete mode 100644 pkg/generator/syslog.go delete mode 100644 pkg/generator/templates.go delete mode 100644 pkg/generator/warewulf.go diff --git a/examples/plugin/test.go b/examples/plugin/test.go deleted file mode 100644 index 6289e1c..0000000 --- a/examples/plugin/test.go +++ /dev/null @@ -1,23 +0,0 @@ -package main - -import ( - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/generator" -) - -type TestGenerator struct{} - -func (g *TestGenerator) GetName() string { return "test" } -func (g *TestGenerator) GetVersion() string { return "v1.0.0" } -func (g *TestGenerator) GetDescription() string { - return "This is a plugin creating for running tests." -} -func (g *TestGenerator) Generate(config *config.Config, params generator.Params) (generator.FileMap, error) { - return generator.ApplyTemplates(generator.Mappings{ - "plugin_name": g.GetName(), - "plugin_version": g.GetVersion(), - "plugin_description": g.GetDescription(), - }, params.Templates) -} - -var Generator TestGenerator diff --git a/go.mod b/go.mod index dcb6e87..97ef719 100644 --- a/go.mod +++ b/go.mod @@ -4,39 +4,28 @@ go 1.21.5 require ( github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18 + github.com/go-chi/chi v1.5.5 github.com/go-chi/chi/v5 v5.1.0 github.com/lestrrat-go/jwx/v2 v2.1.1 - github.com/nikolalohinski/gonja/v2 v2.2.0 - github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700 - github.com/openchami/chi-middleware/log v0.0.0-20240812224658-b16b83c70700 - github.com/rodaine/table v1.2.0 - github.com/rs/zerolog v1.33.0 github.com/spf13/cobra v1.8.0 + github.com/tidwall/sjson v1.2.5 golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 - gopkg.in/yaml.v2 v2.4.0 ) require ( github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect github.com/goccy/go-json v0.10.3 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kr/text v0.1.0 // indirect github.com/lestrrat-go/blackmagic v1.0.2 // indirect github.com/lestrrat-go/httpcc v1.0.1 // indirect github.com/lestrrat-go/httprc v1.0.6 // indirect github.com/lestrrat-go/iter v1.0.2 // indirect github.com/lestrrat-go/option v1.0.1 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pkg/errors v0.9.1 // indirect github.com/segmentio/asm v1.2.0 // indirect - github.com/sirupsen/logrus v1.9.3 // indirect github.com/spf13/pflag v1.0.5 // indirect + github.com/tidwall/gjson v1.14.2 // indirect + github.com/tidwall/match v1.1.1 // indirect + github.com/tidwall/pretty v1.2.0 // indirect golang.org/x/crypto v0.25.0 // indirect golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect ) diff --git a/go.sum b/go.sum index 8452dee..b8090b3 100644 --- a/go.sum +++ b/go.sum @@ -1,39 +1,19 @@ -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18 h1:oBPtXp9RVm9lk5zTmDLf+Vh21yDHpulBxUqGJQjwQCk= github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18/go.mod h1:ggNHWgLfW/WRXcE8ZZC4S7UwHif16HVmyowOCWdNSN8= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg= github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= +github.com/go-chi/chi v1.5.5 h1:vOB/HbEMt9QqBqErz07QehcOKHaWFtuj87tTDVz2qXE= +github.com/go-chi/chi v1.5.5/go.mod h1:C9JqLr3tIYjDOZpzn+BCuxY8z8vmca43EeMgyZt7irw= github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw= github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= -github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE= -github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k= github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU= github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE= @@ -46,81 +26,35 @@ github.com/lestrrat-go/jwx/v2 v2.1.1 h1:Y2ltVl8J6izLYFs54BVcpXLv5msSW4o8eXwnzZLI github.com/lestrrat-go/jwx/v2 v2.1.1/go.mod h1:4LvZg7oxu6Q5VJwn7Mk/UwooNRnTHUpXBj2C4j3HNx0= github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU= github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I= -github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= -github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/nikolalohinski/gonja/v2 v2.2.0 h1:tAs3BDHNjvPj48F2BL5t7iVhN32HhgeldAl3EmdsLh8= -github.com/nikolalohinski/gonja/v2 v2.2.0/go.mod h1:l9DuWJvT/BddBr2SsmEimESD6msSqRw7u5HzI2Um+sc= -github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU= -github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM= -github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc= -github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ= -github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700 h1:XADGipD2FZ9swuFUqeL7h63j3voiq9qA7P0aKsqgZKg= -github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700/go.mod h1:kswb9kU5cZAFRAvf1dAUJRWbQyjDEb0qkxW4ncDdEXg= -github.com/openchami/chi-middleware/log v0.0.0-20240812224658-b16b83c70700 h1:Gzt5f6RK39CHvY3SJudzBb/RK4tVh/S3CpJ0eQlbNdg= -github.com/openchami/chi-middleware/log v0.0.0-20240812224658-b16b83c70700/go.mod h1:UuXvr2loD4MtvZeKr57W0WpBs+gm0KM1kdtcXrE8M6s= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rodaine/table v1.2.0 h1:38HEnwK4mKSHQJIkavVj+bst1TEY7j9zhLMWu4QJrMA= -github.com/rodaine/table v1.2.0/go.mod h1:wejb/q/Yd4T/SVmBSRMr7GCq3KlcZp3gyNYdLSBhkaE= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8= -github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= -github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= -github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= +github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= +github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= +github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= -golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= -golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= -golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= -golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/pkg/generator/conman.go b/pkg/generator/conman.go deleted file mode 100644 index be8e882..0000000 --- a/pkg/generator/conman.go +++ /dev/null @@ -1,56 +0,0 @@ -package generator - -import ( - "fmt" - - configurator "git.towk2.me/towk/configurator/pkg" - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type Conman struct{} - -func (g *Conman) GetName() string { - return "conman" -} - -func (g *Conman) GetVersion() string { - return util.GitCommit() -} - -func (g *Conman) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *Conman) Generate(config *config.Config, params Params) (FileMap, error) { - var ( - smdClient = client.NewSmdClient(params.ClientOpts...) - eps = []configurator.RedfishEndpoint{} - err error = nil - consoles = "" - ) - - // fetch required data from SMD to create config - eps, err = smdClient.FetchRedfishEndpoints(params.Verbose) - if err != nil { - return nil, fmt.Errorf("failed to fetch redfish endpoints with client: %v", err) - } - - // format output to write to config file - consoles = "# ========== DYNAMICALLY GENERATED BY OPENCHAMI CONFIGURATOR ==========\n" - for _, ep := range eps { - consoles += fmt.Sprintf("CONSOLE name=%s dev=ipmi:%s-bmc ipmiopts=U:%s,P:%s,W:solpayloadsize\n", ep.Name, ep.Name, ep.User, ep.Password) - } - consoles += "# =====================================================================" - - // apply template substitutions and return output as byte array - return ApplyTemplates(Mappings{ - "plugin_name": g.GetName(), - "plugin_version": g.GetVersion(), - "plugin_description": g.GetDescription(), - "server_opts": "", - "global_opts": "", - "consoles": consoles, - }, params.Templates) -} diff --git a/pkg/generator/coredhcp.go b/pkg/generator/coredhcp.go deleted file mode 100644 index ccc79cd..0000000 --- a/pkg/generator/coredhcp.go +++ /dev/null @@ -1,26 +0,0 @@ -package generator - -import ( - "fmt" - - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type CoreDhcp struct{} - -func (g *CoreDhcp) GetName() string { - return "coredhcp" -} - -func (g *CoreDhcp) GetVersion() string { - return util.GitCommit() -} - -func (g *CoreDhcp) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s' to generate config files. (WIP)", g.GetName()) -} - -func (g *CoreDhcp) Generate(config *config.Config, params Params) (FileMap, error) { - return nil, fmt.Errorf("plugin does not implement generation function") -} diff --git a/pkg/generator/dhcpd.go b/pkg/generator/dhcpd.go deleted file mode 100644 index 75a41bb..0000000 --- a/pkg/generator/dhcpd.go +++ /dev/null @@ -1,64 +0,0 @@ -package generator - -import ( - "fmt" - - configurator "git.towk2.me/towk/configurator/pkg" - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type DHCPd struct{} - -func (g *DHCPd) GetName() string { - return "dhcpd" -} - -func (g *DHCPd) GetVersion() string { - return util.GitCommit() -} - -func (g *DHCPd) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *DHCPd) Generate(config *config.Config, params Params) (FileMap, error) { - var ( - smdClient = client.NewSmdClient(params.ClientOpts...) - eths = []configurator.EthernetInterface{} - computeNodes = "" - err error = nil - ) - - // - eths, err = smdClient.FetchEthernetInterfaces(params.Verbose) - if err != nil { - return nil, fmt.Errorf("failed to fetch ethernet interfaces with client: %w", err) - } - - // check if we have the required params first - if eths == nil { - return nil, fmt.Errorf("invalid ethernet interfaces (variable is nil)") - } - if len(eths) <= 0 { - return nil, fmt.Errorf("no ethernet interfaces found") - } - - // format output to write to config file - computeNodes = "# ========== DYNAMICALLY GENERATED BY OPENCHAMI CONFIGURATOR ==========\n" - for _, eth := range eths { - if len(eth.IpAddresses) == 0 { - continue - } - computeNodes += fmt.Sprintf("host %s { hardware ethernet %s; fixed-address %s} ", eth.ComponentId, eth.MacAddress, eth.IpAddresses[0]) - } - computeNodes += "# =====================================================================" - return ApplyTemplates(Mappings{ - "plugin_name": g.GetName(), - "plugin_version": g.GetVersion(), - "plugin_description": g.GetDescription(), - "compute_nodes": computeNodes, - "node_entries": "", - }, params.Templates) -} diff --git a/pkg/generator/dnsmasq.go b/pkg/generator/dnsmasq.go deleted file mode 100644 index 16ea6c9..0000000 --- a/pkg/generator/dnsmasq.go +++ /dev/null @@ -1,71 +0,0 @@ -package generator - -import ( - "fmt" - - configurator "git.towk2.me/towk/configurator/pkg" - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type DNSMasq struct{} - -func (g *DNSMasq) GetName() string { - return "dnsmasq" -} - -func (g *DNSMasq) GetVersion() string { - return util.GitCommit() -} - -func (g *DNSMasq) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *DNSMasq) Generate(config *config.Config, params Params) (FileMap, error) { - // make sure we have a valid config first - if config == nil { - return nil, fmt.Errorf("invalid config (config is nil)") - } - - // set all the defaults for variables - var ( - smdClient = client.NewSmdClient(params.ClientOpts...) - eths = []configurator.EthernetInterface{} - err error = nil - ) - - // if we have a client, try making the request for the ethernet interfaces - eths, err = smdClient.FetchEthernetInterfaces(params.Verbose) - if err != nil { - return nil, fmt.Errorf("failed to fetch ethernet interfaces with client: %v", err) - } - - // check if we have the required params first - if eths == nil { - return nil, fmt.Errorf("invalid ethernet interfaces (variable is nil)") - } - if len(eths) <= 0 { - return nil, fmt.Errorf("no ethernet interfaces found") - } - - // format output to write to config file - output := "# ========== DYNAMICALLY GENERATED BY OPENCHAMI CONFIGURATOR ==========\n" - for _, eth := range eths { - if eth.Type == "NodeBMC" { - output += "dhcp-host=" + eth.MacAddress + "," + eth.ComponentId + "," + eth.IpAddresses[0].IpAddress + "\n" - } else { - output += "dhcp-host=" + eth.MacAddress + "," + eth.ComponentId + "," + eth.IpAddresses[0].IpAddress + "\n" - } - } - output += "# =====================================================================" - - // apply template substitutions and return output as byte array - return ApplyTemplates(Mappings{ - "plugin_name": g.GetName(), - "plugin_version": g.GetVersion(), - "plugin_description": g.GetDescription(), - "dhcp_hosts": output, - }, params.Templates) -} diff --git a/pkg/generator/example.go b/pkg/generator/example.go deleted file mode 100644 index 12091ba..0000000 --- a/pkg/generator/example.go +++ /dev/null @@ -1,31 +0,0 @@ -package generator - -import ( - "fmt" - - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type Example struct { - Message string -} - -func (g *Example) GetName() string { - return "example" -} - -func (g *Example) GetVersion() string { - return util.GitCommit() -} - -func (g *Example) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *Example) Generate(config *config.Config, params Params) (FileMap, error) { - g.Message = ` - This is an example generator plugin. See the file in 'internal/generator/plugins/example/example.go' on - information about constructing plugins and plugin requirements.` - return FileMap{"example": []byte(g.Message)}, nil -} diff --git a/pkg/generator/generator.go b/pkg/generator/generator.go deleted file mode 100644 index 3667130..0000000 --- a/pkg/generator/generator.go +++ /dev/null @@ -1,264 +0,0 @@ -package generator - -import ( - "fmt" - "io/fs" - "os" - "path/filepath" - "plugin" - - configurator "git.towk2.me/towk/configurator/pkg" - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" - "github.com/rs/zerolog/log" -) - -type ( - Mappings map[string]any - FileMap map[string][]byte - FileList [][]byte - - // Generator interface used to define how files are created. Plugins can - // be created entirely independent of the main driver program. - Generator interface { - GetName() string - GetVersion() string - GetDescription() string - Generate(config *config.Config, params Params) (FileMap, error) - } -) - -var DefaultGenerators = createDefaultGenerators() - -func createDefaultGenerators() map[string]Generator { - var ( - generatorMap = map[string]Generator{} - generators = []Generator{ - &Conman{}, &DHCPd{}, &DNSMasq{}, &Warewulf{}, &Example{}, &CoreDhcp{}, - } - ) - for _, g := range generators { - generatorMap[g.GetName()] = g - } - return generatorMap -} - -// Converts the file outputs from map[string][]byte to map[string]string. -func ConvertContentsToString(f FileMap) map[string]string { - n := make(map[string]string, len(f)) - for k, v := range f { - n[k] = string(v) - } - return n -} - -// Loads files without applying any Jinja 2 templating. -func LoadFiles(paths ...string) (FileMap, error) { - var outputs = FileMap{} - for _, path := range paths { - expandedPaths, err := filepath.Glob(path) - if err != nil { - return nil, fmt.Errorf("failed to glob path: %w", err) - } - for _, expandedPath := range expandedPaths { - info, err := os.Stat(expandedPath) - if err != nil { - fmt.Println(err) - return nil, fmt.Errorf("failed to stat file or directory: %w", err) - } - // skip any directories found - if info.IsDir() { - continue - } - b, err := os.ReadFile(expandedPath) - if err != nil { - return nil, fmt.Errorf("failed to read file: %w", err) - } - - outputs[expandedPath] = b - } - } - - return outputs, nil -} - -// Loads a single generator plugin given a single file path. -func LoadPlugin(path string) (Generator, error) { - // skip loading plugin if path is a directory with no error - if isDir, err := util.IsDirectory(path); err == nil && isDir { - return nil, nil - } else if err != nil { - return nil, fmt.Errorf("failed to test if plugin path is directory: %w", err) - } - - // try and open the plugin - p, err := plugin.Open(path) - if err != nil { - return nil, fmt.Errorf("failed to open plugin: %w", err) - } - - // load the "Generator" symbol from plugin - symbol, err := p.Lookup("Generator") - if err != nil { - return nil, fmt.Errorf("failed to look up symbol at path '%s': %w", 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 at path '%s'", path) - } - return gen, nil -} - -// Loads all generator plugins in a given directory. -// -// Returns a map of generators. Each generator can be accessed by the name -// returned by the generator.GetName() implemented. -func LoadPlugins(dirpath string, opts ...Option) (map[string]Generator, error) { - // check if verbose option is supplied - var ( - generators = make(map[string]Generator) - params = ToParams(opts...) - ) - - // - err := filepath.Walk(dirpath, func(path string, info fs.FileInfo, err error) error { - // skip trying to load generator plugin if directory or error - if info.IsDir() || err != nil { - return nil - } - - // only try loading if file has .so extension - if filepath.Ext(path) != ".so" { - return nil - } - - // load the generator plugin from current path - gen, err := LoadPlugin(path) - if err != nil { - return fmt.Errorf("failed to load generator in directory '%s': %w", path, err) - } - - // show the plugins found if verbose flag is set - if params.Verbose { - log.Info().Str("plugin_name", gen.GetName()).Msg("found plugin") - } - - // map each generator plugin by name for lookup - generators[gen.GetName()] = gen - return nil - }) - - if err != nil { - return nil, fmt.Errorf("failed to walk directory: %w", err) - } - - return generators, nil -} - -// Generate() is the main function to generate a collection of files and returns them as a map. -// This function only expects a path to a plugin and paths to a collection of templates to -// be used. This function will only load the plugin on-demand and fetch resources as needed. -// -// This function requires that a target and plugin path be set at minimum. -func Generate(config *config.Config, plugin string, params Params) (FileMap, error) { - var ( - gen Generator - ok bool - err error - ) - - // check if generator is built-in first before loading external plugin - log.Debug().Any("generators", DefaultGenerators).Msg("available generators") - gen, ok = DefaultGenerators[plugin] - if !ok { - // only load the plugin needed for this target if we don't find default - log.Error().Str("plugin", plugin).Msg("could not find target in default generators") - gen, err = LoadPlugin(plugin) - if err != nil { - return nil, fmt.Errorf("failed to load plugin from file: %v", err) - } - } - - return gen.Generate(config, params) -} - -// Main function to generate a collection of files as a map with the path as the key and -// the contents of the file as the value. This function currently expects a list of plugin -// paths to load all plugins within a directory. Then, each plugin's generator.GenerateWithTarget() -// function is called for each target specified. -// -// This function is the corresponding implementation for the "generate" CLI subcommand. -// It is also call when running the configurator as a service with the "/generate" route. -// -// TODO: Separate loading plugins so we can load them once when running as a service. -func GenerateWithTarget(config *config.Config, target string) (FileMap, error) { - // load generator plugins to generate configs or to print - var ( - opts []client.Option - targetInfo configurator.Target - generator Generator - params Params - err error - ok bool - ) - - // check if a target is supplied - if target == "" { - return nil, fmt.Errorf("must specify a target") - } - - // load target information from config - targetInfo, ok = config.Targets[target] - if !ok { - log.Warn().Str("target", target).Msg("target not found in config") - } - - // if no plugin supplied in config target, then using the target supplied - if targetInfo.Plugin == "" { - targetInfo.Plugin = target - } - - // check if generator is built-in first before loading - generator, ok = DefaultGenerators[target] - if !ok { - // only load the plugin needed for this target if we don't find default - log.Warn().Str("target", target).Msg("could not find target in default generators") - generator, err = LoadPlugin(targetInfo.Plugin) - if err != nil { - return nil, fmt.Errorf("failed to load plugin: %v", err) - } - } - - // check if there's at least one template available - if len(targetInfo.TemplatePaths) <= 0 { - return nil, fmt.Errorf("expects at least one template to be available") - } - - // prepare params to pass into generator - params.Templates = map[string]Template{} - for _, templatePath := range targetInfo.TemplatePaths { - template := Template{} - template.LoadFromFile(templatePath) - params.Templates[templatePath] = template - } - - // set the client options - if config.AccessToken != "" { - params.ClientOpts = append(opts, client.WithAccessToken(config.AccessToken)) - } - if config.CertPath != "" { - params.ClientOpts = append(opts, client.WithCertPoolFile(config.CertPath)) - } - - // load files that are not to be copied - params.Files, err = LoadFiles(targetInfo.FilePaths...) - if err != nil { - return nil, fmt.Errorf("failed to load files to copy: %v", err) - } - - // run the generator plugin from target passed - return generator.Generate(config, params) -} diff --git a/pkg/generator/hostfile.go b/pkg/generator/hostfile.go deleted file mode 100644 index a9f92e5..0000000 --- a/pkg/generator/hostfile.go +++ /dev/null @@ -1,26 +0,0 @@ -package generator - -import ( - "fmt" - - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type Hostfile struct{} - -func (g *Hostfile) GetName() string { - return "hostfile" -} - -func (g *Hostfile) GetVersion() string { - return util.GitCommit() -} - -func (g *Hostfile) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *Hostfile) Generate(config *config.Config, opts ...Option) (FileMap, error) { - return nil, fmt.Errorf("plugin does not implement generation function") -} diff --git a/pkg/generator/params.go b/pkg/generator/params.go deleted file mode 100644 index e9037ec..0000000 --- a/pkg/generator/params.go +++ /dev/null @@ -1,43 +0,0 @@ -package generator - -import ( - configurator "git.towk2.me/towk/configurator/pkg" - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" -) - -type ( - // Params used by the generator - Params struct { - Templates map[string]Template - Files map[string][]byte - ClientOpts []client.Option - Verbose bool - } - Option func(Params) -) - -func ToParams(opts ...Option) Params { - params := Params{} - for _, opt := range opts { - opt(params) - } - return params -} - -func WithClientOpts(opts ...client.Option) Option { - return func(p Params) { - p.ClientOpts = opts - } -} - -func WithTemplates(templates map[string]Template) Option { - return func(p Params) { - p.Templates = templates - } -} - -// Helper function to get the target in generator.Generate() plugin implementations. -func GetTarget(config *config.Config, key string) configurator.Target { - return config.Targets[key] -} diff --git a/pkg/generator/powerman.go b/pkg/generator/powerman.go deleted file mode 100644 index d8e376f..0000000 --- a/pkg/generator/powerman.go +++ /dev/null @@ -1,26 +0,0 @@ -package generator - -import ( - "fmt" - - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type Powerman struct{} - -func (g *Powerman) GetName() string { - return "powerman" -} - -func (g *Powerman) GetVersion() string { - return util.GitCommit() -} - -func (g *Powerman) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *Powerman) Generate(config *config.Config, opts ...Option) (FileMap, error) { - return nil, fmt.Errorf("plugin does not implement generation function") -} diff --git a/pkg/generator/syslog.go b/pkg/generator/syslog.go deleted file mode 100644 index 450dcbc..0000000 --- a/pkg/generator/syslog.go +++ /dev/null @@ -1,26 +0,0 @@ -package generator - -import ( - "fmt" - - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" -) - -type Syslog struct{} - -func (g *Syslog) GetName() string { - return "syslog" -} - -func (g *Syslog) GetVersion() string { - return util.GitCommit() -} - -func (g *Syslog) GetDescription() string { - return fmt.Sprintf("Configurator generator plugin for '%s'.", g.GetName()) -} - -func (g *Syslog) Generate(config *config.Config, opts ...Option) (FileMap, error) { - return nil, fmt.Errorf("plugin does not implement generation function") -} diff --git a/pkg/generator/templates.go b/pkg/generator/templates.go deleted file mode 100644 index 3028949..0000000 --- a/pkg/generator/templates.go +++ /dev/null @@ -1,98 +0,0 @@ -package generator - -import ( - "bytes" - "fmt" - "os" - - "git.towk2.me/towk/configurator/pkg/util" - "github.com/nikolalohinski/gonja/v2" - "github.com/nikolalohinski/gonja/v2/exec" - "github.com/rs/zerolog/log" -) - -type Template struct { - Contents []byte `json:"contents"` -} - -func (t *Template) LoadFromFile(path string) error { - // skip loading template if path is a directory with no error - if isDir, err := util.IsDirectory(path); err == nil && isDir { - return nil - } else if err != nil { - return fmt.Errorf("failed to test if template path is directory: %w", err) - } - - // try and read the contents of the file - // NOTE: we don't care if this is actually a Jinja template - // or not...at least for now. - contents, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read file: %v", err) - } - t.Contents = contents - return nil -} - -func (t *Template) IsEmpty() bool { - return len(t.Contents) <= 0 -} - -// Wrapper function to slightly abstract away some of the nuances with using gonja -// into a single function call. This function is *mostly* for convenience and -// simplication. If no paths are supplied, then no templates will be applied and -// there will be no output. -// -// The "FileList" returns a slice of byte arrays in the same order as the argument -// list supplied, but with the Jinja templating applied. -func ApplyTemplates(mappings Mappings, templates map[string]Template) (FileMap, error) { - var ( - data = exec.NewContext(mappings) - outputs = FileMap{} - ) - - for path, template := range templates { - // load jinja template from file - t, err := gonja.FromBytes(template.Contents) - if err != nil { - return nil, fmt.Errorf("failed to read template from file: %w", err) - } - - // execute/render jinja template - b := bytes.Buffer{} - if err = t.Execute(&b, data); err != nil { - return nil, fmt.Errorf("failed to execute: %w", err) - } - outputs[path] = b.Bytes() - } - - log.Debug().Any("templates", templates).Any("outputs", outputs).Any("mappings", mappings).Msg("apply templates") - - return outputs, nil -} - -// Wrapper function similiar to "ApplyTemplates" but takes file paths as arguments. -// This function will load templates from a file instead of using file contents. -func ApplyTemplateFromFiles(mappings Mappings, paths ...string) (FileMap, error) { - var ( - data = exec.NewContext(mappings) - outputs = FileMap{} - ) - - for _, path := range paths { - // load jinja template from file - t, err := gonja.FromFile(path) - if err != nil { - return nil, fmt.Errorf("failed to read template from file: %w", err) - } - - // execute/render jinja template - b := bytes.Buffer{} - if err = t.Execute(&b, data); err != nil { - return nil, fmt.Errorf("failed to execute: %w", err) - } - outputs[path] = b.Bytes() - } - - return outputs, nil -} diff --git a/pkg/generator/warewulf.go b/pkg/generator/warewulf.go deleted file mode 100644 index 5a7c803..0000000 --- a/pkg/generator/warewulf.go +++ /dev/null @@ -1,78 +0,0 @@ -package generator - -import ( - "fmt" - "maps" - "strings" - - "git.towk2.me/towk/configurator/pkg/client" - "git.towk2.me/towk/configurator/pkg/config" - "git.towk2.me/towk/configurator/pkg/util" - "github.com/rs/zerolog/log" -) - -type Warewulf struct{} - -func (g *Warewulf) GetName() string { - return "warewulf" -} - -func (g *Warewulf) GetVersion() string { - return util.GitCommit() -} - -func (g *Warewulf) GetDescription() string { - return "Configurator generator plugin for 'warewulf' config files." -} - -func (g *Warewulf) Generate(config *config.Config, params Params) (FileMap, error) { - var ( - smdClient = client.NewSmdClient(params.ClientOpts...) - outputs = make(FileMap, len(params.Templates)) - nodeEntries = "" - paths = []string{} - ) - - // if we have a client, try making the request for the ethernet interfaces - eths, err := smdClient.FetchEthernetInterfaces(params.Verbose) - if err != nil { - return nil, fmt.Errorf("failed to fetch ethernet interfaces with client: %v", err) - } - - // check if we have the required params first - if eths == nil { - return nil, fmt.Errorf("invalid ethernet interfaces (variable is nil)") - } - if len(eths) <= 0 { - return nil, fmt.Errorf("no ethernet interfaces found") - } - - // fetch redfish endpoints and handle errors - eps, err := smdClient.FetchRedfishEndpoints(params.Verbose) - if err != nil { - return nil, fmt.Errorf("failed to fetch redfish endpoints: %v", err) - } - if len(eps) <= 0 { - return nil, fmt.Errorf("no redfish endpoints found") - } - - templates, err := ApplyTemplates(Mappings{ - "node_entries": nodeEntries, - }, params.Templates) - if err != nil { - return nil, fmt.Errorf("failed to load templates: %v", err) - } - - maps.Copy(outputs, params.Files) - maps.Copy(outputs, templates) - - // print message if verbose param is found - if params.Verbose { - for path, _ := range outputs { - paths = append(paths, path) - } - } - log.Info().Str("paths", strings.Join(paths, ":")).Msg("templates and files loaded: \n") - - return outputs, err -} diff --git a/pkg/service/profile.go b/pkg/service/profile.go index e0fb473..6bcdebe 100644 --- a/pkg/service/profile.go +++ b/pkg/service/profile.go @@ -10,6 +10,7 @@ import ( "path/filepath" "github.com/go-chi/chi/v5" + "github.com/tidwall/sjson" ) type Profile struct { @@ -43,7 +44,7 @@ func (s *Service) GetProfiles() http.HandlerFunc { // read file contents var profile *Profile - profile, err = LoadProfile(path) + profile, err = LoadProfileFromFile(path) if err != nil { return err } @@ -91,7 +92,7 @@ func (s *Service) GetProfile() http.HandlerFunc { err error ) - profile, err = LoadProfile(path) + profile, err = LoadProfileFromFile(path) if err != nil { http.Error(w, err.Error(), http.StatusBadRequest) return @@ -114,8 +115,8 @@ func (s *Service) GetProfile() http.HandlerFunc { func (s *Service) CreateProfile() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { type input struct { - path string `json:"path"` - profile *Profile `json:"profile"` + Path string `json:"path"` + Profile *Profile `json:"profile"` } var ( body, contents []byte @@ -137,37 +138,85 @@ func (s *Service) CreateProfile() http.HandlerFunc { } // serialize just the profile part - contents, err = json.Marshal(in.profile) + contents, err = json.Marshal(in.Profile) if err != nil { - + http.Error(w, err.Error(), http.StatusBadRequest) + return } // create a new profile on disk - err = os.WriteFile(in.path, contents, os.ModePerm) + err = os.WriteFile(in.Path, contents, os.ModePerm) if err != nil { - + http.Error(w, err.Error(), http.StatusBadRequest) + return } w.WriteHeader(http.StatusOK) } } -func (s *Service) CreateProfileVar() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) {} +func (s *Service) SetProfileData() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + var ( + body, contents []byte + newContents string + profile *Profile + path string + err error + ) + + body, err = io.ReadAll(r.Body) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + err = json.Unmarshal(body, &profile) + if err != nil { + http.Error(w, err.Error(), http.StatusBadRequest) + return + } + + // make sure the request data sets an ID + if profile.ID == "" { + http.Error(w, "ID must be set to a non-empty value", http.StatusBadRequest) + return + } + + // read the contents the file with profile ID + path = s.BuildProfilePath(profile.ID) + contents, err = os.ReadFile(path) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // modify the data of the profile's contents + newContents, err = sjson.Set(string(contents), "data", profile.Data) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + + // write only the data to the file with ID + err = os.WriteFile(path, []byte(newContents), os.ModePerm) + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + } } -func (s *Service) DeleteProfileVar() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) {} +func (s *Service) DeleteProfileData() http.HandlerFunc { + return func(w http.ResponseWriter, r *http.Request) { + + } } func (s *Service) GetProfileData() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) {} } -func (s *Service) GetProfileVar() http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) {} -} - func (s *Service) CreateProfilePath() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) {} } diff --git a/pkg/service/service.go b/pkg/service/service.go index 6c3467d..9a1545a 100644 --- a/pkg/service/service.go +++ b/pkg/service/service.go @@ -62,10 +62,9 @@ func (s *Service) Serve() error { // router.Post("/profiles", s.CreateProfiles()) router.Get("/profile/{id}", s.GetProfile()) router.Post("/profile/{id}", s.CreateProfile()) - router.Post("/profile/{id}/data/{varname}", s.CreateProfileVar()) - router.Delete("/profile/{id}/data/{varname}", s.DeleteProfileVar()) router.Get("/profile/{id}/data", s.GetProfileData()) - router.Get("/profile/{id}/data/{varname}", s.GetProfileVar()) + router.Post("/profile/{id}/data", s.SetProfileData()) + router.Delete("/profile/{id}/data", s.DeleteProfileData()) router.Post("/profile/{id}/paths/{path}", s.CreateProfilePath()) router.Delete("/profile/{id}/paths/{path}", s.DeleteProfilePath()) router.Get("/profile/{id}/paths/{path}", s.GetProfilePath()) @@ -89,11 +88,11 @@ func (s *Service) FetchJwks(uri string) { } -func LoadProfile(path string) (*Profile, error) { +func LoadProfileFromFile(path string) (*Profile, error) { return LoadFromJSONFile[Profile](path) } -func LoadPlugin(path string) (*configurator.Plugin, error) { +func LoadPluginFromFile(path string) (*configurator.Plugin, error) { return LoadFromJSONFile[configurator.Plugin](path) }