From ab2139a1fda905420d9a4eec9efbe0f745ff5ed5 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 1 Mar 2023 16:42:58 +0100 Subject: [PATCH 01/22] added wwctl genconf used to generate completions Signed-off-by: Christian Goll --- Makefile | 30 ++++++++----------- .../app/wwctl/genconf/completions/main.go | 23 ++++++++++++++ .../app/wwctl/genconf/completions/root.go | 22 ++++++++++++++ internal/app/wwctl/genconf/root.go | 26 ++++++++++++++++ internal/app/wwctl/root.go | 2 ++ 5 files changed, 86 insertions(+), 17 deletions(-) create mode 100644 internal/app/wwctl/genconf/completions/main.go create mode 100644 internal/app/wwctl/genconf/completions/root.go create mode 100644 internal/app/wwctl/genconf/root.go diff --git a/Makefile b/Makefile index 2772c723..c2365b1e 100644 --- a/Makefile +++ b/Makefile @@ -88,6 +88,11 @@ GO_TOOLS_VENDOR := $(addprefix vendor/, $(GO_TOOLS)) GOLANGCI_LINT := $(TOOLS_BIN)/golangci-lint GOLANGCI_LINT_VERSION := v1.50.0 +# helper functions +godeps=$(shell go list -deps -f '{{if not .Standard}}{{ $$dep := . }}{{range .GoFiles}}{{$$dep.Dir}}/{{.}} {{end}}{{end}}' $(1) | sed "s%${PWD}/%%g") +WWCTL_DEPS:=$(call godeps,cmd/wwctl/main.go) +WWCLIENT_DEPS:=$(call godeps,cmd/wwclient/main.go) + # use GOPROXY for older git clients and speed up downloads GOPROXY ?= https://proxy.golang.org export GOPROXY @@ -96,7 +101,7 @@ export GOPROXY WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree # Default target -all: config vendor wwctl wwclient bash_completion.d man_pages config_defaults print_defaults wwapid wwapic wwapird print_mnts +all: config vendor wwctl wwclient man_pages config_defaults print_defaults wwapid wwapic wwapird print_mnts # Validate source and build all packages build: lint test-it vet all @@ -197,7 +202,7 @@ files: all install -m 0644 include/firewalld/warewulf.xml $(DESTDIR)$(FIREWALLDDIR) install -m 0644 include/systemd/warewulfd.service $(DESTDIR)$(SYSTEMDDIR) install -m 0644 LICENSE.md $(DESTDIR)$(WWDOCDIR) - cp bash_completion.d/warewulf $(DESTDIR)$(BASHCOMPDIR) + ./wwctl genconf completions > $(DESTDIR)$(BASHCOMPDIR)/wwctl cp man_pages/*.1* $(DESTDIR)$(MANDIR)/man1/ cp man_pages/*.5* $(DESTDIR)$(MANDIR)/man5/ install -m 0644 staticfiles/README-ipxe.md $(DESTDIR)$(WWDATADIR)/ipxe @@ -210,25 +215,18 @@ init: cp -r tftpboot/* $(WWTFTPDIR)/ipxe/ restorecon -r $(WWTFTPDIR) -wwctl: - cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../wwctl +wwctl: $(WWCTL_DEPS) + @echo Building "$@" + @cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../wwctl -wwclient: - cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ +wwclient: $(WWCLIENT_DEPS) + @echo Building "$@" + @ cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ -X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient install_wwclient: wwclient install -m 0755 wwclient $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/wwclient -bash_completion: - cd cmd/bash_completion && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ - -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ - -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../bash_completion - -bash_completion.d: bash_completion - install -d -m 0755 bash_completion.d - ./bash_completion bash_completion.d/warewulf - man_page: cd cmd/man_page && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ @@ -297,8 +295,6 @@ contclean: rm -f wwctl rm -rf .dist rm -f $(WAREWULF)-$(VERSION).tar.gz - rm -f bash_completion - rm -rf bash_completion.d rm -f man_page rm -rf man_pages rm -f warewulf.spec diff --git a/internal/app/wwctl/genconf/completions/main.go b/internal/app/wwctl/genconf/completions/main.go new file mode 100644 index 00000000..53827131 --- /dev/null +++ b/internal/app/wwctl/genconf/completions/main.go @@ -0,0 +1,23 @@ +package completions + +import ( + "os" + + "github.com/spf13/cobra" +) + +func CobraRunE(cmd *cobra.Command, args []string) error { + myArg := "bash" + if len(args) == 1 { + myArg = args[0] + } + switch myArg { + case "zsh": + cmd.GenZshCompletion(os.Stdout) + case "fish": + cmd.GenFishCompletion(os.Stdout, true) + default: + cmd.GenBashCompletion(os.Stdout) + } + return nil +} diff --git a/internal/app/wwctl/genconf/completions/root.go b/internal/app/wwctl/genconf/completions/root.go new file mode 100644 index 00000000..1e22f904 --- /dev/null +++ b/internal/app/wwctl/genconf/completions/root.go @@ -0,0 +1,22 @@ +package completions + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "completions", + Short: "shell completion", + Long: "This command generates the bash completions if no argument is given.", + RunE: CobraRunE, + Args: cobra.MaximumNArgs(1), + Aliases: []string{"bash"}, + } + Zsh bool +) + +func init() { +} + +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/genconf/root.go b/internal/app/wwctl/genconf/root.go new file mode 100644 index 00000000..3584164d --- /dev/null +++ b/internal/app/wwctl/genconf/root.go @@ -0,0 +1,26 @@ +package genconf + +import ( + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/completions" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "genconfig", + Short: "Generate various configurations", + Long: "This command will allow you to generate different configurations like bash-completions.", + Args: cobra.ExactArgs(0), + Aliases: []string{"cnf"}, + } + ListFull bool +) + +func init() { + baseCmd.AddCommand(completions.GetCommand()) +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index cc8927d6..f60918b1 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -3,6 +3,7 @@ package wwctl import ( "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" + "github.com/hpcng/warewulf/internal/app/wwctl/genconf" "github.com/hpcng/warewulf/internal/app/wwctl/kernel" "github.com/hpcng/warewulf/internal/app/wwctl/node" "github.com/hpcng/warewulf/internal/app/wwctl/overlay" @@ -52,6 +53,7 @@ func init() { rootCmd.AddCommand(server.GetCommand()) rootCmd.AddCommand(version.GetCommand()) rootCmd.AddCommand(ssh.GetCommand()) + rootCmd.AddCommand(genconf.GetCommand()) } // GetRootCommand returns the root cobra.Command for the application. From 94866656a4e48ee5a09f26493e7d6affc1303653 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 2 Mar 2023 11:01:11 +0100 Subject: [PATCH 02/22] generate man pages via sub command Signed-off-by: Christian Goll --- Makefile | 18 ++++----------- cmd/bash_completion/bash_completion.go | 23 ------------------- cmd/man_page/man_page.go | 17 -------------- .../app/wwctl/genconf/completions/main.go | 10 ++++---- internal/app/wwctl/genconf/man/main.go | 15 ++++++++++++ internal/app/wwctl/genconf/man/root.go | 23 +++++++++++++++++++ internal/app/wwctl/genconf/root.go | 5 +++- internal/app/wwctl/root.go | 19 --------------- 8 files changed, 52 insertions(+), 78 deletions(-) delete mode 100644 cmd/bash_completion/bash_completion.go delete mode 100644 cmd/man_page/man_page.go create mode 100644 internal/app/wwctl/genconf/man/main.go create mode 100644 internal/app/wwctl/genconf/man/root.go diff --git a/Makefile b/Makefile index c2365b1e..59927775 100644 --- a/Makefile +++ b/Makefile @@ -196,6 +196,7 @@ files: all chmod 644 $(DESTDIR)$(WWOVERLAYDIR)/wwinit/warewulf/config.ww chmod 750 $(DESTDIR)$(WWOVERLAYDIR)/host install -m 0755 wwctl $(DESTDIR)$(BINDIR) + install -m 0755 wwclient $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/wwclient install -m 0755 wwapic $(DESTDIR)$(BINDIR) install -m 0755 wwapid $(DESTDIR)$(BINDIR) install -m 0755 wwapird $(DESTDIR)$(BINDIR) @@ -224,17 +225,9 @@ wwclient: $(WWCLIENT_DEPS) @ cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ -X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient -install_wwclient: wwclient - install -m 0755 wwclient $(DESTDIR)$(WWOVERLAYDIR)/wwinit/$(WWCLIENTDIR)/wwclient - -man_page: - cd cmd/man_page && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ - -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ - -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../man_page - -man_pages: man_page +man_pages: wwctl install -d man_pages - ./man_page ./man_pages + ./wwctl genconfig man man_pages cp docs/man/man5/*.5 ./man_pages/ cd man_pages; for i in wwctl*1 *.5; do echo "Compressing manpage: $$i"; gzip --force $$i; done @@ -272,7 +265,7 @@ dist: vendor config ## sudo make install ## sudo ldconfig # refresh shared library cache. ## To setup protoc-gen-grpc-gateway, see https://github.com/grpc-ecosystem/grpc-gateway -proto: +proto: rm -rf internal/pkg/api/routes/wwapiv1/ protoc -I internal/pkg/api/routes/v1 -I=. \ --grpc-gateway_out=. \ @@ -295,7 +288,6 @@ contclean: rm -f wwctl rm -rf .dist rm -f $(WAREWULF)-$(VERSION).tar.gz - rm -f man_page rm -rf man_pages rm -f warewulf.spec rm -f config @@ -309,6 +301,6 @@ contclean: clean: contclean rm -rf vendor -install: files install_wwclient +install: files debinstall: files debfiles diff --git a/cmd/bash_completion/bash_completion.go b/cmd/bash_completion/bash_completion.go deleted file mode 100644 index 752884bc..00000000 --- a/cmd/bash_completion/bash_completion.go +++ /dev/null @@ -1,23 +0,0 @@ -// usage: ./bash_completion -package main - -import ( - "fmt" - "github.com/hpcng/warewulf/internal/app/wwctl" - "os" -) - -func main() { - fh, err := os.Create(os.Args[1]) - if err != nil { - fmt.Println(err) - return - } - - defer fh.Close() - - if err := wwctl.GenBashCompletion(fh); err != nil { - fmt.Println(err) - return - } -} diff --git a/cmd/man_page/man_page.go b/cmd/man_page/man_page.go deleted file mode 100644 index 8a35a3be..00000000 --- a/cmd/man_page/man_page.go +++ /dev/null @@ -1,17 +0,0 @@ -// Generate man pages for wwctl command. -// usage: ./man_page -package main - -import ( - "fmt" - "github.com/hpcng/warewulf/internal/app/wwctl" - "os" -) - -func main() { - - if err := wwctl.GenManTree(os.Args[1]); err != nil { - fmt.Println(err) - return - } -} diff --git a/internal/app/wwctl/genconf/completions/main.go b/internal/app/wwctl/genconf/completions/main.go index 53827131..01557f52 100644 --- a/internal/app/wwctl/genconf/completions/main.go +++ b/internal/app/wwctl/genconf/completions/main.go @@ -6,18 +6,18 @@ import ( "github.com/spf13/cobra" ) -func CobraRunE(cmd *cobra.Command, args []string) error { +func CobraRunE(cmd *cobra.Command, args []string) (err error) { myArg := "bash" if len(args) == 1 { myArg = args[0] } switch myArg { case "zsh": - cmd.GenZshCompletion(os.Stdout) + err = cmd.Parent().Parent().GenZshCompletion(os.Stdout) case "fish": - cmd.GenFishCompletion(os.Stdout, true) + err = cmd.Parent().Parent().GenFishCompletion(os.Stdout, true) default: - cmd.GenBashCompletion(os.Stdout) + err = cmd.Parent().Parent().GenBashCompletion(os.Stdout) } - return nil + return } diff --git a/internal/app/wwctl/genconf/man/main.go b/internal/app/wwctl/genconf/man/main.go new file mode 100644 index 00000000..3e752307 --- /dev/null +++ b/internal/app/wwctl/genconf/man/main.go @@ -0,0 +1,15 @@ +package man + +import ( + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + header := &doc.GenManHeader{ + Title: "WWCTL", + Section: "1", + } + err = doc.GenManTree(cmd.Parent().Parent(), header, args[0]) + return +} diff --git a/internal/app/wwctl/genconf/man/root.go b/internal/app/wwctl/genconf/man/root.go new file mode 100644 index 00000000..d450e5d3 --- /dev/null +++ b/internal/app/wwctl/genconf/man/root.go @@ -0,0 +1,23 @@ +package man + +import ( + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "man", + Short: "manpage generation", + Long: "This command generates the man pages for all commands, needs target dir as argument", + RunE: CobraRunE, + Args: cobra.ExactArgs(1), + Aliases: []string{"man_pages"}, + } +) + +func init() { +} + +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/genconf/root.go b/internal/app/wwctl/genconf/root.go index 3584164d..0c8afb2f 100644 --- a/internal/app/wwctl/genconf/root.go +++ b/internal/app/wwctl/genconf/root.go @@ -2,6 +2,7 @@ package genconf import ( "github.com/hpcng/warewulf/internal/app/wwctl/genconf/completions" + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/man" "github.com/spf13/cobra" ) @@ -13,11 +14,13 @@ var ( Args: cobra.ExactArgs(0), Aliases: []string{"cnf"}, } - ListFull bool + ListFull bool + WWctlRoot *cobra.Command ) func init() { baseCmd.AddCommand(completions.GetCommand()) + baseCmd.AddCommand(man.GetCommand()) } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index f60918b1..20a02657 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -15,9 +15,6 @@ import ( "github.com/hpcng/warewulf/internal/pkg/help" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" - "github.com/spf13/cobra/doc" - - "io" ) var ( @@ -74,19 +71,3 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { } return nil } - -// External functions not used by the wwctl command line - -// Generate Bash completion file -func GenBashCompletion(w io.Writer) error { - return rootCmd.GenBashCompletion(w) -} - -// Generate man pages -func GenManTree(fileName string) error { - header := &doc.GenManHeader{ - Title: "WWCTL", - Section: "1", - } - return doc.GenManTree(rootCmd, header, fileName) -} From 786ccdb1e1a7de3a2f106d10a4ee3771dfeaaa87 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 2 Mar 2023 12:18:59 +0100 Subject: [PATCH 03/22] generate reference documentation Signed-off-by: Christian Goll --- .gitignore | 1 + Makefile | 8 ++++++- internal/app/wwctl/genconf/reference/main.go | 17 ++++++++++++++ internal/app/wwctl/genconf/reference/root.go | 22 +++++++++++++++++++ internal/app/wwctl/genconf/root.go | 2 ++ userdocs/{reference => contents}/glossary.rst | 0 userdocs/index.rst | 7 +++++- 7 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 internal/app/wwctl/genconf/reference/main.go create mode 100644 internal/app/wwctl/genconf/reference/root.go rename userdocs/{reference => contents}/glossary.rst (100%) diff --git a/.gitignore b/.gitignore index 96fe0936..10a7f077 100644 --- a/.gitignore +++ b/.gitignore @@ -38,3 +38,4 @@ Defaults.mk /etc/wwapird.conf .dist/ userdocs/_* +userdocs/reference/* diff --git a/Makefile b/Makefile index 59927775..1303ae40 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ export GOPROXY WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree # Default target -all: config vendor wwctl wwclient man_pages config_defaults print_defaults wwapid wwapic wwapird print_mnts +all: config vendor wwctl wwclient man_pages config_defaults print_defaults wwapid wwapic wwapird # Validate source and build all packages build: lint test-it vet all @@ -255,6 +255,12 @@ dist: vendor config cd .dist; tar -czf ../$(WAREWULF)-$(VERSION).tar.gz $(WAREWULF)-$(VERSION) rm -rf .dist +reference: wwctl + ./wwctl genconfig reference userdocs/reference/ + +latexpdf: reference + make -C userdocs latexpdf + ## wwapi generate code from protobuf. Requires protoc and protoc-grpc-gen-gateway to generate code. ## To setup latest protoc: ## Download the protobuf-all-[VERSION].tar.gz from https://github.com/protocolbuffers/protobuf/releases diff --git a/internal/app/wwctl/genconf/reference/main.go b/internal/app/wwctl/genconf/reference/main.go new file mode 100644 index 00000000..c3cdacaa --- /dev/null +++ b/internal/app/wwctl/genconf/reference/main.go @@ -0,0 +1,17 @@ +package reference + +import ( + "fmt" + + "github.com/spf13/cobra" + "github.com/spf13/cobra/doc" +) + +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + linkHandler := func(name, ref string) string { + return fmt.Sprintf(":ref:`%s <%s>`", name, ref) + } + err = doc.GenReSTTreeCustom(cmd.Parent().Parent(), args[0], func(arg string) string { return "" }, linkHandler) + //err = doc.GenReSTTree(cmd.Parent().Parent(), args[0]) + return +} diff --git a/internal/app/wwctl/genconf/reference/root.go b/internal/app/wwctl/genconf/reference/root.go new file mode 100644 index 00000000..de89d871 --- /dev/null +++ b/internal/app/wwctl/genconf/reference/root.go @@ -0,0 +1,22 @@ +package reference + +import ( + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "reference", + Short: "reference generation", + Long: "This command generates the references in ReStructured Text, needs target dir as argument", + RunE: CobraRunE, + Args: cobra.ExactArgs(1), + } +) + +func init() { +} + +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/genconf/root.go b/internal/app/wwctl/genconf/root.go index 0c8afb2f..fc240021 100644 --- a/internal/app/wwctl/genconf/root.go +++ b/internal/app/wwctl/genconf/root.go @@ -3,6 +3,7 @@ package genconf import ( "github.com/hpcng/warewulf/internal/app/wwctl/genconf/completions" "github.com/hpcng/warewulf/internal/app/wwctl/genconf/man" + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/reference" "github.com/spf13/cobra" ) @@ -21,6 +22,7 @@ var ( func init() { baseCmd.AddCommand(completions.GetCommand()) baseCmd.AddCommand(man.GetCommand()) + baseCmd.AddCommand(reference.GetCommand()) } // GetRootCommand returns the root cobra.Command for the application. diff --git a/userdocs/reference/glossary.rst b/userdocs/contents/glossary.rst similarity index 100% rename from userdocs/reference/glossary.rst rename to userdocs/contents/glossary.rst diff --git a/userdocs/index.rst b/userdocs/index.rst index 7b2b2ecc..c65537cd 100644 --- a/userdocs/index.rst +++ b/userdocs/index.rst @@ -41,9 +41,14 @@ Welcome to the Warewulf User Guide! Documentation Development Environment (KVM) Development Environment (VirtualBox) + Glossary .. toctree:: :maxdepth: 2 :caption: Reference + :glob: + + reference/* + + - Glossary From 61960b6c8cad394010236fc848dd7e1d0ebf1a28 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 2 Mar 2023 15:23:46 +0100 Subject: [PATCH 04/22] moved print_defaults to wwctl genconfig defaults Signed-off-by: Christian Goll --- Makefile | 11 +++-------- cmd/print_defaults/print_defaults.go | 17 ----------------- internal/app/wwctl/genconf/dfaults/main.go | 13 +++++++++++++ internal/app/wwctl/genconf/dfaults/root.go | 22 ++++++++++++++++++++++ internal/app/wwctl/genconf/root.go | 2 ++ 5 files changed, 40 insertions(+), 25 deletions(-) delete mode 100644 cmd/print_defaults/print_defaults.go create mode 100644 internal/app/wwctl/genconf/dfaults/main.go create mode 100644 internal/app/wwctl/genconf/dfaults/root.go diff --git a/Makefile b/Makefile index 1303ae40..9fdbc02b 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ export GOPROXY WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree # Default target -all: config vendor wwctl wwclient man_pages config_defaults print_defaults wwapid wwapic wwapird +all: config vendor wwctl wwclient man_pages config_defaults wwapid wwapic wwapird # Validate source and build all packages build: lint test-it vet all @@ -183,7 +183,7 @@ files: all test -f $(DESTDIR)$(WWCONFIGDIR)/wwapic.conf || install -m 644 etc/wwapic.conf $(DESTDIR)$(WWCONFIGDIR) test -f $(DESTDIR)$(WWCONFIGDIR)/wwapid.conf || install -m 644 etc/wwapid.conf $(DESTDIR)$(WWCONFIGDIR) test -f $(DESTDIR)$(WWCONFIGDIR)/wwapird.conf || install -m 644 etc/wwapird.conf $(DESTDIR)$(WWCONFIGDIR) - test -f $(DESTDIR)$(WWCONFIGDIR)/defaults.conf || ./print_defaults > $(DESTDIR)$(WWCONFIGDIR)/defaults.conf + test -f $(DESTDIR)$(WWCONFIGDIR)/defaults.conf || ./wwctl genconfig defaults > $(DESTDIR)$(WWCONFIGDIR)/defaults.conf cp -r etc/examples $(DESTDIR)$(WWCONFIGDIR)/ cp -r etc/ipxe $(DESTDIR)$(WWCONFIGDIR)/ cp -r overlays/* $(DESTDIR)$(WWOVERLAYDIR)/ @@ -222,7 +222,7 @@ wwctl: $(WWCTL_DEPS) wwclient: $(WWCLIENT_DEPS) @echo Building "$@" - @ cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ + @cd cmd/wwclient; CGO_ENABLED=0 GOOS=linux go build -mod vendor -a -ldflags "-extldflags -static \ -X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=/etc/warewulf/warewulf.conf'" -o ../../wwclient man_pages: wwctl @@ -236,10 +236,6 @@ config_defaults: vendor cmd/config_defaults/config_defaults.go -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../config_defaults -print_defaults: vendor cmd/print_defaults/print_defaults.go - cd cmd/print_defaults && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'" -o ../../print_defaults - - update_configuration: vendor cmd/update_configuration/update_configuration.go cd cmd/update_configuration && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ @@ -301,7 +297,6 @@ contclean: rm -rf $(TOOLS_DIR) rm -f config_defaults rm -f update_configuration - rm -f print_defaults rm -f etc/wwapi{c,d,rd}.conf clean: contclean diff --git a/cmd/print_defaults/print_defaults.go b/cmd/print_defaults/print_defaults.go deleted file mode 100644 index 397294dd..00000000 --- a/cmd/print_defaults/print_defaults.go +++ /dev/null @@ -1,17 +0,0 @@ -package main - -import ( - "fmt" - - "github.com/hpcng/warewulf/internal/pkg/node" -) - -/* -Print the build in defaults for the nodes. -Called via Makefile so that there is single upstream -source of the defaults which is FallBackConf -*/ - -func main() { - fmt.Println(node.FallBackConf) -} diff --git a/internal/app/wwctl/genconf/dfaults/main.go b/internal/app/wwctl/genconf/dfaults/main.go new file mode 100644 index 00000000..a10309f0 --- /dev/null +++ b/internal/app/wwctl/genconf/dfaults/main.go @@ -0,0 +1,13 @@ +package dfaults + +import ( + "fmt" + + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/spf13/cobra" +) + +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + fmt.Println(node.FallBackConf) + return +} diff --git a/internal/app/wwctl/genconf/dfaults/root.go b/internal/app/wwctl/genconf/dfaults/root.go new file mode 100644 index 00000000..ad575709 --- /dev/null +++ b/internal/app/wwctl/genconf/dfaults/root.go @@ -0,0 +1,22 @@ +package dfaults + +import "github.com/spf13/cobra" + +var ( + baseCmd = &cobra.Command{ + Use: "defaults", + Short: "print defaults", + Long: "This command prints the fallbacks which are used if defaults.conf isn't present", + RunE: CobraRunE, + Args: cobra.NoArgs, + Aliases: []string{"dfaults"}, + } + Zsh bool +) + +func init() { +} + +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/genconf/root.go b/internal/app/wwctl/genconf/root.go index fc240021..5f9a8a4b 100644 --- a/internal/app/wwctl/genconf/root.go +++ b/internal/app/wwctl/genconf/root.go @@ -2,6 +2,7 @@ package genconf import ( "github.com/hpcng/warewulf/internal/app/wwctl/genconf/completions" + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/dfaults" "github.com/hpcng/warewulf/internal/app/wwctl/genconf/man" "github.com/hpcng/warewulf/internal/app/wwctl/genconf/reference" "github.com/spf13/cobra" @@ -23,6 +24,7 @@ func init() { baseCmd.AddCommand(completions.GetCommand()) baseCmd.AddCommand(man.GetCommand()) baseCmd.AddCommand(reference.GetCommand()) + baseCmd.AddCommand(dfaults.GetCommand()) } // GetRootCommand returns the root cobra.Command for the application. From bb894df100f47d745416b1efef9ad7ef6be1d0f1 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 2 Mar 2023 19:44:48 +0100 Subject: [PATCH 05/22] added make_defaults to wwctl genconfig defaults Signed-off-by: Christian Goll --- internal/app/wwctl/genconf/dfaults/root.go | 1 - internal/app/wwctl/root.go | 10 +++++++--- internal/pkg/warewulfconf/constructors.go | 12 +++++++++--- internal/pkg/warewulfconf/datastructure.go | 7 +------ 4 files changed, 17 insertions(+), 13 deletions(-) diff --git a/internal/app/wwctl/genconf/dfaults/root.go b/internal/app/wwctl/genconf/dfaults/root.go index ad575709..9eadd58a 100644 --- a/internal/app/wwctl/genconf/dfaults/root.go +++ b/internal/app/wwctl/genconf/dfaults/root.go @@ -11,7 +11,6 @@ var ( Args: cobra.NoArgs, Aliases: []string{"dfaults"}, } - Zsh bool ) func init() { diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 20a02657..9c746c79 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -13,6 +13,7 @@ import ( "github.com/hpcng/warewulf/internal/app/wwctl/ssh" "github.com/hpcng/warewulf/internal/app/wwctl/version" "github.com/hpcng/warewulf/internal/pkg/help" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/spf13/cobra" ) @@ -27,9 +28,10 @@ var ( SilenceUsage: true, SilenceErrors: true, } - verboseArg bool - DebugFlag bool - LogLevel int + verboseArg bool + DebugFlag bool + LogLevel int + WarewulfConfArg string ) func init() { @@ -37,6 +39,7 @@ func init() { rootCmd.PersistentFlags().BoolVarP(&DebugFlag, "debug", "d", false, "Run with debugging messages enabled.") rootCmd.PersistentFlags().IntVar(&LogLevel, "loglevel", wwlog.INFO, "Set log level to given string") _ = rootCmd.PersistentFlags().MarkHidden("loglevel") + rootCmd.PersistentFlags().StringVar(&WarewulfConfArg, "warewulfconf", "", "Set the warewulf configuration file") rootCmd.SetUsageTemplate(help.UsageTemplate) rootCmd.SetHelpTemplate(help.HelpTemplate) @@ -69,5 +72,6 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { if LogLevel != wwlog.INFO { wwlog.SetLogLevel(LogLevel) } + warewulfconf.ConfigFile = WarewulfConfArg return nil } diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index c434d66e..f956bcd0 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -19,7 +19,13 @@ var cachedConf ControllerConf var ConfigFile string +/* +Get the configFile location from the os.ev if set +*/ func init() { + if ConfigFile == "" { + ConfigFile = os.Getenv("WARWULFCONF") + } if ConfigFile == "" { ConfigFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/warewulf.conf") } @@ -51,7 +57,7 @@ func New() (ControllerConf, error) { wwlog.Debug("Opening Warewulf configuration file: %s", ConfigFile) data, err := os.ReadFile(ConfigFile) if err != nil { - wwlog.Warn("Error reading Warewulf configuration file") + wwlog.Warn("Error reading Warewulf configuration file, falling back on defaults") } wwlog.Debug("Unmarshaling the Warewulf configuration") @@ -71,12 +77,12 @@ func New() (ControllerConf, error) { localIp := conn.LocalAddr().(*net.UDPAddr) if ret.Ipaddr == "" { ret.Ipaddr = localIp.IP.String() - wwlog.Warn("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr) + wwlog.Verbose("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr) } if ret.Netmask == "" { mask := localIp.IP.DefaultMask() ret.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) - wwlog.Warn("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask) + wwlog.Verbose("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask) } } diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index 8403e878..38443883 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -2,7 +2,6 @@ package warewulfconf import ( "github.com/creasty/defaults" - "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) @@ -80,13 +79,9 @@ func (s *NfsConf) Unmarshal(unmarshal func(interface{}) error) error { } func init() { - if !util.IsFile(ConfigFile) { - wwlog.Error("Configuration file not found: %s", ConfigFile) - // fail silently as this also called by bash_completion - } _, err := New() if err != nil { - wwlog.Error("Could not read Warewulf configuration file: %s", err) + wwlog.Warn("Could not get any Warewulf configuration: %s", err) } } From 78978ad2337e2fae679de9e9e241e81647d09252 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 3 Mar 2023 11:18:49 +0100 Subject: [PATCH 06/22] added warewulfconf as command line parameter the environment variable WAREWULFCONF is also recognized Signed-off-by: Christian Goll --- .../app/wwctl/container/exec/child/main.go | 7 +- internal/app/wwctl/node/status/main.go | 11 +- internal/app/wwctl/overlay/build/main.go | 6 +- internal/app/wwctl/root.go | 9 +- internal/app/wwctl/server/start/main.go | 5 +- internal/pkg/api/node/node.go | 6 +- internal/pkg/configure/dhcp.go | 10 +- internal/pkg/configure/nfs.go | 12 +- internal/pkg/configure/tftp.go | 8 +- internal/pkg/overlay/datastructure.go | 6 +- internal/pkg/warewulfconf/constructors.go | 169 ++++++++++-------- internal/pkg/warewulfconf/datastructure.go | 9 +- internal/pkg/warewulfd/daemon.go | 5 +- internal/pkg/warewulfd/provision.go | 69 ++++--- internal/pkg/warewulfd/warewulfd.go | 5 +- 15 files changed, 151 insertions(+), 186 deletions(-) diff --git a/internal/app/wwctl/container/exec/child/main.go b/internal/app/wwctl/container/exec/child/main.go index bf32ad17..9b62b507 100644 --- a/internal/app/wwctl/container/exec/child/main.go +++ b/internal/app/wwctl/container/exec/child/main.go @@ -21,7 +21,7 @@ import ( "github.com/spf13/cobra" ) -func CobraRunE(cmd *cobra.Command, args []string) error { +func CobraRunE(cmd *cobra.Command, args []string) (err error) { if os.Getpid() != 1 { wwlog.Error("PID is not 1: %d", os.Getpid()) os.Exit(1) @@ -33,10 +33,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { wwlog.Error("Unknown Warewulf container: %s", containerName) os.Exit(1) } - conf, err := warewulfconf.New() - if err != nil { - wwlog.Verbose("Couldn't get warewulf ocnfiguration: %s", err) - } + conf := warewulfconf.New() mountPts := conf.MountsContainer mountPts = append(container.InitMountPnts(binds), mountPts...) // check for valid mount points diff --git a/internal/app/wwctl/node/status/main.go b/internal/app/wwctl/node/status/main.go index 1999627f..5d8cdef7 100644 --- a/internal/app/wwctl/node/status/main.go +++ b/internal/app/wwctl/node/status/main.go @@ -2,7 +2,6 @@ package nodestatus import ( "fmt" - "os" "sort" "strings" "time" @@ -19,15 +18,11 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) (err error) { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - os.Exit(1) - } + controller := warewulfconf.New() if controller.Ipaddr == "" { - wwlog.Error("The Warewulf Server IP Address is not properly configured") - os.Exit(1) + return fmt.Errorf("warewulf Server IP Address is not properly configured") + } for { diff --git a/internal/app/wwctl/overlay/build/main.go b/internal/app/wwctl/overlay/build/main.go index 30babd08..556833c4 100644 --- a/internal/app/wwctl/overlay/build/main.go +++ b/internal/app/wwctl/overlay/build/main.go @@ -14,11 +14,7 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - os.Exit(1) - } + controller := warewulfconf.New() nodeDB, err := node.New() if err != nil { wwlog.Error("Could not open node configuration: %s", err) diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 9c746c79..f40e859d 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -1,6 +1,8 @@ package wwctl import ( + "os" + "github.com/hpcng/warewulf/internal/app/wwctl/configure" "github.com/hpcng/warewulf/internal/app/wwctl/container" "github.com/hpcng/warewulf/internal/app/wwctl/genconf" @@ -72,6 +74,11 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { if LogLevel != wwlog.INFO { wwlog.SetLogLevel(LogLevel) } - warewulfconf.ConfigFile = WarewulfConfArg + conf := warewulfconf.New() + if WarewulfConfArg != "" { + conf.ReadConf(WarewulfConfArg) + } else if os.Getenv("WAREWULFCONF") != "" { + conf.ReadConf(os.Getenv("WAREWULFCONF")) + } return nil } diff --git a/internal/app/wwctl/server/start/main.go b/internal/app/wwctl/server/start/main.go index b1954a46..00429177 100644 --- a/internal/app/wwctl/server/start/main.go +++ b/internal/app/wwctl/server/start/main.go @@ -10,10 +10,7 @@ import ( func CobraRunE(cmd *cobra.Command, args []string) error { if SetForeground { - conf, err := warewulfconf.New() - if err != nil { - return errors.Wrap(err, "Could not read Warewulf configuration file") - } + conf := warewulfconf.New() conf.Warewulf.Syslog = false return errors.Wrap(warewulfd.RunServer(), "failed to start Warewulf server") } else { diff --git a/internal/pkg/api/node/node.go b/internal/pkg/api/node/node.go index 47cc4c0b..69ad38ff 100644 --- a/internal/pkg/api/node/node.go +++ b/internal/pkg/api/node/node.go @@ -290,11 +290,7 @@ func NodeStatus(nodeNames []string) (nodeStatusResponse *wwapiv1.NodeStatusRespo Nodes map[string]*nodeStatusInternal `json:"nodes"` } - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - return - } + controller := warewulfconf.New() if controller.Ipaddr == "" { err = fmt.Errorf("the Warewulf Server IP Address is not properly configured") diff --git a/internal/pkg/configure/dhcp.go b/internal/pkg/configure/dhcp.go index 356dbefe..4d2f42df 100644 --- a/internal/pkg/configure/dhcp.go +++ b/internal/pkg/configure/dhcp.go @@ -15,13 +15,9 @@ import ( Configures the dhcpd server, when show is set to false, else the dhcp configuration is checked. */ -func Dhcp() error { +func Dhcp() (err error) { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - os.Exit(1) - } + controller := warewulfconf.New() if !controller.Dhcp.Enabled { wwlog.Info("This system is not configured as a Warewulf DHCP controller") @@ -51,5 +47,5 @@ func Dhcp() error { return errors.Wrap(err, "failed to start") } - return nil + return } diff --git a/internal/pkg/configure/nfs.go b/internal/pkg/configure/nfs.go index 5a8f8158..d7e18469 100644 --- a/internal/pkg/configure/nfs.go +++ b/internal/pkg/configure/nfs.go @@ -2,7 +2,6 @@ package configure import ( "fmt" - "os" "github.com/hpcng/warewulf/internal/pkg/overlay" "github.com/hpcng/warewulf/internal/pkg/util" @@ -17,18 +16,11 @@ nfs server. */ func NFS() error { - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - os.Exit(1) - } + controller := warewulfconf.New() if controller.Nfs.Enabled { - if err != nil { - fmt.Println(err) - } if controller.Warewulf.EnableHostOverlay { - err = overlay.BuildHostOverlay() + err := overlay.BuildHostOverlay() if err != nil { wwlog.Warn("host overlay could not be built: %s", err) } diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go index 9e71f67a..808852f2 100644 --- a/internal/pkg/configure/tftp.go +++ b/internal/pkg/configure/tftp.go @@ -13,13 +13,9 @@ import ( func TFTP() error { var tftpdir string = path.Join(buildconfig.TFTPDIR(), "warewulf") - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - return err - } + controller := warewulfconf.New() - err = os.MkdirAll(tftpdir, 0755) + err := os.MkdirAll(tftpdir, 0755) if err != nil { wwlog.Error("%s", err) return err diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index eb8004cf..f02bdedc 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -43,11 +43,7 @@ Initialize an TemplateStruct with the given node.NodeInfo */ func InitStruct(nodeInfo node.NodeInfo) TemplateStruct { var tstruct TemplateStruct - controller, err := warewulfconf.New() - if err != nil { - wwlog.Error("%s", err) - os.Exit(1) - } + controller := warewulfconf.New() nodeDB, err := node.New() if err != nil { wwlog.Error("%s", err) diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index f956bcd0..231749c2 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -11,7 +11,6 @@ import ( "github.com/creasty/defaults" "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/wwlog" - "gopkg.in/yaml.v2" ) @@ -31,91 +30,107 @@ func init() { } } -func New() (ControllerConf, error) { - var ret ControllerConf - var warewulfconf WarewulfConf - var dhpdconf DhcpConf - var tftpconf TftpConf - var nfsConf NfsConf - ret.Warewulf = &warewulfconf - ret.Dhcp = &dhpdconf - ret.Tftp = &tftpconf - ret.Nfs = &nfsConf - err := defaults.Set(&ret) - // ipxe binaries are merged not overwritten, store defaults separate - defIpxe := make(map[string]string) - for k, v := range ret.Tftp.IpxeBinaries { - defIpxe[k] = v - delete(ret.Tftp.IpxeBinaries, k) - } - if err != nil { - wwlog.Error("Could initialize default variables") - return ret, err - } - // Check if cached config is old before re-reading config file +/* +Creates a new empty ControllerConf object, returns a cached +one if called in a nother context. +*/ +func New() (ret ControllerConf) { + // NOTE: This function can be called before any log level is set + // so using wwlog.Verbose or wwlog.Debug won't work if !cachedConf.current { - wwlog.Debug("Opening Warewulf configuration file: %s", ConfigFile) - data, err := os.ReadFile(ConfigFile) + ret.Warewulf = new(WarewulfConf) + ret.Dhcp = new(DhcpConf) + ret.Tftp = new(TftpConf) + ret.Nfs = new(NfsConf) + err := defaults.Set(&ret) if err != nil { - wwlog.Warn("Error reading Warewulf configuration file, falling back on defaults") + ret.setDynamicDefaults() } - wwlog.Debug("Unmarshaling the Warewulf configuration") - err = yaml.Unmarshal(data, &ret) - if err != nil { - return ret, err - } - if len(ret.Tftp.IpxeBinaries) == 0 { - ret.Tftp.IpxeBinaries = defIpxe - } - if ret.Ipaddr == "" || ret.Netmask == "" { - conn, error := net.Dial("udp", "8.8.8.8:80") - if error != nil { - return ret, err - } - defer conn.Close() - localIp := conn.LocalAddr().(*net.UDPAddr) - if ret.Ipaddr == "" { - ret.Ipaddr = localIp.IP.String() - wwlog.Verbose("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr) - } - if ret.Netmask == "" { - mask := localIp.IP.DefaultMask() - ret.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) - wwlog.Verbose("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask) - } - } - - if ret.Network == "" { - mask := net.IPMask(net.ParseIP(ret.Netmask).To4()) - size, _ := mask.Size() - - sub := ipsubnet.SubnetCalculator(ret.Ipaddr, size) - - ret.Network = sub.GetNetworkPortion() - } - // check validity of ipv6 net - if ret.Ipaddr6 != "" { - _, ipv6net, err := net.ParseCIDR(ret.Ipaddr6) - if err != nil { - wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", ret.Ipaddr6) - return ret, errors.New("invalid ipv6 network") - } - if msize, _ := ipv6net.Mask.Size(); msize > 64 { - wwlog.Error("ipv6 mask size must be smaller than 64") - return ret, errors.New("invalid ipv6 network size") - } - } - - wwlog.Debug("Returning warewulf config object") cachedConf = ret cachedConf.current = true } else { - wwlog.Debug("Returning cached warewulf config object") // If cached struct isn't empty, use it as the return value ret = cachedConf } - - return ret, nil + return ret +} + +/* +Populate the configuration with the values from the configuration file. +*/ +func (conf *ControllerConf) ReadConf(confFileName string) (err error) { + fileHandle, err := os.ReadFile(confFileName) + if err != nil { + return err + } + return conf.Read(fileHandle) +} + +/* +Populate the configuration with the values from the given yaml information +*/ +func (conf *ControllerConf) Read(data []byte) (err error) { + // ipxe binaries are merged not overwritten, store defaults separate + defIpxe := make(map[string]string) + for k, v := range conf.Tftp.IpxeBinaries { + defIpxe[k] = v + delete(conf.Tftp.IpxeBinaries, k) + } + err = yaml.Unmarshal(data, &conf) + if err != nil { + return + } + if len(conf.Tftp.IpxeBinaries) == 0 { + conf.Tftp.IpxeBinaries = defIpxe + } + cachedConf = *conf + cachedConf.current = true + return +} + +/* +Set the runtime defaults like IP address of running system to the config +*/ +func (ret *ControllerConf) setDynamicDefaults() (err error) { + if ret.Ipaddr == "" || ret.Netmask == "" { + conn, error := net.Dial("udp", "8.8.8.8:80") + if error != nil { + return err + } + defer conn.Close() + localIp := conn.LocalAddr().(*net.UDPAddr) + if ret.Ipaddr == "" { + ret.Ipaddr = localIp.IP.String() + wwlog.Verbose("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr) + } + if ret.Netmask == "" { + mask := localIp.IP.DefaultMask() + ret.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) + wwlog.Verbose("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask) + } + } + + if ret.Network == "" { + mask := net.IPMask(net.ParseIP(ret.Netmask).To4()) + size, _ := mask.Size() + + sub := ipsubnet.SubnetCalculator(ret.Ipaddr, size) + + ret.Network = sub.GetNetworkPortion() + } + // check validity of ipv6 net + if ret.Ipaddr6 != "" { + _, ipv6net, err := net.ParseCIDR(ret.Ipaddr6) + if err != nil { + wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", ret.Ipaddr6) + return errors.New("invalid ipv6 network") + } + if msize, _ := ipv6net.Mask.Size(); msize > 64 { + wwlog.Error("ipv6 mask size must be smaller than 64") + return errors.New("invalid ipv6 network size") + } + } + return } diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index 38443883..ad0921a1 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -2,7 +2,6 @@ package warewulfconf import ( "github.com/creasty/defaults" - "github.com/hpcng/warewulf/internal/pkg/wwlog" ) type ControllerConf struct { @@ -78,15 +77,9 @@ func (s *NfsConf) Unmarshal(unmarshal func(interface{}) error) error { return nil } -func init() { - _, err := New() - if err != nil { - wwlog.Warn("Could not get any Warewulf configuration: %s", err) - } -} - // Waste processor cycles to make code more readable func DataStore() string { + _ = New() return cachedConf.Warewulf.DataStore } diff --git a/internal/pkg/warewulfd/daemon.go b/internal/pkg/warewulfd/daemon.go index 2ed57ed4..99407d23 100644 --- a/internal/pkg/warewulfd/daemon.go +++ b/internal/pkg/warewulfd/daemon.go @@ -44,10 +44,7 @@ func DaemonInitLogging() error { wwlog.SetLogLevel(wwlog.SERV) } - conf, err := warewulfconf.New() - if err != nil { - return errors.Wrap(err, "Could not read Warewulf configuration file") - } + conf := warewulfconf.New() if conf.Warewulf.Syslog { diff --git a/internal/pkg/warewulfd/provision.go b/internal/pkg/warewulfd/provision.go index a2abe4dd..67d23ac1 100644 --- a/internal/pkg/warewulfd/provision.go +++ b/internal/pkg/warewulfd/provision.go @@ -31,12 +31,7 @@ type iPxeTemplate struct { } func ProvisionSend(w http.ResponseWriter, req *http.Request) { - conf, err := warewulfconf.New() - if err != nil { - wwlog.Error("Could not open Warewulf configuration: %s", err) - w.WriteHeader(http.StatusServiceUnavailable) - return - } + conf := warewulfconf.New() rinfo, err := parseReq(req) if err != nil { @@ -45,7 +40,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { return } - wwlog.Recv("hwaddr: %s, ipaddr: %s, stage: %s", rinfo.hwaddr, req.RemoteAddr, rinfo.stage ) + wwlog.Recv("hwaddr: %s, ipaddr: %s, stage: %s", rinfo.hwaddr, req.RemoteAddr, rinfo.stage) if rinfo.stage == "runtime" && conf.Warewulf.Secure { if rinfo.remoteport >= 1024 { @@ -56,11 +51,11 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { } status_stages := map[string]string{ - "ipxe": "IPXE", - "kernel": "KERNEL", - "kmods": "KMODS_OVERLAY", - "system": "SYSTEM_OVERLAY", - "runtime": "RUNTIME_OVERLAY" } + "ipxe": "IPXE", + "kernel": "KERNEL", + "kmods": "KMODS_OVERLAY", + "system": "SYSTEM_OVERLAY", + "runtime": "RUNTIME_OVERLAY"} status_stage := status_stages[rinfo.stage] var stage_overlays []string @@ -87,24 +82,24 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { if rinfo.stage == "ipxe" { stage_file = path.Join(buildconfig.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe") tmpl_data = iPxeTemplate{ - Hwaddr : rinfo.hwaddr } + Hwaddr: rinfo.hwaddr} } - }else if rinfo.stage == "ipxe" { + } else if rinfo.stage == "ipxe" { stage_file = path.Join(buildconfig.SYSCONFDIR(), "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe") tmpl_data = iPxeTemplate{ - Id : node.Id.Get(), - Cluster : node.ClusterName.Get(), - Fqdn : node.Id.Get(), - Ipaddr : conf.Ipaddr, - Port : strconv.Itoa(conf.Warewulf.Port), - Hostname : node.Id.Get(), - Hwaddr : rinfo.hwaddr, - ContainerName : node.ContainerName.Get(), - KernelArgs : node.Kernel.Args.Get(), - KernelOverride : node.Kernel.Override.Get() } + Id: node.Id.Get(), + Cluster: node.ClusterName.Get(), + Fqdn: node.Id.Get(), + Ipaddr: conf.Ipaddr, + Port: strconv.Itoa(conf.Warewulf.Port), + Hostname: node.Id.Get(), + Hwaddr: rinfo.hwaddr, + ContainerName: node.ContainerName.Get(), + KernelArgs: node.Kernel.Args.Get(), + KernelOverride: node.Kernel.Override.Get()} - }else if rinfo.stage == "kernel" { + } else if rinfo.stage == "kernel" { if node.Kernel.Override.Defined() { stage_file = kernel.KernelImage(node.Kernel.Override.Get()) } else if node.ContainerName.Defined() { @@ -117,28 +112,28 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { wwlog.Warn("No kernel version set for node %s", node.Id.Get()) } - }else if rinfo.stage == "kmods" { + } else if rinfo.stage == "kmods" { if node.Kernel.Override.Defined() { stage_file = kernel.KmodsImage(node.Kernel.Override.Get()) - }else{ + } else { wwlog.Warn("No kernel override modules set for node %s", node.Id.Get()) } - }else if rinfo.stage == "container" { + } else if rinfo.stage == "container" { if node.ContainerName.Defined() { stage_file = container.ImageFile(node.ContainerName.Get()) } else { wwlog.Warn("No container set for node %s", node.Id.Get()) } - }else if rinfo.stage == "system" { + } else if rinfo.stage == "system" { if len(node.SystemOverlay.GetSlice()) != 0 { stage_overlays = node.SystemOverlay.GetSlice() } else { wwlog.Warn("No system overlay set for node %s", node.Id.Get()) } - }else if rinfo.stage == "runtime" { + } else if rinfo.stage == "runtime" { if rinfo.overlay != "" { stage_overlays = []string{rinfo.overlay} } else if len(node.RuntimeOverlay.GetSlice()) != 0 { @@ -153,7 +148,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { stage_file, err = getOverlayFile( node.Id.Get(), stage_overlays, - conf.Warewulf.AutobuildOverlays ) + conf.Warewulf.AutobuildOverlays) if err != nil { w.WriteHeader(http.StatusInternalServerError) @@ -162,7 +157,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { } } - wwlog.Serv("stage_file '%s'", stage_file ) + wwlog.Serv("stage_file '%s'", stage_file) if util.IsFile(stage_file) { @@ -200,7 +195,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { wwlog.Send("%15s: %s", node.Id.Get(), stage_file) - }else{ + } else { if rinfo.compress == "gz" { stage_file += ".gz" @@ -210,7 +205,7 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { w.WriteHeader(http.StatusNotFound) return } - }else if rinfo.compress != "" { + } else if rinfo.compress != "" { wwlog.Error("unsupported %s compressed version of file %s", rinfo.compress, stage_file) w.WriteHeader(http.StatusNotFound) @@ -225,14 +220,14 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { updateStatus(node.Id.Get(), status_stage, path.Base(stage_file), rinfo.ipaddr) - }else if stage_file == "" { + } else if stage_file == "" { w.WriteHeader(http.StatusBadRequest) wwlog.Error("No resource selected") updateStatus(node.Id.Get(), status_stage, "BAD_REQUEST", rinfo.ipaddr) - }else{ + } else { w.WriteHeader(http.StatusNotFound) - wwlog.Error("Not found: %s", stage_file ) + wwlog.Error("Not found: %s", stage_file) updateStatus(node.Id.Get(), status_stage, "NOT_FOUND", rinfo.ipaddr) } diff --git a/internal/pkg/warewulfd/warewulfd.go b/internal/pkg/warewulfd/warewulfd.go index 5ecf48b6..d69aa210 100644 --- a/internal/pkg/warewulfd/warewulfd.go +++ b/internal/pkg/warewulfd/warewulfd.go @@ -58,10 +58,7 @@ func RunServer() error { http.HandleFunc("/overlay-runtime/", ProvisionSend) http.HandleFunc("/status", StatusSend) - conf, err := warewulfconf.New() - if err != nil { - return errors.Wrap(err, "could not get Warewulf configuration") - } + conf := warewulfconf.New() daemonPort := conf.Warewulf.Port wwlog.Serv("Starting HTTPD REST service on port %d", daemonPort) From 32b4bb74cc62d7828bedd8e6e3e37f097450f402 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 3 Mar 2023 14:07:26 +0100 Subject: [PATCH 07/22] added `wwctl genconfig warewulfconf print` Signed-off-by: Christian Goll --- cmd/config_defaults/config_defaults.go | 26 ------------------ internal/app/wwctl/genconf/root.go | 2 ++ .../wwctl/genconf/warewulfconf/print/main.go | 19 +++++++++++++ .../wwctl/genconf/warewulfconf/print/root.go | 22 +++++++++++++++ .../app/wwctl/genconf/warewulfconf/root.go | 27 +++++++++++++++++++ internal/pkg/warewulfconf/datastructure.go | 2 +- 6 files changed, 71 insertions(+), 27 deletions(-) delete mode 100644 cmd/config_defaults/config_defaults.go create mode 100644 internal/app/wwctl/genconf/warewulfconf/print/main.go create mode 100644 internal/app/wwctl/genconf/warewulfconf/print/root.go create mode 100644 internal/app/wwctl/genconf/warewulfconf/root.go diff --git a/cmd/config_defaults/config_defaults.go b/cmd/config_defaults/config_defaults.go deleted file mode 100644 index 70068c90..00000000 --- a/cmd/config_defaults/config_defaults.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -// Regenerates the default configuration files -// Keeps the current content and adds missing default values -// Won't create a new file, but will update a blank file - -//TODO: Add nodes.conf - -import ( - "fmt" - "github.com/hpcng/warewulf/internal/pkg/warewulfconf" -) - -func main() { - tmpConf, err := warewulfconf.New() - if err != nil { - fmt.Println(err) - return - } - - err = tmpConf.Persist() - if err != nil { - fmt.Println(err) - return - } -} diff --git a/internal/app/wwctl/genconf/root.go b/internal/app/wwctl/genconf/root.go index 5f9a8a4b..1a979be4 100644 --- a/internal/app/wwctl/genconf/root.go +++ b/internal/app/wwctl/genconf/root.go @@ -5,6 +5,7 @@ import ( "github.com/hpcng/warewulf/internal/app/wwctl/genconf/dfaults" "github.com/hpcng/warewulf/internal/app/wwctl/genconf/man" "github.com/hpcng/warewulf/internal/app/wwctl/genconf/reference" + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/warewulfconf" "github.com/spf13/cobra" ) @@ -25,6 +26,7 @@ func init() { baseCmd.AddCommand(man.GetCommand()) baseCmd.AddCommand(reference.GetCommand()) baseCmd.AddCommand(dfaults.GetCommand()) + baseCmd.AddCommand(warewulfconf.GetCommand()) } // GetRootCommand returns the root cobra.Command for the application. diff --git a/internal/app/wwctl/genconf/warewulfconf/print/main.go b/internal/app/wwctl/genconf/warewulfconf/print/main.go new file mode 100644 index 00000000..2efca477 --- /dev/null +++ b/internal/app/wwctl/genconf/warewulfconf/print/main.go @@ -0,0 +1,19 @@ +package print + +import ( + "fmt" + + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/spf13/cobra" + "gopkg.in/yaml.v2" +) + +func CobraRunE(cmd *cobra.Command, args []string) (err error) { + conf := warewulfconf.New() + buffer, err := yaml.Marshal(&conf) + if err != nil { + return + } + fmt.Println(string(buffer)) + return +} diff --git a/internal/app/wwctl/genconf/warewulfconf/print/root.go b/internal/app/wwctl/genconf/warewulfconf/print/root.go new file mode 100644 index 00000000..8bd53f6f --- /dev/null +++ b/internal/app/wwctl/genconf/warewulfconf/print/root.go @@ -0,0 +1,22 @@ +package print + +import ( + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "print", + Short: "print wareweulf.conf", + Long: "This command prints the actual used warewulf.conf, can be used to create an empty valid warewulf.conf", + RunE: CobraRunE, + Args: cobra.ExactArgs(0), + } +) + +func init() { +} + +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/app/wwctl/genconf/warewulfconf/root.go b/internal/app/wwctl/genconf/warewulfconf/root.go new file mode 100644 index 00000000..856c2f70 --- /dev/null +++ b/internal/app/wwctl/genconf/warewulfconf/root.go @@ -0,0 +1,27 @@ +package warewulfconf + +import ( + "github.com/hpcng/warewulf/internal/app/wwctl/genconf/warewulfconf/print" + "github.com/spf13/cobra" +) + +var ( + baseCmd = &cobra.Command{ + Use: "warewulfconf", + Short: "access warewulf.conf", + Long: "Commands for accessing the actual used warewulf.conf", + Args: cobra.ExactArgs(0), + Aliases: []string{"cnf"}, + } + ListFull bool + WWctlRoot *cobra.Command +) + +func init() { + baseCmd.AddCommand(print.GetCommand()) +} + +// GetRootCommand returns the root cobra.Command for the application. +func GetCommand() *cobra.Command { + return baseCmd +} diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index ad0921a1..ff12e4cb 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -17,7 +17,7 @@ type ControllerConf struct { Dhcp *DhcpConf `yaml:"dhcp"` Tftp *TftpConf `yaml:"tftp"` Nfs *NfsConf `yaml:"nfs"` - MountsContainer []*MountEntry `yaml:"container mounts"` + MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` current bool } From 377702a1799122521538afba92e4c52841457054 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 3 Mar 2023 16:02:41 +0100 Subject: [PATCH 08/22] make the configuration to be based in warewulf.conf defaults will be se by the Makefile Signed-off-by: Christian Goll --- .gitignore | 1 + Makefile | 8 -- internal/app/wwclient/root.go | 6 +- internal/pkg/buildconfig/defaults.go | 98 --------------------- internal/pkg/buildconfig/setconfigs.go.in | 19 ---- internal/pkg/configure/ssh.go | 8 +- internal/pkg/configure/tftp.go | 5 +- internal/pkg/container/config.go | 8 +- internal/pkg/kernel/kernel.go | 5 +- internal/pkg/node/constructors.go | 7 +- internal/pkg/overlay/config.go | 8 +- internal/pkg/overlay/funcmap.go | 8 +- internal/pkg/version/version.go | 5 +- internal/pkg/warewulfconf/buildconfig.go.in | 18 ++++ internal/pkg/warewulfconf/constructors.go | 21 +---- internal/pkg/warewulfconf/datastructure.go | 1 + internal/pkg/warewulfconf/getter.go | 73 +++++++++++++++ internal/pkg/warewulfd/provision.go | 5 +- 18 files changed, 130 insertions(+), 174 deletions(-) delete mode 100644 internal/pkg/buildconfig/defaults.go delete mode 100644 internal/pkg/buildconfig/setconfigs.go.in create mode 100644 internal/pkg/warewulfconf/buildconfig.go.in create mode 100644 internal/pkg/warewulfconf/getter.go diff --git a/.gitignore b/.gitignore index 10a7f077..18b9454f 100644 --- a/.gitignore +++ b/.gitignore @@ -25,6 +25,7 @@ /etc/bash_completion.d/ warewulf.spec internal/pkg/buildconfig/setconfigs.go +internal/pkg/warewulfconf/buildconfig.go include/systemd/warewulfd.service _dist/ config diff --git a/Makefile b/Makefile index 9fdbc02b..f1d08c92 100644 --- a/Makefile +++ b/Makefile @@ -231,19 +231,11 @@ man_pages: wwctl cp docs/man/man5/*.5 ./man_pages/ cd man_pages; for i in wwctl*1 *.5; do echo "Compressing manpage: $$i"; gzip --force $$i; done -config_defaults: vendor cmd/config_defaults/config_defaults.go - cd cmd/config_defaults && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ - -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ - -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../config_defaults - update_configuration: vendor cmd/update_configuration/update_configuration.go cd cmd/update_configuration && go build -ldflags="-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=./etc/warewulf.conf'\ -X 'github.com/hpcng/warewulf/internal/pkg/node.ConfigFile=./etc/nodes.conf'"\ -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../update_configuration -warewulfconf: config_defaults - ./config_defaults - dist: vendor config rm -rf .dist/$(WAREWULF)-$(VERSION) $(WAREWULF)-$(VERSION).tar.gz mkdir -p .dist/$(WAREWULF)-$(VERSION) diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index dc06e684..e657c21b 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -16,7 +16,6 @@ import ( "github.com/coreos/go-systemd/daemon" "github.com/google/uuid" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/pidfile" "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" @@ -50,10 +49,7 @@ func GetRootCommand() *cobra.Command { } func CobraRunE(cmd *cobra.Command, args []string) error { - conf, err := warewulfconf.New() - if err != nil { - return err - } + conf := warewulfconf.New() pid, err := pidfile.Write(PIDFile) if err != nil && pid == -1 { diff --git a/internal/pkg/buildconfig/defaults.go b/internal/pkg/buildconfig/defaults.go deleted file mode 100644 index f739cff1..00000000 --- a/internal/pkg/buildconfig/defaults.go +++ /dev/null @@ -1,98 +0,0 @@ -package buildconfig - -import "github.com/hpcng/warewulf/internal/pkg/wwlog" - -const WWVer = 43 - -var ( - bindir string = "UNDEF" - sysconfdir string = "UNDEF" - localstatedir string = "UNDEF" - srvdir string = "UNDEF" - tftpdir string = "UNDEF" - firewallddir string = "UNDEF" - systemddir string = "UNDEF" - wwoverlaydir string = "UNDEF" - wwchrootdir string = "UNDEF" - wwprovisiondir string = "UNDEF" - version string = "UNDEF" - release string = "UNDEF" - wwclientdir string = "UNDEF" - datadir string = "UNDEF" - tmpdir string = "UNDEF" -) - -func BINDIR() string { - wwlog.Debug("BINDIR = '%s'", bindir) - return bindir -} - -func DATADIR() string { - wwlog.Debug("DATADIR = '%s'", datadir) - return datadir -} - -func SYSCONFDIR() string { - wwlog.Debug("SYSCONFDIR = '%s'", sysconfdir) - return sysconfdir -} - -func LOCALSTATEDIR() string { - wwlog.Debug("LOCALSTATEDIR = '%s'", localstatedir) - return localstatedir -} - -func SRVDIR() string { - wwlog.Debug("SRVDIR = '%s'", srvdir) - return srvdir -} - -func TFTPDIR() string { - wwlog.Debug("TFTPDIR = '%s'", tftpdir) - return tftpdir -} - -func FIREWALLDDIR() string { - wwlog.Debug("FIREWALLDDIR = '%s'", firewallddir) - return firewallddir -} - -func SYSTEMDDIR() string { - wwlog.Debug("SYSTEMDDIR = '%s'", systemddir) - return systemddir -} - -func WWOVERLAYDIR() string { - wwlog.Debug("WWOVERLAYDIR = '%s'", wwoverlaydir) - return wwoverlaydir -} - -func WWCHROOTDIR() string { - wwlog.Debug("WWCHROOTDIR = '%s'", wwchrootdir) - return wwchrootdir -} - -func WWPROVISIONDIR() string { - wwlog.Debug("WWPROVISIONDIR = '%s'", wwprovisiondir) - return wwprovisiondir -} - -func VERSION() string { - wwlog.Debug("VERSION = '%s'", version) - return version -} - -func RELEASE() string { - wwlog.Debug("RELEASE = '%s'", release) - return release -} - -func WWCLIENTDIR() string { - wwlog.Debug("WWCLIENTDIR = '%s'", wwclientdir) - return wwclientdir -} - -func TMPDIR() string { - wwlog.Debug("TMPDIR = '%s'", tmpdir) - return tmpdir -} diff --git a/internal/pkg/buildconfig/setconfigs.go.in b/internal/pkg/buildconfig/setconfigs.go.in deleted file mode 100644 index f049ffeb..00000000 --- a/internal/pkg/buildconfig/setconfigs.go.in +++ /dev/null @@ -1,19 +0,0 @@ -package buildconfig - -func init() { - bindir = "@BINDIR@" - sysconfdir = "@SYSCONFDIR@" - datadir = "@DATADIR@" - localstatedir = "@LOCALSTATEDIR@" - srvdir = "@SRVDIR@" - tftpdir = "@TFTPDIR@" - firewallddir = "@FIREWALLDDIR@" - systemddir = "@SYSTEMDDIR@" - wwoverlaydir = "@WWOVERLAYDIR@" - wwchrootdir = "@WWCHROOTDIR@" - wwprovisiondir = "@WWPROVISIONDIR@" - version = "@VERSION@" - release = "@RELEASE@" - wwclientdir = "@WWCLIENTDIR@" - tmpdir = "@TMPDIR@" -} diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go index c4b5e04f..0c60e053 100644 --- a/internal/pkg/configure/ssh.go +++ b/internal/pkg/configure/ssh.go @@ -5,8 +5,8 @@ import ( "os" "path" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" "github.com/pkg/errors" ) @@ -14,10 +14,10 @@ import ( func SSH() error { if os.Getuid() == 0 { fmt.Printf("Updating system keys\n") + conf := warewulfconf.New() + wwkeydir := path.Join(conf.SYSCONFDIR(), "warewulf/keys") + "/" - wwkeydir := path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys") + "/" - - err := os.MkdirAll(path.Join(buildconfig.SYSCONFDIR(), "warewulf/keys"), 0755) + err := os.MkdirAll(path.Join(conf.SYSCONFDIR(), "warewulf/keys"), 0755) if err != nil { wwlog.Error("Could not create base directory: %s", err) os.Exit(1) diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go index 808852f2..718a4030 100644 --- a/internal/pkg/configure/tftp.go +++ b/internal/pkg/configure/tftp.go @@ -5,15 +5,14 @@ import ( "os" "path" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/util" "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) func TFTP() error { - var tftpdir string = path.Join(buildconfig.TFTPDIR(), "warewulf") controller := warewulfconf.New() + var tftpdir string = path.Join(controller.TFTPDIR(), "warewulf") err := os.MkdirAll(tftpdir, 0755) if err != nil { @@ -28,7 +27,7 @@ func TFTP() error { continue } copyCheck[f] = true - err = util.SafeCopyFile(path.Join(buildconfig.DATADIR(), f), path.Join(tftpdir, f)) + err = util.SafeCopyFile(path.Join(controller.DATADIR(), f), path.Join(tftpdir, f)) if err != nil { wwlog.Warn("ipxe binary could not be copied, booting may not work: %s", err) } diff --git a/internal/pkg/container/config.go b/internal/pkg/container/config.go index 1faf7423..ebbc8569 100644 --- a/internal/pkg/container/config.go +++ b/internal/pkg/container/config.go @@ -3,11 +3,12 @@ package container import ( "path" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" ) func SourceParentDir() string { - return buildconfig.WWCHROOTDIR() + conf := warewulfconf.New() + return conf.WWCHROOTDIR() } func SourceDir(name string) string { @@ -19,7 +20,8 @@ func RootFsDir(name string) string { } func ImageParentDir() string { - return path.Join(buildconfig.WWPROVISIONDIR(), "container/") + conf := warewulfconf.New() + return path.Join(conf.WWPROVISIONDIR(), "container/") } func ImageFile(name string) string { diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 9983572e..14ce78a2 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -11,8 +11,8 @@ import ( "github.com/pkg/errors" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) @@ -28,7 +28,8 @@ var ( ) func KernelImageTopDir() string { - return path.Join(buildconfig.WWPROVISIONDIR(), "kernel") + conf := warewulfconf.New() + return path.Join(conf.WWPROVISIONDIR(), "kernel") } func KernelImage(kernelName string) string { diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index d69bdf74..3d83f8df 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -7,7 +7,7 @@ import ( "sort" "strings" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" "gopkg.in/yaml.v2" @@ -37,11 +37,12 @@ defaultnode: netmask: 255.255.255.0` func init() { + conf := warewulfconf.New() if ConfigFile == "" { - ConfigFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/nodes.conf") + ConfigFile = path.Join(conf.SYSCONFDIR(), "warewulf/nodes.conf") } if DefaultConfig == "" { - DefaultConfig = path.Join(buildconfig.SYSCONFDIR(), "warewulf/defaults.conf") + DefaultConfig = path.Join(conf.SYSCONFDIR(), "warewulf/defaults.conf") } } diff --git a/internal/pkg/overlay/config.go b/internal/pkg/overlay/config.go index c9b80306..3f5b1bd4 100644 --- a/internal/pkg/overlay/config.go +++ b/internal/pkg/overlay/config.go @@ -5,11 +5,12 @@ import ( "path" "strings" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" ) func OverlaySourceTopDir() string { - return buildconfig.WWOVERLAYDIR() + conf := warewulfconf.New() + return conf.WWOVERLAYDIR() } /* @@ -30,5 +31,6 @@ func OverlaySourceDir(overlayName string) string { Returns the overlay name of the image for a given node */ func OverlayImage(nodeName string, overlayName []string) string { - return path.Join(buildconfig.WWPROVISIONDIR(), "overlays/", nodeName, strings.Join(overlayName, "-")+".img") + conf := warewulfconf.New() + return path.Join(conf.WWPROVISIONDIR(), "overlays/", nodeName, strings.Join(overlayName, "-")+".img") } diff --git a/internal/pkg/overlay/funcmap.go b/internal/pkg/overlay/funcmap.go index 49b50d3d..d3fe05e5 100644 --- a/internal/pkg/overlay/funcmap.go +++ b/internal/pkg/overlay/funcmap.go @@ -6,9 +6,9 @@ import ( "path" "strings" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/util" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "github.com/hpcng/warewulf/internal/pkg/wwlog" ) @@ -18,8 +18,9 @@ the path is relative to SYSCONFDIR. Templates in the file are no evaluated. */ func templateFileInclude(inc string) string { + conf := warewulfconf.New() if !strings.HasPrefix(inc, "/") { - inc = path.Join(buildconfig.SYSCONFDIR(), "warewulf", inc) + inc = path.Join(conf.SYSCONFDIR(), "warewulf", inc) } wwlog.Debug("Including file into template: %s", inc) content, err := os.ReadFile(inc) @@ -35,8 +36,9 @@ is the file to read, the second the abort string Templates in the file are no evaluated. */ func templateFileBlock(inc string, abortStr string) (string, error) { + conf := warewulfconf.New() if !strings.HasPrefix(inc, "/") { - inc = path.Join(buildconfig.SYSCONFDIR(), "warewulf", inc) + inc = path.Join(conf.SYSCONFDIR(), "warewulf", inc) } wwlog.Debug("Including file block into template: %s", inc) readFile, err := os.Open(inc) diff --git a/internal/pkg/version/version.go b/internal/pkg/version/version.go index f77050f4..5ce00f23 100644 --- a/internal/pkg/version/version.go +++ b/internal/pkg/version/version.go @@ -4,14 +4,15 @@ import ( "fmt" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" ) /* Return the version of wwctl */ func GetVersion() string { - return fmt.Sprintf("%s-%s", buildconfig.VERSION(), buildconfig.RELEASE()) + conf := warewulfconf.New() + return fmt.Sprintf("%s-%s", conf.VERSION(), conf.RELEASE()) } /* diff --git a/internal/pkg/warewulfconf/buildconfig.go.in b/internal/pkg/warewulfconf/buildconfig.go.in new file mode 100644 index 00000000..7bdf96e1 --- /dev/null +++ b/internal/pkg/warewulfconf/buildconfig.go.in @@ -0,0 +1,18 @@ +package warewulfconf + +type BuildConfig struct { + bindir string `default:"@BINDIR@"` + sysconfdir string `default:"@SYSCONFDIR@"` + datadir string `default:"@DATADIR@"` + localstatedir string `default:"@LOCALSTATEDIR@"` + srvdir string `default:"@SRVDIR@"` + tftpdir string `default:"@TFTPDIR@"` + firewallddir string `default:"@FIREWALLDDIR@"` + systemddir string `default:"@SYSTEMDDIR@"` + wwoverlaydir string `default:"@WWOVERLAYDIR@"` + wwchrootdir string `default:"@WWCHROOTDIR@"` + wwprovisiondir string `default:"@WWPROVISIONDIR@"` + version string `default:"@VERSION@"` + release string `default:"@RELEASE@"` + wwclientdir string `default:"@WWCLIENTDIR@"` +} diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index 231749c2..0b01e760 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -5,11 +5,9 @@ import ( "fmt" "net" "os" - "path" "github.com/brotherpowers/ipsubnet" "github.com/creasty/defaults" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/wwlog" "gopkg.in/yaml.v2" ) @@ -18,18 +16,6 @@ var cachedConf ControllerConf var ConfigFile string -/* -Get the configFile location from the os.ev if set -*/ -func init() { - if ConfigFile == "" { - ConfigFile = os.Getenv("WARWULFCONF") - } - if ConfigFile == "" { - ConfigFile = path.Join(buildconfig.SYSCONFDIR(), "warewulf/warewulf.conf") - } -} - /* Creates a new empty ControllerConf object, returns a cached one if called in a nother context. @@ -42,10 +28,9 @@ func New() (ret ControllerConf) { ret.Dhcp = new(DhcpConf) ret.Tftp = new(TftpConf) ret.Nfs = new(NfsConf) - err := defaults.Set(&ret) - if err != nil { - ret.setDynamicDefaults() - } + ret.Paths = new(BuildConfig) + _ = defaults.Set(&ret) + ret.setDynamicDefaults() cachedConf = ret cachedConf.current = true diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index ff12e4cb..33d77fe2 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -18,6 +18,7 @@ type ControllerConf struct { Tftp *TftpConf `yaml:"tftp"` Nfs *NfsConf `yaml:"nfs"` MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` + Paths *BuildConfig `yaml:"mypaths"` current bool } diff --git a/internal/pkg/warewulfconf/getter.go b/internal/pkg/warewulfconf/getter.go new file mode 100644 index 00000000..6a3f5a01 --- /dev/null +++ b/internal/pkg/warewulfconf/getter.go @@ -0,0 +1,73 @@ +package warewulfconf + +import "github.com/hpcng/warewulf/internal/pkg/wwlog" + +func (conf *ControllerConf) BINDIR() string { + wwlog.Debug("BINDIR = '%s'", conf.Paths.bindir) + return conf.Paths.bindir +} + +func (conf *ControllerConf) DATADIR() string { + wwlog.Debug("DATADIR = '%s'", conf.Paths.datadir) + return conf.Paths.datadir +} + +func (conf *ControllerConf) SYSCONFDIR() string { + wwlog.Debug("SYSCONFDIR = '%s'", conf.Paths.sysconfdir) + return conf.Paths.sysconfdir +} + +func (conf *ControllerConf) LOCALSTATEDIR() string { + wwlog.Debug("LOCALSTATEDIR = '%s'", conf.Paths.localstatedir) + return conf.Paths.localstatedir +} + +func (conf *ControllerConf) SRVDIR() string { + wwlog.Debug("SRVDIR = '%s'", conf.Paths.srvdir) + return conf.Paths.srvdir +} + +func (conf *ControllerConf) TFTPDIR() string { + wwlog.Debug("TFTPDIR = '%s'", conf.Paths.tftpdir) + return conf.Paths.tftpdir +} + +func (conf *ControllerConf) FIREWALLDDIR() string { + wwlog.Debug("FIREWALLDDIR = '%s'", conf.Paths.firewallddir) + return conf.Paths.firewallddir +} + +func (conf *ControllerConf) SYSTEMDDIR() string { + wwlog.Debug("SYSTEMDDIR = '%s'", conf.Paths.systemddir) + return conf.Paths.systemddir +} + +func (conf *ControllerConf) WWOVERLAYDIR() string { + wwlog.Debug("WWOVERLAYDIR = '%s'", conf.Paths.wwoverlaydir) + return conf.Paths.wwoverlaydir +} + +func (conf *ControllerConf) WWCHROOTDIR() string { + wwlog.Debug("WWCHROOTDIR = '%s'", conf.Paths.wwchrootdir) + return conf.Paths.wwchrootdir +} + +func (conf *ControllerConf) WWPROVISIONDIR() string { + wwlog.Debug("WWPROVISIONDIR = '%s'", conf.Paths.wwprovisiondir) + return conf.Paths.wwprovisiondir +} + +func (conf *ControllerConf) VERSION() string { + wwlog.Debug("VERSION = '%s'", conf.Paths.version) + return conf.Paths.version +} + +func (conf *ControllerConf) RELEASE() string { + wwlog.Debug("RELEASE = '%s'", conf.Paths.release) + return conf.Paths.release +} + +func (conf *ControllerConf) WWCLIENTDIR() string { + wwlog.Debug("WWCLIENTDIR = '%s'", conf.Paths.wwclientdir) + return conf.Paths.wwclientdir +} diff --git a/internal/pkg/warewulfd/provision.go b/internal/pkg/warewulfd/provision.go index 67d23ac1..7b96ee6d 100644 --- a/internal/pkg/warewulfd/provision.go +++ b/internal/pkg/warewulfd/provision.go @@ -7,7 +7,6 @@ import ( "strconv" "text/template" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/container" "github.com/hpcng/warewulf/internal/pkg/kernel" "github.com/hpcng/warewulf/internal/pkg/util" @@ -80,13 +79,13 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { if !node.Id.Defined() { wwlog.Error("%s (unknown/unconfigured node)", rinfo.hwaddr) if rinfo.stage == "ipxe" { - stage_file = path.Join(buildconfig.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe") + stage_file = path.Join(conf.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe") tmpl_data = iPxeTemplate{ Hwaddr: rinfo.hwaddr} } } else if rinfo.stage == "ipxe" { - stage_file = path.Join(buildconfig.SYSCONFDIR(), "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe") + stage_file = path.Join(conf.SYSCONFDIR(), "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe") tmpl_data = iPxeTemplate{ Id: node.Id.Get(), Cluster: node.ClusterName.Get(), From ca088d123dde8e39f0c539b0fa01b97c0d48febe Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 3 Mar 2023 16:12:53 +0100 Subject: [PATCH 09/22] paths need to be visibale for marshalling Signed-off-by: Christian Goll --- internal/pkg/overlay/datastructure.go | 1 + internal/pkg/warewulfconf/buildconfig.go.in | 28 +++++------ internal/pkg/warewulfconf/datastructure.go | 2 +- internal/pkg/warewulfconf/getter.go | 56 ++++++++++----------- 4 files changed, 44 insertions(+), 43 deletions(-) diff --git a/internal/pkg/overlay/datastructure.go b/internal/pkg/overlay/datastructure.go index f02bdedc..c7da9a70 100644 --- a/internal/pkg/overlay/datastructure.go +++ b/internal/pkg/overlay/datastructure.go @@ -32,6 +32,7 @@ type TemplateStruct struct { Nfs warewulfconf.NfsConf Warewulf warewulfconf.WarewulfConf Tftp warewulfconf.TftpConf + Paths warewulfconf.BuildConfig AllNodes []node.NodeInfo node.NodeConf // backward compatiblity diff --git a/internal/pkg/warewulfconf/buildconfig.go.in b/internal/pkg/warewulfconf/buildconfig.go.in index 7bdf96e1..3a5a52cd 100644 --- a/internal/pkg/warewulfconf/buildconfig.go.in +++ b/internal/pkg/warewulfconf/buildconfig.go.in @@ -1,18 +1,18 @@ package warewulfconf type BuildConfig struct { - bindir string `default:"@BINDIR@"` - sysconfdir string `default:"@SYSCONFDIR@"` - datadir string `default:"@DATADIR@"` - localstatedir string `default:"@LOCALSTATEDIR@"` - srvdir string `default:"@SRVDIR@"` - tftpdir string `default:"@TFTPDIR@"` - firewallddir string `default:"@FIREWALLDDIR@"` - systemddir string `default:"@SYSTEMDDIR@"` - wwoverlaydir string `default:"@WWOVERLAYDIR@"` - wwchrootdir string `default:"@WWCHROOTDIR@"` - wwprovisiondir string `default:"@WWPROVISIONDIR@"` - version string `default:"@VERSION@"` - release string `default:"@RELEASE@"` - wwclientdir string `default:"@WWCLIENTDIR@"` + Bindir string `default:"@BINDIR@"` + Sysconfdir string `default:"@SYSCONFDIR@"` + Datadir string `default:"@DATADIR@"` + Localstatedir string `default:"@LOCALSTATEDIR@"` + Srvdir string `default:"@SRVDIR@"` + Tftpdir string `default:"@TFTPDIR@"` + Firewallddir string `default:"@FIREWALLDDIR@"` + Systemddir string `default:"@SYSTEMDDIR@"` + Wwoverlaydir string `default:"@WWOVERLAYDIR@"` + Wwchrootdir string `default:"@WWCHROOTDIR@"` + Wwprovisiondir string `default:"@WWPROVISIONDIR@"` + Version string `default:"@VERSION@"` + Release string `default:"@RELEASE@"` + Wwclientdir string `default:"@WWCLIENTDIR@"` } diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index 33d77fe2..4c4ae71b 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -18,7 +18,7 @@ type ControllerConf struct { Tftp *TftpConf `yaml:"tftp"` Nfs *NfsConf `yaml:"nfs"` MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` - Paths *BuildConfig `yaml:"mypaths"` + Paths *BuildConfig `yaml:"paths"` current bool } diff --git a/internal/pkg/warewulfconf/getter.go b/internal/pkg/warewulfconf/getter.go index 6a3f5a01..6d92a2fe 100644 --- a/internal/pkg/warewulfconf/getter.go +++ b/internal/pkg/warewulfconf/getter.go @@ -3,71 +3,71 @@ package warewulfconf import "github.com/hpcng/warewulf/internal/pkg/wwlog" func (conf *ControllerConf) BINDIR() string { - wwlog.Debug("BINDIR = '%s'", conf.Paths.bindir) - return conf.Paths.bindir + wwlog.Debug("BINDIR = '%s'", conf.Paths.Bindir) + return conf.Paths.Bindir } func (conf *ControllerConf) DATADIR() string { - wwlog.Debug("DATADIR = '%s'", conf.Paths.datadir) - return conf.Paths.datadir + wwlog.Debug("DATADIR = '%s'", conf.Paths.Datadir) + return conf.Paths.Datadir } func (conf *ControllerConf) SYSCONFDIR() string { - wwlog.Debug("SYSCONFDIR = '%s'", conf.Paths.sysconfdir) - return conf.Paths.sysconfdir + wwlog.Debug("SYSCONFDIR = '%s'", conf.Paths.Sysconfdir) + return conf.Paths.Sysconfdir } func (conf *ControllerConf) LOCALSTATEDIR() string { - wwlog.Debug("LOCALSTATEDIR = '%s'", conf.Paths.localstatedir) - return conf.Paths.localstatedir + wwlog.Debug("LOCALSTATEDIR = '%s'", conf.Paths.Localstatedir) + return conf.Paths.Localstatedir } func (conf *ControllerConf) SRVDIR() string { - wwlog.Debug("SRVDIR = '%s'", conf.Paths.srvdir) - return conf.Paths.srvdir + wwlog.Debug("SRVDIR = '%s'", conf.Paths.Srvdir) + return conf.Paths.Srvdir } func (conf *ControllerConf) TFTPDIR() string { - wwlog.Debug("TFTPDIR = '%s'", conf.Paths.tftpdir) - return conf.Paths.tftpdir + wwlog.Debug("TFTPDIR = '%s'", conf.Paths.Tftpdir) + return conf.Paths.Tftpdir } func (conf *ControllerConf) FIREWALLDDIR() string { - wwlog.Debug("FIREWALLDDIR = '%s'", conf.Paths.firewallddir) - return conf.Paths.firewallddir + wwlog.Debug("FIREWALLDDIR = '%s'", conf.Paths.Firewallddir) + return conf.Paths.Firewallddir } func (conf *ControllerConf) SYSTEMDDIR() string { - wwlog.Debug("SYSTEMDDIR = '%s'", conf.Paths.systemddir) - return conf.Paths.systemddir + wwlog.Debug("SYSTEMDDIR = '%s'", conf.Paths.Systemddir) + return conf.Paths.Systemddir } func (conf *ControllerConf) WWOVERLAYDIR() string { - wwlog.Debug("WWOVERLAYDIR = '%s'", conf.Paths.wwoverlaydir) - return conf.Paths.wwoverlaydir + wwlog.Debug("WWOVERLAYDIR = '%s'", conf.Paths.Wwoverlaydir) + return conf.Paths.Wwoverlaydir } func (conf *ControllerConf) WWCHROOTDIR() string { - wwlog.Debug("WWCHROOTDIR = '%s'", conf.Paths.wwchrootdir) - return conf.Paths.wwchrootdir + wwlog.Debug("WWCHROOTDIR = '%s'", conf.Paths.Wwchrootdir) + return conf.Paths.Wwchrootdir } func (conf *ControllerConf) WWPROVISIONDIR() string { - wwlog.Debug("WWPROVISIONDIR = '%s'", conf.Paths.wwprovisiondir) - return conf.Paths.wwprovisiondir + wwlog.Debug("WWPROVISIONDIR = '%s'", conf.Paths.Wwprovisiondir) + return conf.Paths.Wwprovisiondir } func (conf *ControllerConf) VERSION() string { - wwlog.Debug("VERSION = '%s'", conf.Paths.version) - return conf.Paths.version + wwlog.Debug("VERSION = '%s'", conf.Paths.Version) + return conf.Paths.Version } func (conf *ControllerConf) RELEASE() string { - wwlog.Debug("RELEASE = '%s'", conf.Paths.release) - return conf.Paths.release + wwlog.Debug("RELEASE = '%s'", conf.Paths.Release) + return conf.Paths.Release } func (conf *ControllerConf) WWCLIENTDIR() string { - wwlog.Debug("WWCLIENTDIR = '%s'", conf.Paths.wwclientdir) - return conf.Paths.wwclientdir + wwlog.Debug("WWCLIENTDIR = '%s'", conf.Paths.Wwclientdir) + return conf.Paths.Wwclientdir } From b55473e1e48639c719e83b15f4493436f9f19c94 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 3 Mar 2023 16:21:44 +0100 Subject: [PATCH 10/22] added new build in vars to rest of binaries Signed-off-by: Christian Goll --- cmd/update_configuration/update_configuration.go | 3 +-- internal/app/api/wwapic/wwapic.go | 5 +++-- internal/app/api/wwapid/wwapid.go | 5 +++-- internal/app/api/wwapird/wwapird.go | 6 +++--- internal/app/wwclient/root.go | 4 ++-- internal/app/wwctl/root.go | 8 ++++---- internal/pkg/warewulfconf/constructors.go | 2 +- 7 files changed, 17 insertions(+), 16 deletions(-) diff --git a/cmd/update_configuration/update_configuration.go b/cmd/update_configuration/update_configuration.go index c64de182..728eaaf6 100644 --- a/cmd/update_configuration/update_configuration.go +++ b/cmd/update_configuration/update_configuration.go @@ -8,7 +8,6 @@ import ( "github.com/hpcng/warewulf/cmd/update_configuration/vers42" "github.com/hpcng/warewulf/cmd/update_configuration/vers43" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/util" "gopkg.in/yaml.v2" ) @@ -125,7 +124,7 @@ func main() { var endVers int var startVers int flag.StringVar(&confFile, "f", "", "Config file for update") - flag.IntVar(&endVers, "e", buildconfig.WWVer, "Final version of configuration file") + flag.IntVar(&endVers, "e", 0, "Final version of configuration file") flag.IntVar(&startVers, "s", 0, "Start version of configuration file, 0 is for autodetection") flag.BoolVar(&nowrite, "n", false, "Do not write, just print new conf to terminal") flag.BoolVar(&quiet, "q", false, "Do not print what the program is doing") diff --git a/internal/app/api/wwapic/wwapic.go b/internal/app/api/wwapic/wwapic.go index 65cd85b5..bd35a973 100644 --- a/internal/app/api/wwapic/wwapic.go +++ b/internal/app/api/wwapic/wwapic.go @@ -12,7 +12,7 @@ import ( "github.com/hpcng/warewulf/internal/pkg/api/apiconfig" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "google.golang.org/grpc" "google.golang.org/grpc/credentials" @@ -24,9 +24,10 @@ import ( func main() { log.Println("Client running") + conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewClient(path.Join(buildconfig.SYSCONFDIR(), "warewulf/wwapic.conf")) + config, err := apiconfig.NewClient(path.Join(conf.SYSCONFDIR(), "warewulf/wwapic.conf")) if err != nil { log.Fatalf("err: %v", err) } diff --git a/internal/app/api/wwapid/wwapid.go b/internal/app/api/wwapid/wwapid.go index 1cea854f..0678114c 100644 --- a/internal/app/api/wwapid/wwapid.go +++ b/internal/app/api/wwapid/wwapid.go @@ -15,8 +15,8 @@ import ( "github.com/hpcng/warewulf/internal/pkg/api/container" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" - "github.com/hpcng/warewulf/internal/pkg/buildconfig" "github.com/hpcng/warewulf/internal/pkg/version" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" "google.golang.org/grpc" "google.golang.org/grpc/codes" "google.golang.org/grpc/credentials" @@ -34,8 +34,9 @@ var apiVersion string func main() { log.Println("Server running") + conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewServer(path.Join(buildconfig.SYSCONFDIR(), "warewulf/wwapid.conf")) + config, err := apiconfig.NewServer(path.Join(conf.SYSCONFDIR(), "warewulf/wwapid.conf")) if err != nil { log.Fatalf("err: %v", err) } diff --git a/internal/app/api/wwapird/wwapird.go b/internal/app/api/wwapird/wwapird.go index dcbaecf1..13f12d4e 100644 --- a/internal/app/api/wwapird/wwapird.go +++ b/internal/app/api/wwapird/wwapird.go @@ -18,20 +18,20 @@ import ( "google.golang.org/grpc/credentials/insecure" "github.com/hpcng/warewulf/internal/pkg/api/apiconfig" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" gw "github.com/hpcng/warewulf/internal/pkg/api/routes/wwapiv1" "path" - - "github.com/hpcng/warewulf/internal/pkg/buildconfig" ) func run() error { log.Println("test0") + conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewClientServer(path.Join(buildconfig.SYSCONFDIR(), "warewulf/wwapird.conf")) + config, err := apiconfig.NewClientServer(path.Join(conf.SYSCONFDIR(), "warewulf/wwapird.conf")) if err != nil { glog.Fatalf("Failed to read config file, err: %v", err) } diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index e657c21b..72691595 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -58,7 +58,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return errors.New("found pidfile " + PIDFile + " not starting") } - if os.Args[0] == path.Join(buildconfig.WWCLIENTDIR(), "wwclient") { + if os.Args[0] == path.Join(conf.WWCLIENTDIR(), "wwclient") { err := os.Chdir("/") if err != nil { wwlog.Error("failed to change dir: %s", err) @@ -70,7 +70,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } else { fmt.Printf("Called via: %s\n", os.Args[0]) fmt.Printf("Runtime overlay is being put in '/warewulf/wwclient-test' rather than '/'\n") - fmt.Printf("For full functionality call with: %s\n", path.Join(buildconfig.WWCLIENTDIR(), "wwclient")) + fmt.Printf("For full functionality call with: %s\n", path.Join(conf.WWCLIENTDIR(), "wwclient")) err := os.MkdirAll("/warewulf/wwclient-test", 0755) if err != nil { wwlog.Error("failed to create dir: %s", err) diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index f40e859d..a59a9739 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -63,7 +63,7 @@ func GetRootCommand() *cobra.Command { return rootCmd } -func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { +func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) { if DebugFlag { wwlog.SetLogLevel(wwlog.DEBUG) } else if verboseArg { @@ -76,9 +76,9 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) error { } conf := warewulfconf.New() if WarewulfConfArg != "" { - conf.ReadConf(WarewulfConfArg) + err = conf.ReadConf(WarewulfConfArg) } else if os.Getenv("WAREWULFCONF") != "" { - conf.ReadConf(os.Getenv("WAREWULFCONF")) + err = conf.ReadConf(os.Getenv("WAREWULFCONF")) } - return nil + return } diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index 0b01e760..f7cfc325 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -30,7 +30,7 @@ func New() (ret ControllerConf) { ret.Nfs = new(NfsConf) ret.Paths = new(BuildConfig) _ = defaults.Set(&ret) - ret.setDynamicDefaults() + _ = ret.setDynamicDefaults() cachedConf = ret cachedConf.current = true From ce43dfa0b77d0fb26e5023f17475e57de9f9ff98 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 6 Mar 2023 09:59:25 +0100 Subject: [PATCH 11/22] removed getters as configs must exportable Signed-off-by: Christian Goll --- .github/workflows/lint.yaml | 3 +- Makefile | 3 +- internal/app/api/wwapic/wwapic.go | 2 +- internal/app/api/wwapid/wwapid.go | 2 +- internal/app/api/wwapird/wwapird.go | 2 +- internal/app/wwclient/root.go | 4 +- internal/pkg/configure/ssh.go | 4 +- internal/pkg/configure/tftp.go | 4 +- internal/pkg/container/config.go | 4 +- internal/pkg/kernel/kernel.go | 2 +- internal/pkg/node/constructors.go | 4 +- internal/pkg/overlay/config.go | 4 +- internal/pkg/overlay/funcmap.go | 7 +- internal/pkg/version/version.go | 2 +- internal/pkg/warewulfconf/buildconfig.go.in | 8 +-- internal/pkg/warewulfconf/getter.go | 73 --------------------- internal/pkg/warewulfd/provision.go | 4 +- 17 files changed, 29 insertions(+), 103 deletions(-) delete mode 100644 internal/pkg/warewulfconf/getter.go diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml index 53901d02..3c6eafee 100644 --- a/.github/workflows/lint.yaml +++ b/.github/workflows/lint.yaml @@ -21,7 +21,8 @@ jobs: go: [ '1.17' ] steps: - uses: actions/checkout@v3 - + - name: Create config + run: make config - name: Setup go ${{ matrix.go }} uses: actions/setup-go@v3 with: diff --git a/Makefile b/Makefile index f1d08c92..cd7b20f7 100644 --- a/Makefile +++ b/Makefile @@ -101,7 +101,7 @@ export GOPROXY WW_GO_BUILD_TAGS := containers_image_openpgp containers_image_ostree # Default target -all: config vendor wwctl wwclient man_pages config_defaults wwapid wwapic wwapird +all: config vendor wwctl wwclient man_pages wwapid wwapic wwapird # Validate source and build all packages build: lint test-it vet all @@ -287,7 +287,6 @@ contclean: rm -f config rm -f Defaults.mk rm -rf $(TOOLS_DIR) - rm -f config_defaults rm -f update_configuration rm -f etc/wwapi{c,d,rd}.conf diff --git a/internal/app/api/wwapic/wwapic.go b/internal/app/api/wwapic/wwapic.go index bd35a973..36cfb002 100644 --- a/internal/app/api/wwapic/wwapic.go +++ b/internal/app/api/wwapic/wwapic.go @@ -27,7 +27,7 @@ func main() { conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewClient(path.Join(conf.SYSCONFDIR(), "warewulf/wwapic.conf")) + config, err := apiconfig.NewClient(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapic.conf")) if err != nil { log.Fatalf("err: %v", err) } diff --git a/internal/app/api/wwapid/wwapid.go b/internal/app/api/wwapid/wwapid.go index 0678114c..ce7457e5 100644 --- a/internal/app/api/wwapid/wwapid.go +++ b/internal/app/api/wwapid/wwapid.go @@ -36,7 +36,7 @@ func main() { conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewServer(path.Join(conf.SYSCONFDIR(), "warewulf/wwapid.conf")) + config, err := apiconfig.NewServer(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapid.conf")) if err != nil { log.Fatalf("err: %v", err) } diff --git a/internal/app/api/wwapird/wwapird.go b/internal/app/api/wwapird/wwapird.go index 13f12d4e..e9b210ac 100644 --- a/internal/app/api/wwapird/wwapird.go +++ b/internal/app/api/wwapird/wwapird.go @@ -31,7 +31,7 @@ func run() error { conf := warewulfconf.New() // Read the config file. - config, err := apiconfig.NewClientServer(path.Join(conf.SYSCONFDIR(), "warewulf/wwapird.conf")) + config, err := apiconfig.NewClientServer(path.Join(conf.Paths.Sysconfdir, "warewulf/wwapird.conf")) if err != nil { glog.Fatalf("Failed to read config file, err: %v", err) } diff --git a/internal/app/wwclient/root.go b/internal/app/wwclient/root.go index 72691595..b63f3f41 100644 --- a/internal/app/wwclient/root.go +++ b/internal/app/wwclient/root.go @@ -58,7 +58,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { return errors.New("found pidfile " + PIDFile + " not starting") } - if os.Args[0] == path.Join(conf.WWCLIENTDIR(), "wwclient") { + if os.Args[0] == path.Join(conf.Paths.WWClientdir, "wwclient") { err := os.Chdir("/") if err != nil { wwlog.Error("failed to change dir: %s", err) @@ -70,7 +70,7 @@ func CobraRunE(cmd *cobra.Command, args []string) error { } else { fmt.Printf("Called via: %s\n", os.Args[0]) fmt.Printf("Runtime overlay is being put in '/warewulf/wwclient-test' rather than '/'\n") - fmt.Printf("For full functionality call with: %s\n", path.Join(conf.WWCLIENTDIR(), "wwclient")) + fmt.Printf("For full functionality call with: %s\n", path.Join(conf.Paths.WWClientdir, "wwclient")) err := os.MkdirAll("/warewulf/wwclient-test", 0755) if err != nil { wwlog.Error("failed to create dir: %s", err) diff --git a/internal/pkg/configure/ssh.go b/internal/pkg/configure/ssh.go index 0c60e053..10186bc2 100644 --- a/internal/pkg/configure/ssh.go +++ b/internal/pkg/configure/ssh.go @@ -15,9 +15,9 @@ func SSH() error { if os.Getuid() == 0 { fmt.Printf("Updating system keys\n") conf := warewulfconf.New() - wwkeydir := path.Join(conf.SYSCONFDIR(), "warewulf/keys") + "/" + wwkeydir := path.Join(conf.Paths.Sysconfdir, "warewulf/keys") + "/" - err := os.MkdirAll(path.Join(conf.SYSCONFDIR(), "warewulf/keys"), 0755) + err := os.MkdirAll(path.Join(conf.Paths.Sysconfdir, "warewulf/keys"), 0755) if err != nil { wwlog.Error("Could not create base directory: %s", err) os.Exit(1) diff --git a/internal/pkg/configure/tftp.go b/internal/pkg/configure/tftp.go index 718a4030..74bed889 100644 --- a/internal/pkg/configure/tftp.go +++ b/internal/pkg/configure/tftp.go @@ -12,7 +12,7 @@ import ( func TFTP() error { controller := warewulfconf.New() - var tftpdir string = path.Join(controller.TFTPDIR(), "warewulf") + var tftpdir string = path.Join(controller.Paths.Tftpdir, "warewulf") err := os.MkdirAll(tftpdir, 0755) if err != nil { @@ -27,7 +27,7 @@ func TFTP() error { continue } copyCheck[f] = true - err = util.SafeCopyFile(path.Join(controller.DATADIR(), f), path.Join(tftpdir, f)) + err = util.SafeCopyFile(path.Join(controller.Paths.Datadir, f), path.Join(tftpdir, f)) if err != nil { wwlog.Warn("ipxe binary could not be copied, booting may not work: %s", err) } diff --git a/internal/pkg/container/config.go b/internal/pkg/container/config.go index ebbc8569..ecd751fa 100644 --- a/internal/pkg/container/config.go +++ b/internal/pkg/container/config.go @@ -8,7 +8,7 @@ import ( func SourceParentDir() string { conf := warewulfconf.New() - return conf.WWCHROOTDIR() + return conf.Paths.WWChrootdir } func SourceDir(name string) string { @@ -21,7 +21,7 @@ func RootFsDir(name string) string { func ImageParentDir() string { conf := warewulfconf.New() - return path.Join(conf.WWPROVISIONDIR(), "container/") + return path.Join(conf.Paths.WWProvisiondir, "container/") } func ImageFile(name string) string { diff --git a/internal/pkg/kernel/kernel.go b/internal/pkg/kernel/kernel.go index 14ce78a2..32a1da47 100644 --- a/internal/pkg/kernel/kernel.go +++ b/internal/pkg/kernel/kernel.go @@ -29,7 +29,7 @@ var ( func KernelImageTopDir() string { conf := warewulfconf.New() - return path.Join(conf.WWPROVISIONDIR(), "kernel") + return path.Join(conf.Paths.WWProvisiondir, "kernel") } func KernelImage(kernelName string) string { diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 3d83f8df..bcf57d0b 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -39,10 +39,10 @@ defaultnode: func init() { conf := warewulfconf.New() if ConfigFile == "" { - ConfigFile = path.Join(conf.SYSCONFDIR(), "warewulf/nodes.conf") + ConfigFile = path.Join(conf.Paths.Sysconfdir, "warewulf/nodes.conf") } if DefaultConfig == "" { - DefaultConfig = path.Join(conf.SYSCONFDIR(), "warewulf/defaults.conf") + DefaultConfig = path.Join(conf.Paths.Sysconfdir, "warewulf/defaults.conf") } } diff --git a/internal/pkg/overlay/config.go b/internal/pkg/overlay/config.go index 3f5b1bd4..91452e4a 100644 --- a/internal/pkg/overlay/config.go +++ b/internal/pkg/overlay/config.go @@ -10,7 +10,7 @@ import ( func OverlaySourceTopDir() string { conf := warewulfconf.New() - return conf.WWOVERLAYDIR() + return conf.Paths.WWOverlaydir } /* @@ -32,5 +32,5 @@ Returns the overlay name of the image for a given node */ func OverlayImage(nodeName string, overlayName []string) string { conf := warewulfconf.New() - return path.Join(conf.WWPROVISIONDIR(), "overlays/", nodeName, strings.Join(overlayName, "-")+".img") + return path.Join(conf.Paths.WWProvisiondir, "overlays/", nodeName, strings.Join(overlayName, "-")+".img") } diff --git a/internal/pkg/overlay/funcmap.go b/internal/pkg/overlay/funcmap.go index d3fe05e5..ebdb1b1a 100644 --- a/internal/pkg/overlay/funcmap.go +++ b/internal/pkg/overlay/funcmap.go @@ -14,13 +14,12 @@ import ( /* Reads a file file from the host fs. If the file has nor '/' prefix -the path is relative to SYSCONFDIR. -Templates in the file are no evaluated. +the path is relative to Paths.SysconfdirTemplates in the file are no evaluated. */ func templateFileInclude(inc string) string { conf := warewulfconf.New() if !strings.HasPrefix(inc, "/") { - inc = path.Join(conf.SYSCONFDIR(), "warewulf", inc) + inc = path.Join(conf.Paths.Sysconfdir, "warewulf", inc) } wwlog.Debug("Including file into template: %s", inc) content, err := os.ReadFile(inc) @@ -38,7 +37,7 @@ Templates in the file are no evaluated. func templateFileBlock(inc string, abortStr string) (string, error) { conf := warewulfconf.New() if !strings.HasPrefix(inc, "/") { - inc = path.Join(conf.SYSCONFDIR(), "warewulf", inc) + inc = path.Join(conf.Paths.Sysconfdir, "warewulf", inc) } wwlog.Debug("Including file block into template: %s", inc) readFile, err := os.Open(inc) diff --git a/internal/pkg/version/version.go b/internal/pkg/version/version.go index 5ce00f23..6b4771bb 100644 --- a/internal/pkg/version/version.go +++ b/internal/pkg/version/version.go @@ -12,7 +12,7 @@ Return the version of wwctl */ func GetVersion() string { conf := warewulfconf.New() - return fmt.Sprintf("%s-%s", conf.VERSION(), conf.RELEASE()) + return fmt.Sprintf("%s-%s", conf.Paths.Version, conf.Paths.Release) } /* diff --git a/internal/pkg/warewulfconf/buildconfig.go.in b/internal/pkg/warewulfconf/buildconfig.go.in index 3a5a52cd..cd7ac2f4 100644 --- a/internal/pkg/warewulfconf/buildconfig.go.in +++ b/internal/pkg/warewulfconf/buildconfig.go.in @@ -9,10 +9,10 @@ type BuildConfig struct { Tftpdir string `default:"@TFTPDIR@"` Firewallddir string `default:"@FIREWALLDDIR@"` Systemddir string `default:"@SYSTEMDDIR@"` - Wwoverlaydir string `default:"@WWOVERLAYDIR@"` - Wwchrootdir string `default:"@WWCHROOTDIR@"` - Wwprovisiondir string `default:"@WWPROVISIONDIR@"` + WWOverlaydir string `default:"@WWOVERLAYDIR@"` + WWChrootdir string `default:"@WWCHROOTDIR@"` + WWProvisiondir string `default:"@WWPROVISIONDIR@"` Version string `default:"@VERSION@"` Release string `default:"@RELEASE@"` - Wwclientdir string `default:"@WWCLIENTDIR@"` + WWClientdir string `default:"@WWCLIENTDIR@"` } diff --git a/internal/pkg/warewulfconf/getter.go b/internal/pkg/warewulfconf/getter.go deleted file mode 100644 index 6d92a2fe..00000000 --- a/internal/pkg/warewulfconf/getter.go +++ /dev/null @@ -1,73 +0,0 @@ -package warewulfconf - -import "github.com/hpcng/warewulf/internal/pkg/wwlog" - -func (conf *ControllerConf) BINDIR() string { - wwlog.Debug("BINDIR = '%s'", conf.Paths.Bindir) - return conf.Paths.Bindir -} - -func (conf *ControllerConf) DATADIR() string { - wwlog.Debug("DATADIR = '%s'", conf.Paths.Datadir) - return conf.Paths.Datadir -} - -func (conf *ControllerConf) SYSCONFDIR() string { - wwlog.Debug("SYSCONFDIR = '%s'", conf.Paths.Sysconfdir) - return conf.Paths.Sysconfdir -} - -func (conf *ControllerConf) LOCALSTATEDIR() string { - wwlog.Debug("LOCALSTATEDIR = '%s'", conf.Paths.Localstatedir) - return conf.Paths.Localstatedir -} - -func (conf *ControllerConf) SRVDIR() string { - wwlog.Debug("SRVDIR = '%s'", conf.Paths.Srvdir) - return conf.Paths.Srvdir -} - -func (conf *ControllerConf) TFTPDIR() string { - wwlog.Debug("TFTPDIR = '%s'", conf.Paths.Tftpdir) - return conf.Paths.Tftpdir -} - -func (conf *ControllerConf) FIREWALLDDIR() string { - wwlog.Debug("FIREWALLDDIR = '%s'", conf.Paths.Firewallddir) - return conf.Paths.Firewallddir -} - -func (conf *ControllerConf) SYSTEMDDIR() string { - wwlog.Debug("SYSTEMDDIR = '%s'", conf.Paths.Systemddir) - return conf.Paths.Systemddir -} - -func (conf *ControllerConf) WWOVERLAYDIR() string { - wwlog.Debug("WWOVERLAYDIR = '%s'", conf.Paths.Wwoverlaydir) - return conf.Paths.Wwoverlaydir -} - -func (conf *ControllerConf) WWCHROOTDIR() string { - wwlog.Debug("WWCHROOTDIR = '%s'", conf.Paths.Wwchrootdir) - return conf.Paths.Wwchrootdir -} - -func (conf *ControllerConf) WWPROVISIONDIR() string { - wwlog.Debug("WWPROVISIONDIR = '%s'", conf.Paths.Wwprovisiondir) - return conf.Paths.Wwprovisiondir -} - -func (conf *ControllerConf) VERSION() string { - wwlog.Debug("VERSION = '%s'", conf.Paths.Version) - return conf.Paths.Version -} - -func (conf *ControllerConf) RELEASE() string { - wwlog.Debug("RELEASE = '%s'", conf.Paths.Release) - return conf.Paths.Release -} - -func (conf *ControllerConf) WWCLIENTDIR() string { - wwlog.Debug("WWCLIENTDIR = '%s'", conf.Paths.Wwclientdir) - return conf.Paths.Wwclientdir -} diff --git a/internal/pkg/warewulfd/provision.go b/internal/pkg/warewulfd/provision.go index 7b96ee6d..c96267cc 100644 --- a/internal/pkg/warewulfd/provision.go +++ b/internal/pkg/warewulfd/provision.go @@ -79,13 +79,13 @@ func ProvisionSend(w http.ResponseWriter, req *http.Request) { if !node.Id.Defined() { wwlog.Error("%s (unknown/unconfigured node)", rinfo.hwaddr) if rinfo.stage == "ipxe" { - stage_file = path.Join(conf.SYSCONFDIR(), "/warewulf/ipxe/unconfigured.ipxe") + stage_file = path.Join(conf.Paths.Sysconfdir, "/warewulf/ipxe/unconfigured.ipxe") tmpl_data = iPxeTemplate{ Hwaddr: rinfo.hwaddr} } } else if rinfo.stage == "ipxe" { - stage_file = path.Join(conf.SYSCONFDIR(), "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe") + stage_file = path.Join(conf.Paths.Sysconfdir, "warewulf/ipxe/"+node.Ipxe.Get()+".ipxe") tmpl_data = iPxeTemplate{ Id: node.Id.Get(), Cluster: node.ClusterName.Get(), From a422a1617ca7e90ad26f7a807050eeb757b84365 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 6 Mar 2023 15:51:34 +0100 Subject: [PATCH 12/22] added Changelog Signed-off-by: Christian Goll --- CHANGELOG.md | 12 ++- Makefile | 4 +- internal/app/wwctl/root.go | 18 ++-- internal/pkg/warewulfconf/constructors.go | 103 ++++++++++++++-------- 4 files changed, 93 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d9c14ff8..2acc340c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,7 +16,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - The primary hostname and warewulf server fqdn are now the canonical name in `/etc/hosts` - +- new subcommand `wwctl genconf` is available with following subcommands: + * `completions` which will create the files used for bash-completion. Also + fish an zsh completions can be generated + * `defaults` which will generate a valid `defaults.conf` + * `man` which will generate the man pages in the specified directory + * `reference` which will generate a reference documentation for the wwctl commands + * `warwulfconf print` which will print the used `warewulf.conf`. If there is no valid + `warewulf.conf` a valid configuration is provided, prefilled with default values + and an IP configuration derived from the network configuration of the host +- All paths can now be configured in `warewulf.conf`, check the paths section of of + `wwctl --emptyconf genconfig warewulfconf print` for the available paths. ## [4.4.0] 2023-01-18 ### Added diff --git a/Makefile b/Makefile index cd7b20f7..1093f65a 100644 --- a/Makefile +++ b/Makefile @@ -218,7 +218,9 @@ init: wwctl: $(WWCTL_DEPS) @echo Building "$@" - @cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" -o ../../wwctl + @cd cmd/wwctl; GOOS=linux go build -mod vendor -tags "$(WW_GO_BUILD_TAGS)" \ + -ldflags "-X 'github.com/hpcng/warewulf/internal/pkg/warewulfconf.ConfigFile=$(SYSCONFDIR)/warewulf/warewulf.conf'" \ + -o ../../wwctl wwclient: $(WWCLIENT_DEPS) @echo Building "$@" diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index a59a9739..395c4b4c 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -34,6 +34,7 @@ var ( DebugFlag bool LogLevel int WarewulfConfArg string + AllowEmptyConf bool ) func init() { @@ -42,9 +43,10 @@ func init() { rootCmd.PersistentFlags().IntVar(&LogLevel, "loglevel", wwlog.INFO, "Set log level to given string") _ = rootCmd.PersistentFlags().MarkHidden("loglevel") rootCmd.PersistentFlags().StringVar(&WarewulfConfArg, "warewulfconf", "", "Set the warewulf configuration file") + rootCmd.PersistentFlags().BoolVar(&AllowEmptyConf, "emptyconf", false, "Allow empty configuration") + _ = rootCmd.PersistentFlags().MarkHidden("emptyconf") rootCmd.SetUsageTemplate(help.UsageTemplate) rootCmd.SetHelpTemplate(help.HelpTemplate) - rootCmd.AddCommand(overlay.GetCommand()) rootCmd.AddCommand(container.GetCommand()) rootCmd.AddCommand(node.GetCommand()) @@ -75,10 +77,16 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) { wwlog.SetLogLevel(LogLevel) } conf := warewulfconf.New() - if WarewulfConfArg != "" { - err = conf.ReadConf(WarewulfConfArg) - } else if os.Getenv("WAREWULFCONF") != "" { - err = conf.ReadConf(os.Getenv("WAREWULFCONF")) + if !AllowEmptyConf { + if WarewulfConfArg != "" { + err = conf.ReadConf(WarewulfConfArg) + } else if os.Getenv("WAREWULFCONF") != "" { + err = conf.ReadConf(os.Getenv("WAREWULFCONF")) + } else { + err = conf.ReadConf(warewulfconf.ConfigFile) + } + } else { + conf.SetDynamicDefaults() } return } diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index f7cfc325..03d510ca 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -1,12 +1,12 @@ package warewulfconf import ( - "errors" "fmt" "net" "os" - "github.com/brotherpowers/ipsubnet" + "github.com/pkg/errors" + "github.com/creasty/defaults" "github.com/hpcng/warewulf/internal/pkg/wwlog" "gopkg.in/yaml.v2" @@ -20,32 +20,32 @@ var ConfigFile string Creates a new empty ControllerConf object, returns a cached one if called in a nother context. */ -func New() (ret ControllerConf) { +func New() (conf ControllerConf) { // NOTE: This function can be called before any log level is set // so using wwlog.Verbose or wwlog.Debug won't work if !cachedConf.current { - ret.Warewulf = new(WarewulfConf) - ret.Dhcp = new(DhcpConf) - ret.Tftp = new(TftpConf) - ret.Nfs = new(NfsConf) - ret.Paths = new(BuildConfig) - _ = defaults.Set(&ret) - _ = ret.setDynamicDefaults() + conf.Warewulf = new(WarewulfConf) + conf.Dhcp = new(DhcpConf) + conf.Tftp = new(TftpConf) + conf.Nfs = new(NfsConf) + conf.Paths = new(BuildConfig) + _ = defaults.Set(&conf) - cachedConf = ret + cachedConf = conf cachedConf.current = true } else { // If cached struct isn't empty, use it as the return value - ret = cachedConf + conf = cachedConf } - return ret + return conf } /* Populate the configuration with the values from the configuration file. */ func (conf *ControllerConf) ReadConf(confFileName string) (err error) { + wwlog.Debug("Reading warewulf.conf from: %s", confFileName) fileHandle, err := os.ReadFile(confFileName) if err != nil { return err @@ -67,6 +67,10 @@ func (conf *ControllerConf) Read(data []byte) (err error) { if err != nil { return } + err = conf.SetDynamicDefaults() + if err != nil { + return + } if len(conf.Tftp.IpxeBinaries) == 0 { conf.Tftp.IpxeBinaries = defIpxe } @@ -78,38 +82,61 @@ func (conf *ControllerConf) Read(data []byte) (err error) { /* Set the runtime defaults like IP address of running system to the config */ -func (ret *ControllerConf) setDynamicDefaults() (err error) { - if ret.Ipaddr == "" || ret.Netmask == "" { - conn, error := net.Dial("udp", "8.8.8.8:80") - if error != nil { - return err +func (conf *ControllerConf) SetDynamicDefaults() (err error) { + if conf.Ipaddr == "" || conf.Netmask == "" || conf.Network == "" { + var mask net.IPMask + var network *net.IPNet + var ipaddr net.IP + + if conf.Ipaddr == "" { + wwlog.Verbose("Configuration has no valid network, going to dynamic values") + conn, _ := net.Dial("udp", "8.8.8.8:80") + defer conn.Close() + ipaddr = conn.LocalAddr().(*net.UDPAddr).IP + mask = ipaddr.DefaultMask() + sz, _ := mask.Size() + conf.Ipaddr = ipaddr.String() + fmt.Sprintf("/%d", sz) } - defer conn.Close() - localIp := conn.LocalAddr().(*net.UDPAddr) - if ret.Ipaddr == "" { - ret.Ipaddr = localIp.IP.String() - wwlog.Verbose("IP address is not configured in warewulfd.conf, using %s", ret.Ipaddr) + _, network, err = net.ParseCIDR(conf.Ipaddr) + if err == nil { + mask = network.Mask + fmt.Println(mask) + } else { + return errors.Wrap(err, "Couldn't parse IP address") } - if ret.Netmask == "" { - mask := localIp.IP.DefaultMask() - ret.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) - wwlog.Verbose("Netmask address is not configured in warewulfd.conf, using %s", ret.Netmask) + if conf.Netmask == "" { + conf.Netmask = fmt.Sprintf("%d.%d.%d.%d", mask[0], mask[1], mask[2], mask[3]) + wwlog.Verbose("Netmask address is not configured in warewulf.conf, using %s", conf.Netmask) + } + if conf.Network == "" { + conf.Network = network.IP.String() + wwlog.Verbose("Network is not configured in warewulf.conf, using %s", conf.Network) } } + if conf.Dhcp.RangeStart == "" && conf.Dhcp.RangeEnd == "" { + start := net.ParseIP(conf.Network).To4() + start[3] += 1 + if start.Equal(net.ParseIP(conf.Ipaddr)) { + start[3] += 1 + } + conf.Dhcp.RangeStart = start.String() + wwlog.Verbose("dhpd start is not configured in warewulf.conf, using %s", conf.Dhcp.RangeStart) + sz, _ := net.IPMask(net.ParseIP(conf.Netmask).To4()).Size() + range_end := (1 << (32 - sz)) / 8 + if range_end > 127 { + range_end = 127 + } + end := net.ParseIP(conf.Network).To4() + end[3] += byte(range_end) + conf.Dhcp.RangeEnd = end.String() + wwlog.Verbose("dhpd end is not configured in warewulf.conf, using %s", conf.Dhcp.RangeEnd) - if ret.Network == "" { - mask := net.IPMask(net.ParseIP(ret.Netmask).To4()) - size, _ := mask.Size() - - sub := ipsubnet.SubnetCalculator(ret.Ipaddr, size) - - ret.Network = sub.GetNetworkPortion() } // check validity of ipv6 net - if ret.Ipaddr6 != "" { - _, ipv6net, err := net.ParseCIDR(ret.Ipaddr6) + if conf.Ipaddr6 != "" { + _, ipv6net, err := net.ParseCIDR(conf.Ipaddr6) if err != nil { - wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", ret.Ipaddr6) + wwlog.Error("Invalid ipv6 address specified, mut be CIDR notation: %s", conf.Ipaddr6) return errors.New("invalid ipv6 network") } if msize, _ := ipv6net.Mask.Size(); msize > 64 { @@ -117,5 +144,7 @@ func (ret *ControllerConf) setDynamicDefaults() (err error) { return errors.New("invalid ipv6 network size") } } + cachedConf = *conf + cachedConf.current = true return } From 3367b67b9f09188b4ebd098e22dda690a99d9ed7 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 7 Mar 2023 08:58:29 +0100 Subject: [PATCH 13/22] added a test for `wwctl node add` Signed-off-by: Christian Goll --- internal/app/wwctl/node/add/main_test.go | 89 ++++++++++++++++++++++ internal/app/wwctl/root.go | 4 +- internal/pkg/node/constructors.go | 43 ++++++++++- internal/pkg/node/datastructure.go | 2 + internal/pkg/node/modifiers.go | 5 +- internal/pkg/warewulfconf/constructors.go | 10 ++- internal/pkg/warewulfconf/datastructure.go | 1 + internal/pkg/warewulfd/daemon.go | 28 +++++++ 8 files changed, 177 insertions(+), 5 deletions(-) create mode 100644 internal/app/wwctl/node/add/main_test.go diff --git a/internal/app/wwctl/node/add/main_test.go b/internal/app/wwctl/node/add/main_test.go new file mode 100644 index 00000000..29750a47 --- /dev/null +++ b/internal/app/wwctl/node/add/main_test.go @@ -0,0 +1,89 @@ +package add + +import ( + "bytes" + "testing" + + "github.com/hpcng/warewulf/internal/pkg/node" + "github.com/hpcng/warewulf/internal/pkg/warewulfconf" + "github.com/hpcng/warewulf/internal/pkg/warewulfd" + "github.com/stretchr/testify/assert" +) + +func Test_Add(t *testing.T) { + t.Helper() + conf_yml := ` +WW_INTERNAL: 0 + ` + nodes_yml := ` +WW_INTERNAL: 43 +` + conf := warewulfconf.New() + err := conf.Read([]byte(conf_yml)) + assert.NoError(t, err) + db, err := node.TestNew([]byte(nodes_yml)) + assert.NoError(t, err) + warewulfd.SetNoDaemon() + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) + tests := []struct { + name string + args []string + wantErr bool + stdout string + outDb string + }{ + {name: "single node add", + args: []string{"n01"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + default: {} +`}, + {name: "double node add", + args: []string{"n0[1-2]"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + default: {} + n02: + profiles: + - default + network devices: + default: {} +`}, + } + for _, tt := range tests { + db, err = node.TestNew([]byte(nodes_yml)) + assert.NoError(t, err) + t.Run(tt.name, func(t *testing.T) { + baseCmd.SetArgs(tt.args) + err = baseCmd.Execute() + if (err != nil) != tt.wantErr { + t.Errorf("Got unwanted error: %s", err) + return + } + dump := string(db.DBDump()) + if dump != tt.outDb { + t.Errorf("DB dump is wrong, got:'%s'\nwant:'%s'", dump, tt.outDb) + return + } + if buf.String() != tt.stdout { + t.Errorf("Got wrong output, got:'%s'\nwant:'%s'", buf.String(), tt.stdout) + } + }) + } +} diff --git a/internal/app/wwctl/root.go b/internal/app/wwctl/root.go index 395c4b4c..42f9e4e9 100644 --- a/internal/app/wwctl/root.go +++ b/internal/app/wwctl/root.go @@ -77,7 +77,7 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) { wwlog.SetLogLevel(LogLevel) } conf := warewulfconf.New() - if !AllowEmptyConf { + if !AllowEmptyConf && !conf.Initialized() { if WarewulfConfArg != "" { err = conf.ReadConf(WarewulfConfArg) } else if os.Getenv("WAREWULFCONF") != "" { @@ -86,7 +86,7 @@ func rootPersistentPreRunE(cmd *cobra.Command, args []string) (err error) { err = conf.ReadConf(warewulfconf.ConfigFile) } } else { - conf.SetDynamicDefaults() + err = conf.SetDynamicDefaults() } return } diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index bcf57d0b..89079144 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -16,6 +16,8 @@ import ( var ConfigFile string var DefaultConfig string +var cachedDB NodeYaml + // used as fallback if DefaultConfig can't be read var FallBackConf = `--- defaultnode: @@ -44,9 +46,18 @@ func init() { if DefaultConfig == "" { DefaultConfig = path.Join(conf.Paths.Sysconfdir, "warewulf/defaults.conf") } + cachedDB.current = false + cachedDB.persist = true } +/* +Creates a new nodeDb object from the actual configuration +*/ func New() (NodeYaml, error) { + if cachedDB.current { + wwlog.Debug("Returning cached object") + return cachedDB, nil + } var ret NodeYaml wwlog.Verbose("Opening node configuration file: %s", ConfigFile) @@ -62,10 +73,40 @@ func New() (NodeYaml, error) { } wwlog.Debug("Returning node object") - + cachedDB = ret + cachedDB.current = true return ret, nil } +/* +Creates a database object from a given buffer, always create +a new object, never return the cached one. +*/ +func TestNew(buffer []byte) (db NodeYaml, err error) { + db.NodeProfiles = make(map[string]*NodeConf) + db.Nodes = make(map[string]*NodeConf) + err = yaml.Unmarshal(buffer, &db) + db.persist = false + cachedDB = db + cachedDB.current = true + wwlog.Debug("Created cached object") + return +} + +func (config *NodeYaml) DBDump() (buffer []byte) { + for _, n := range config.Nodes { + n.Flatten() + } + for _, p := range config.NodeProfiles { + p.Flatten() + } + buffer, err := yaml.Marshal(config) + if err != nil { + wwlog.Warn("porblems on dumping nodedb: %s", err) + } + return +} + /* Get all the nodes of a configuration. This function also merges the nodes with the given profiles and set the default values diff --git a/internal/pkg/node/datastructure.go b/internal/pkg/node/datastructure.go index 72bea85a..cecd1db5 100644 --- a/internal/pkg/node/datastructure.go +++ b/internal/pkg/node/datastructure.go @@ -10,6 +10,8 @@ type NodeYaml struct { WWInternal int `yaml:"WW_INTERNAL"` NodeProfiles map[string]*NodeConf Nodes map[string]*NodeConf + current bool + persist bool } /* diff --git a/internal/pkg/node/modifiers.go b/internal/pkg/node/modifiers.go index 1537f93c..2c644657 100644 --- a/internal/pkg/node/modifiers.go +++ b/internal/pkg/node/modifiers.go @@ -127,7 +127,10 @@ func (config *NodeYaml) Persist() error { if err != nil { return err } - + // Can't persist for unit tests + if !config.persist { + return err + } file, err := os.OpenFile(ConfigFile, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644) if err != nil { wwlog.Error("%s", err) diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index 03d510ca..217b8cfc 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -30,8 +30,8 @@ func New() (conf ControllerConf) { conf.Nfs = new(NfsConf) conf.Paths = new(BuildConfig) _ = defaults.Set(&conf) - cachedConf = conf + cachedConf.readConf = false cachedConf.current = true } else { @@ -76,6 +76,7 @@ func (conf *ControllerConf) Read(data []byte) (err error) { } cachedConf = *conf cachedConf.current = true + cachedConf.readConf = true return } @@ -148,3 +149,10 @@ func (conf *ControllerConf) SetDynamicDefaults() (err error) { cachedConf.current = true return } + +/* +Return if configuration was read from disk +*/ +func (conf *ControllerConf) Initialized() bool { + return conf.readConf +} diff --git a/internal/pkg/warewulfconf/datastructure.go b/internal/pkg/warewulfconf/datastructure.go index 4c4ae71b..1958a2b5 100644 --- a/internal/pkg/warewulfconf/datastructure.go +++ b/internal/pkg/warewulfconf/datastructure.go @@ -20,6 +20,7 @@ type ControllerConf struct { MountsContainer []*MountEntry `yaml:"container mounts" default:"[{\"source\": \"/etc/resolv.conf\", \"dest\": \"/etc/resolv.conf\"}]"` Paths *BuildConfig `yaml:"paths"` current bool + readConf bool } type WarewulfConf struct { diff --git a/internal/pkg/warewulfd/daemon.go b/internal/pkg/warewulfd/daemon.go index 99407d23..34a989b6 100644 --- a/internal/pkg/warewulfd/daemon.go +++ b/internal/pkg/warewulfd/daemon.go @@ -23,6 +23,23 @@ const ( var loginit bool +// allow to run without daemon for tests +var nodaemon bool + +func init() { + nodaemon = false +} + +// run without daemon +func SetNoDaemon() { + nodaemon = true +} + +// run with daemon +func SetDaemon() { + nodaemon = false +} + func DaemonFormatter(logLevel int, rec *wwlog.LogRecord) string { return "[" + rec.Time.Format(time.UnixDate) + "] " + wwlog.DefaultFormatter(logLevel, rec) } @@ -66,6 +83,10 @@ func DaemonInitLogging() error { } func DaemonStart() error { + if nodaemon { + return nil + } + if os.Getenv("WAREWULFD_BACKGROUND") == "1" { err := RunServer() if err != nil { @@ -116,6 +137,10 @@ func DaemonStart() error { } func DaemonStatus() error { + if nodaemon { + return nil + } + if !util.IsFile(WAREWULFD_PIDFILE) { return errors.New("Warewulf server is not running") } @@ -142,6 +167,9 @@ func DaemonStatus() error { } func DaemonReload() error { + if nodaemon { + return nil + } if !util.IsFile(WAREWULFD_PIDFILE) { return errors.New("Warewulf server is not running") } From 07d39c2e496727bc130510069f111828c071953e Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 7 Mar 2023 11:49:09 +0100 Subject: [PATCH 14/22] moved location of defaults.conf Signed-off-by: Christian Goll --- Makefile | 6 +++--- go.mod | 1 - go.sum | 2 -- internal/pkg/node/constructors.go | 8 +------- internal/pkg/warewulfconf/constructors.go | 2 -- 5 files changed, 4 insertions(+), 15 deletions(-) diff --git a/Makefile b/Makefile index 1093f65a..c50baae9 100644 --- a/Makefile +++ b/Makefile @@ -183,7 +183,7 @@ files: all test -f $(DESTDIR)$(WWCONFIGDIR)/wwapic.conf || install -m 644 etc/wwapic.conf $(DESTDIR)$(WWCONFIGDIR) test -f $(DESTDIR)$(WWCONFIGDIR)/wwapid.conf || install -m 644 etc/wwapid.conf $(DESTDIR)$(WWCONFIGDIR) test -f $(DESTDIR)$(WWCONFIGDIR)/wwapird.conf || install -m 644 etc/wwapird.conf $(DESTDIR)$(WWCONFIGDIR) - test -f $(DESTDIR)$(WWCONFIGDIR)/defaults.conf || ./wwctl genconfig defaults > $(DESTDIR)$(WWCONFIGDIR)/defaults.conf + test -f $(DESTDIR)$(DATADIR)/warewulf/defaults.conf || ./wwctl --emptyconf genconfig defaults > $(DESTDIR)$(DATADIR)/warewulf/defaults.conf cp -r etc/examples $(DESTDIR)$(WWCONFIGDIR)/ cp -r etc/ipxe $(DESTDIR)$(WWCONFIGDIR)/ cp -r overlays/* $(DESTDIR)$(WWOVERLAYDIR)/ @@ -229,7 +229,7 @@ wwclient: $(WWCLIENT_DEPS) man_pages: wwctl install -d man_pages - ./wwctl genconfig man man_pages + ./wwctl --emptyconf genconfig man man_pages cp docs/man/man5/*.5 ./man_pages/ cd man_pages; for i in wwctl*1 *.5; do echo "Compressing manpage: $$i"; gzip --force $$i; done @@ -246,7 +246,7 @@ dist: vendor config rm -rf .dist reference: wwctl - ./wwctl genconfig reference userdocs/reference/ + ./wwctl --emptyconf genconfig reference userdocs/reference/ latexpdf: reference make -C userdocs latexpdf diff --git a/go.mod b/go.mod index 6159de0c..34b3a458 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,6 @@ module github.com/hpcng/warewulf go 1.16 require ( - github.com/brotherpowers/ipsubnet v0.0.0-20170914094241-30bc98f0a5b1 github.com/containers/image/v5 v5.7.0 github.com/containers/storage v1.30.0 github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e diff --git a/go.sum b/go.sum index a58cfc27..829c8f81 100644 --- a/go.sum +++ b/go.sum @@ -104,8 +104,6 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/blang/semver v3.1.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk= github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4= -github.com/brotherpowers/ipsubnet v0.0.0-20170914094241-30bc98f0a5b1 h1:80OMQcGycPqKFFabSaxOagCh7mgspnMl/X3YGmNi+j0= -github.com/brotherpowers/ipsubnet v0.0.0-20170914094241-30bc98f0a5b1/go.mod h1:mm9ZF6W76SwZtJpYzrVmTMuzmIhPX0SIuEosW/OTFd4= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= diff --git a/internal/pkg/node/constructors.go b/internal/pkg/node/constructors.go index 89079144..10ee86ad 100644 --- a/internal/pkg/node/constructors.go +++ b/internal/pkg/node/constructors.go @@ -44,7 +44,7 @@ func init() { ConfigFile = path.Join(conf.Paths.Sysconfdir, "warewulf/nodes.conf") } if DefaultConfig == "" { - DefaultConfig = path.Join(conf.Paths.Sysconfdir, "warewulf/defaults.conf") + DefaultConfig = path.Join(conf.Paths.Datadir, "warewulf/defaults.conf") } cachedDB.current = false cachedDB.persist = true @@ -114,12 +114,6 @@ for every node */ func (config *NodeYaml) FindAllNodes() ([]NodeInfo, error) { var ret []NodeInfo - /* - wwconfig, err := warewulfconf.New() - if err != nil { - return ret, err - } - */ var defConf map[string]*NodeConf wwlog.Verbose("Opening defaults from file failed %s\n", DefaultConfig) defData, err := os.ReadFile(DefaultConfig) diff --git a/internal/pkg/warewulfconf/constructors.go b/internal/pkg/warewulfconf/constructors.go index 217b8cfc..2a1e0ff0 100644 --- a/internal/pkg/warewulfconf/constructors.go +++ b/internal/pkg/warewulfconf/constructors.go @@ -33,7 +33,6 @@ func New() (conf ControllerConf) { cachedConf = conf cachedConf.readConf = false cachedConf.current = true - } else { // If cached struct isn't empty, use it as the return value conf = cachedConf @@ -101,7 +100,6 @@ func (conf *ControllerConf) SetDynamicDefaults() (err error) { _, network, err = net.ParseCIDR(conf.Ipaddr) if err == nil { mask = network.Mask - fmt.Println(mask) } else { return errors.Wrap(err, "Couldn't parse IP address") } From d3af143a5b1cb03ab9140949a0199cf007b5e24f Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Tue, 7 Mar 2023 17:01:57 +0100 Subject: [PATCH 15/22] main_tests are not working as expected The global values which store the flags are not regenerated during test Signed-off-by: Christian Goll --- internal/app/wwctl/node/add/main.go | 9 +- internal/app/wwctl/node/add/main_test.go | 155 ++++++++++++++++++++++- internal/pkg/node/methods.go | 27 ++++ internal/pkg/node/methods_test.go | 32 +++++ 4 files changed, 213 insertions(+), 10 deletions(-) create mode 100644 internal/pkg/node/methods_test.go diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index 762907bf..dc24299e 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -12,13 +12,16 @@ import ( ) func CobraRunE(cmd *cobra.Command, args []string) error { - // remove the default network as the all network values are assigned + // remove the default network as all network values are assigned // to this network - if NetName != "" { + if _, ok := NodeConf.NetDevs["default"]; ok && NetName != "" { netDev := *NodeConf.NetDevs["default"] NodeConf.NetDevs[NetName] = &netDev delete(NodeConf.NetDevs, "default") - + } else { + if NodeConf.NetDevs["default"].Empty() { + delete(NodeConf.NetDevs, "default") + } } buffer, err := yaml.Marshal(NodeConf) if err != nil { diff --git a/internal/app/wwctl/node/add/main_test.go b/internal/app/wwctl/node/add/main_test.go index 29750a47..d6935790 100644 --- a/internal/app/wwctl/node/add/main_test.go +++ b/internal/app/wwctl/node/add/main_test.go @@ -2,6 +2,7 @@ package add import ( "bytes" + "fmt" "testing" "github.com/hpcng/warewulf/internal/pkg/node" @@ -14,7 +15,7 @@ func Test_Add(t *testing.T) { t.Helper() conf_yml := ` WW_INTERNAL: 0 - ` + ` nodes_yml := ` WW_INTERNAL: 43 ` @@ -33,6 +34,7 @@ WW_INTERNAL: 43 wantErr bool stdout string outDb string + flags map[string]string }{ {name: "single node add", args: []string{"n01"}, @@ -44,11 +46,50 @@ nodes: n01: profiles: - default - network devices: - default: {} `}, - {name: "double node add", - args: []string{"n0[1-2]"}, + {name: "single node add, profile foo", + args: []string{"n01"}, + flags: map[string]string{"profile": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - foo +`}, + {name: "single node add with Kernel args", + args: []string{"n01"}, + flags: map[string]string{"kernelargs": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + kernel: + args: foo + profiles: + - default +`}, + {name: "double node add explicit", + args: []string{"n01", "n02"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + n02: + profiles: + - default +`}, + {name: "single node with ipaddr", + args: []string{"n01"}, + flags: map[string]string{"ipaddr": "10.10.0.1"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -58,19 +99,111 @@ nodes: profiles: - default network devices: - default: {} + default: + ipaddr: 10.10.0.1 +`}, + {name: "three nodes with ipaddr", + args: []string{"n[01-02,03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + default: + ipaddr: 10.10.0.1 n02: profiles: - default network devices: - default: {} + default: + ipaddr: 10.10.0.2 + n03: + profiles: + - default + network devices: + default: + ipaddr: 10.10.0.3 +`}, + {name: "three nodes with ipaddr different network", + args: []string{"n[01-03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.1 + n02: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.2 + n03: + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.3 +`}, + {name: "three nodes with ipaddr different network, with ipmiaddr", + args: []string{"n[01-03]"}, + flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo", "ipmiaddr": "10.20.0.1"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + ipmi: + ipaddr: 10.20.0.1 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.1 + n02: + ipmi: + ipaddr: 10.20.0.2 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.2 + n03: + ipmi: + ipaddr: 10.20.0.3 + profiles: + - default + network devices: + foo: + ipaddr: 10.10.0.3 `}, } for _, tt := range tests { db, err = node.TestNew([]byte(nodes_yml)) assert.NoError(t, err) + fmt.Printf("Running test: %s\n", tt.name) t.Run(tt.name, func(t *testing.T) { + // store global NodeConf as the NodeConf.NetDevs["default"] will be delete + // in the main.go + tmpConfNet := NodeConf.NetDevs["default"] + //tmpConf := NodeConf + //tmpKernel := NodeConf.Kernel baseCmd.SetArgs(tt.args) + for key, val := range tt.flags { + baseCmd.Flags().Set(key, val) + } err = baseCmd.Execute() if (err != nil) != tt.wantErr { t.Errorf("Got unwanted error: %s", err) @@ -83,7 +216,15 @@ nodes: } if buf.String() != tt.stdout { t.Errorf("Got wrong output, got:'%s'\nwant:'%s'", buf.String(), tt.stdout) + return } + NodeConf.NetDevs["default"] = tmpConfNet + for key, _ := range tt.flags { + baseCmd.Flags().Set(key, "hark") + } + + //NodeConf = tmpConf + //NodeConf.Kernel = node.NewConf().Kernel }) } } diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 4ee8deca..9f89255a 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -382,3 +382,30 @@ func GetByName(node interface{}, name string) (string, error) { myEntry := entryField.Interface().(Entry) return myEntry.Get(), nil } + +/* +Check if the Netdev is empty, so has no values set +*/ +func (dev *NetDevs) Empty() bool { + if dev == nil { + return true + } + varType := reflect.TypeOf(*dev) + varVal := reflect.ValueOf(*dev) + if varVal.IsZero() { + return true + } + for i := 0; i < varType.NumField(); i++ { + if varType.Field(i).Type.Kind() == reflect.String && !varVal.Field(i).IsZero() { + val := varVal.Field(i).Interface().(string) + if val != "" { + return false + } + } else if varType.Field(i).Type == reflect.TypeOf(map[string]string{}) { + if len(varVal.Field(i).Interface().(map[string]string)) != 0 { + return false + } + } + } + return true +} diff --git a/internal/pkg/node/methods_test.go b/internal/pkg/node/methods_test.go new file mode 100644 index 00000000..d17f1529 --- /dev/null +++ b/internal/pkg/node/methods_test.go @@ -0,0 +1,32 @@ +package node + +import "testing" + +func Test_Empty(t *testing.T) { + var netdev NetDevs + var netdevPtr *NetDevs + + t.Run("test for empty", func(t *testing.T) { + if netdev.Empty() != true { + t.Errorf("netdev must be empty") + } + }) + t.Run("test for non empty", func(t *testing.T) { + netdev.Device = "foo" + if netdev.Empty() == true { + t.Errorf("netdev must be non empty") + } + }) + t.Run("test for nil pointer", func(t *testing.T) { + if netdevPtr.Empty() != true { + t.Errorf("netdev must be empty") + } + }) + t.Run("test for pointer assigned", func(t *testing.T) { + netdev.Ipaddr = "10.10.10.1" + netdevPtr = &netdev + if netdevPtr.Empty() == true { + t.Errorf("netdev must be empty") + } + }) +} From d34e496d4230028d50ce22b5f6adf328e5ab22db Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Wed, 8 Mar 2023 11:56:46 +0100 Subject: [PATCH 16/22] wwctl node add without global variables Signed-off-by: Christian Goll --- internal/app/wwctl/node/add/main.go | 50 +++++++------ internal/app/wwctl/node/add/main_test.go | 93 +++++++++++------------- internal/app/wwctl/node/add/root.go | 30 ++++---- 3 files changed, 84 insertions(+), 89 deletions(-) diff --git a/internal/app/wwctl/node/add/main.go b/internal/app/wwctl/node/add/main.go index dc24299e..d0d919a8 100644 --- a/internal/app/wwctl/node/add/main.go +++ b/internal/app/wwctl/node/add/main.go @@ -1,8 +1,6 @@ package add import ( - "os" - "gopkg.in/yaml.v2" apinode "github.com/hpcng/warewulf/internal/pkg/api/node" @@ -11,27 +9,33 @@ import ( "github.com/spf13/cobra" ) -func CobraRunE(cmd *cobra.Command, args []string) error { - // remove the default network as all network values are assigned - // to this network - if _, ok := NodeConf.NetDevs["default"]; ok && NetName != "" { - netDev := *NodeConf.NetDevs["default"] - NodeConf.NetDevs[NetName] = &netDev - delete(NodeConf.NetDevs, "default") - } else { - if NodeConf.NetDevs["default"].Empty() { - delete(NodeConf.NetDevs, "default") +/* +RunE needs a function of type func(*cobraCommand,[]string) err, but +in order to avoid global variables which mess up testing a function of +the required type is returned +*/ +func CobraRunE(vars *variables) func(cmd *cobra.Command, args []string) error { + return func(cmd *cobra.Command, args []string) error { + // remove the default network as all network values are assigned + // to this network + if _, ok := vars.nodeConf.NetDevs["default"]; ok && vars.netName != "" { + netDev := *vars.nodeConf.NetDevs["default"] + vars.nodeConf.NetDevs[vars.netName] = &netDev + delete(vars.nodeConf.NetDevs, "default") + } else { + if vars.nodeConf.NetDevs["default"].Empty() { + delete(vars.nodeConf.NetDevs, "default") + } } + buffer, err := yaml.Marshal(vars.nodeConf) + if err != nil { + wwlog.Error("Cant marshall nodeInfo", err) + return err + } + set := wwapiv1.NodeAddParameter{ + NodeConfYaml: string(buffer[:]), + NodeNames: args, + } + return apinode.NodeAdd(&set) } - buffer, err := yaml.Marshal(NodeConf) - if err != nil { - wwlog.Error("Cant marshall nodeInfo", err) - os.Exit(1) - } - set := wwapiv1.NodeAddParameter{ - NodeConfYaml: string(buffer[:]), - NodeNames: args, - } - - return apinode.NodeAdd(&set) } diff --git a/internal/app/wwctl/node/add/main_test.go b/internal/app/wwctl/node/add/main_test.go index d6935790..98c8e47e 100644 --- a/internal/app/wwctl/node/add/main_test.go +++ b/internal/app/wwctl/node/add/main_test.go @@ -2,7 +2,6 @@ package add import ( "bytes" - "fmt" "testing" "github.com/hpcng/warewulf/internal/pkg/node" @@ -12,29 +11,12 @@ import ( ) func Test_Add(t *testing.T) { - t.Helper() - conf_yml := ` -WW_INTERNAL: 0 - ` - nodes_yml := ` -WW_INTERNAL: 43 -` - conf := warewulfconf.New() - err := conf.Read([]byte(conf_yml)) - assert.NoError(t, err) - db, err := node.TestNew([]byte(nodes_yml)) - assert.NoError(t, err) - warewulfd.SetNoDaemon() - buf := new(bytes.Buffer) - baseCmd.SetOut(buf) - baseCmd.SetErr(buf) tests := []struct { name string args []string wantErr bool stdout string outDb string - flags map[string]string }{ {name: "single node add", args: []string{"n01"}, @@ -48,8 +30,7 @@ nodes: - default `}, {name: "single node add, profile foo", - args: []string{"n01"}, - flags: map[string]string{"profile": "foo"}, + args: []string{"--profile=foo", "n01"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -60,8 +41,7 @@ nodes: - foo `}, {name: "single node add with Kernel args", - args: []string{"n01"}, - flags: map[string]string{"kernelargs": "foo"}, + args: []string{"--kernelargs=foo", "n01"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -87,9 +67,8 @@ nodes: profiles: - default `}, - {name: "single node with ipaddr", - args: []string{"n01"}, - flags: map[string]string{"ipaddr": "10.10.0.1"}, + {name: "single node with ipaddr6", + args: []string{"--ipaddr6=fdaa::1", "n01"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -100,11 +79,24 @@ nodes: - default network devices: default: - ipaddr: 10.10.0.1 + ip6addr: fdaa::1 +`}, + {name: "single node with ipaddr", + args: []string{"--ipaddr=10.0.0.1", "n01"}, + wantErr: false, + stdout: "", + outDb: `WW_INTERNAL: 43 +nodeprofiles: {} +nodes: + n01: + profiles: + - default + network devices: + default: + ipaddr: 10.0.0.1 `}, {name: "three nodes with ipaddr", - args: []string{"n[01-02,03]"}, - flags: map[string]string{"ipaddr": "10.10.0.1"}, + args: []string{"--ipaddr=10.10.0.1", "n[01-02,03]"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -130,8 +122,7 @@ nodes: ipaddr: 10.10.0.3 `}, {name: "three nodes with ipaddr different network", - args: []string{"n[01-03]"}, - flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo"}, + args: []string{"--ipaddr=10.10.0.1", "--netname=foo", "n[01-03]"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -157,8 +148,7 @@ nodes: ipaddr: 10.10.0.3 `}, {name: "three nodes with ipaddr different network, with ipmiaddr", - args: []string{"n[01-03]"}, - flags: map[string]string{"ipaddr": "10.10.0.1", "netname": "foo", "ipmiaddr": "10.20.0.1"}, + args: []string{"--ipaddr=10.10.0.1", "--netname=foo", "--ipmiaddr=10.20.0.1", "n[01-03]"}, wantErr: false, stdout: "", outDb: `WW_INTERNAL: 43 @@ -190,41 +180,42 @@ nodes: ipaddr: 10.10.0.3 `}, } + conf_yml := ` +WW_INTERNAL: 0 + ` + nodes_yml := ` +WW_INTERNAL: 43 +` + conf := warewulfconf.New() + err := conf.Read([]byte(conf_yml)) + assert.NoError(t, err) + db, err := node.TestNew([]byte(nodes_yml)) + assert.NoError(t, err) + warewulfd.SetNoDaemon() for _, tt := range tests { db, err = node.TestNew([]byte(nodes_yml)) assert.NoError(t, err) - fmt.Printf("Running test: %s\n", tt.name) + t.Logf("Running test: %s\n", tt.name) t.Run(tt.name, func(t *testing.T) { - // store global NodeConf as the NodeConf.NetDevs["default"] will be delete - // in the main.go - tmpConfNet := NodeConf.NetDevs["default"] - //tmpConf := NodeConf - //tmpKernel := NodeConf.Kernel + baseCmd := GetCommand() baseCmd.SetArgs(tt.args) - for key, val := range tt.flags { - baseCmd.Flags().Set(key, val) - } + buf := new(bytes.Buffer) + baseCmd.SetOut(buf) + baseCmd.SetErr(buf) err = baseCmd.Execute() if (err != nil) != tt.wantErr { t.Errorf("Got unwanted error: %s", err) - return + t.FailNow() } dump := string(db.DBDump()) if dump != tt.outDb { t.Errorf("DB dump is wrong, got:'%s'\nwant:'%s'", dump, tt.outDb) - return + t.FailNow() } if buf.String() != tt.stdout { t.Errorf("Got wrong output, got:'%s'\nwant:'%s'", buf.String(), tt.stdout) - return + t.FailNow() } - NodeConf.NetDevs["default"] = tmpConfNet - for key, _ := range tt.flags { - baseCmd.Flags().Set(key, "hark") - } - - //NodeConf = tmpConf - //NodeConf.Kernel = node.NewConf().Kernel }) } } diff --git a/internal/app/wwctl/node/add/root.go b/internal/app/wwctl/node/add/root.go index 76297f9a..c498187f 100644 --- a/internal/app/wwctl/node/add/root.go +++ b/internal/app/wwctl/node/add/root.go @@ -10,23 +10,26 @@ import ( "github.com/spf13/cobra" ) -var ( - baseCmd = &cobra.Command{ +// Holds the variables which are needed in CobraRunE +type variables struct { + netName string + nodeConf node.NodeConf +} + +// Returns the newly created command +func GetCommand() *cobra.Command { + vars := variables{} + vars.nodeConf = node.NewConf() + baseCmd := &cobra.Command{ DisableFlagsInUseLine: true, Use: "add [OPTIONS] NODENAME", Short: "Add new node to Warewulf", Long: "This command will add a new node named NODENAME to Warewulf.", - RunE: CobraRunE, + RunE: CobraRunE(&vars), Args: cobra.MinimumNArgs(1), } - NodeConf node.NodeConf - NetName string -) - -func init() { - NodeConf = node.NewConf() - NodeConf.CreateFlags(baseCmd, []string{}) - baseCmd.PersistentFlags().StringVar(&NetName, "netname", "", "Set network name for network options") + vars.nodeConf.CreateFlags(baseCmd, []string{"tagdel", "nettagdel", "ipmitagdel"}) + baseCmd.PersistentFlags().StringVar(&vars.netName, "netname", "", "Set network name for network options") // register the command line completions if err := baseCmd.RegisterFlagCompletionFunc("container", func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { @@ -65,9 +68,6 @@ func init() { log.Println(err) } -} - -// GetRootCommand returns the root cobra.Command for the application. -func GetCommand() *cobra.Command { + // GetRootCommand returns the root cobra.Command for the application. return baseCmd } From 8c95a57089f1d4a908423948cdb936deb1003e9a Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Wed, 22 Mar 2023 15:30:33 -0600 Subject: [PATCH 17/22] Fixes to build process * Fixed a misspelling of genconfig in Makefile * Updated completions path in warewulf.spec.in Signed-off-by: Jonathon Anderson --- Makefile | 2 +- warewulf.spec.in | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index b3d61360..e973f9ce 100644 --- a/Makefile +++ b/Makefile @@ -203,7 +203,7 @@ files: all install -m 0644 include/firewalld/warewulf.xml $(DESTDIR)$(FIREWALLDDIR) install -m 0644 include/systemd/warewulfd.service $(DESTDIR)$(SYSTEMDDIR) install -m 0644 LICENSE.md $(DESTDIR)$(WWDOCDIR) - ./wwctl genconf completions > $(DESTDIR)$(BASHCOMPDIR)/wwctl + ./wwctl genconfig completions > $(DESTDIR)$(BASHCOMPDIR)/wwctl cp man_pages/*.1* $(DESTDIR)$(MANDIR)/man1/ cp man_pages/*.5* $(DESTDIR)$(MANDIR)/man5/ install -m 0644 staticfiles/README-ipxe.md $(DESTDIR)$(WWDATADIR)/ipxe diff --git a/warewulf.spec.in b/warewulf.spec.in index 5f57ffb2..fd0c32c0 100644 --- a/warewulf.spec.in +++ b/warewulf.spec.in @@ -118,7 +118,7 @@ getent group %{wwgroup} >/dev/null || groupadd -r %{wwgroup} %dir %{_sysconfdir}/warewulf %config(noreplace) %{_sysconfdir}/warewulf/* %config(noreplace) %attr(0640,-,-) %{_sysconfdir}/warewulf/nodes.conf -%{_sysconfdir}/bash_completion.d/warewulf +%{_sysconfdir}/bash_completion.d/wwctl %dir %{_sharedstatedir}/warewulf %{_sharedstatedir}/warewulf/chroots From 132f14c4c34a1bb352636c3fcb8a51bcffb711ab Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Sat, 18 Mar 2023 22:34:05 -0600 Subject: [PATCH 18/22] Disable TestBatchPool This test is unreliable due to its dependency on timing. Disabling for now until a better method is implemented. Signed-off-by: Jonathon Anderson --- internal/pkg/batch/batch_test.go | 62 ++++++++++++++++---------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/internal/pkg/batch/batch_test.go b/internal/pkg/batch/batch_test.go index f3884776..c9276706 100644 --- a/internal/pkg/batch/batch_test.go +++ b/internal/pkg/batch/batch_test.go @@ -1,34 +1,34 @@ -package batch +// package batch -import ( - "testing" - "time" +// import ( +// "testing" +// "time" - "github.com/stretchr/testify/assert" -) +// "github.com/stretchr/testify/assert" +// ) -/* Submits 10 jobs into a pool that supports 2 simultaneous jobs, and - tests that only two of the jobs ran at a time by capturing the time - that they ran and comparing against the start time. */ -func TestBatchPool (t *testing.T) { - pool := New(2) - var times []time.Time - for i := 0; i <= 10; i++ { - pool.Submit(func() { - times = append(times, time.Now()) - time.Sleep(1 * time.Second) - }) - } - startTime := time.Now() - pool.Run() - assert.Equal(t, 0 * time.Second, times[0].Sub(startTime).Round(time.Second)) - assert.Equal(t, 0 * time.Second, times[1].Sub(startTime).Round(time.Second)) - assert.Equal(t, 1 * time.Second, times[2].Sub(startTime).Round(time.Second)) - assert.Equal(t, 1 * time.Second, times[3].Sub(startTime).Round(time.Second)) - assert.Equal(t, 2 * time.Second, times[4].Sub(startTime).Round(time.Second)) - assert.Equal(t, 2 * time.Second, times[5].Sub(startTime).Round(time.Second)) - assert.Equal(t, 3 * time.Second, times[6].Sub(startTime).Round(time.Second)) - assert.Equal(t, 3 * time.Second, times[7].Sub(startTime).Round(time.Second)) - assert.Equal(t, 4 * time.Second, times[8].Sub(startTime).Round(time.Second)) - assert.Equal(t, 4 * time.Second, times[9].Sub(startTime).Round(time.Second)) -} +// /* Submits 10 jobs into a pool that supports 2 simultaneous jobs, and +// tests that only two of the jobs ran at a time by capturing the time +// that they ran and comparing against the start time. */ +// func TestBatchPool (t *testing.T) { +// pool := New(2) +// var times []time.Time +// for i := 0; i <= 10; i++ { +// pool.Submit(func() { +// times = append(times, time.Now()) +// time.Sleep(1 * time.Second) +// }) +// } +// startTime := time.Now() +// pool.Run() +// assert.Equal(t, 0 * time.Second, times[0].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 0 * time.Second, times[1].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 1 * time.Second, times[2].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 1 * time.Second, times[3].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 2 * time.Second, times[4].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 2 * time.Second, times[5].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 3 * time.Second, times[6].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 3 * time.Second, times[7].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 4 * time.Second, times[8].Sub(startTime).Round(time.Second)) +// assert.Equal(t, 4 * time.Second, times[9].Sub(startTime).Round(time.Second)) +// } From fc362beebcbd126e6826b801661c14edbbfb8396 Mon Sep 17 00:00:00 2001 From: Jonathon Anderson Date: Wed, 22 Mar 2023 14:33:18 -0600 Subject: [PATCH 19/22] Add a userdocs page for using delve to debug tests Signed-off-by: Jonathon Anderson --- userdocs/contributing/debugging.rst | 310 ++++++++++++++++++++++++++++ 1 file changed, 310 insertions(+) create mode 100644 userdocs/contributing/debugging.rst diff --git a/userdocs/contributing/debugging.rst b/userdocs/contributing/debugging.rst new file mode 100644 index 00000000..cf1c256d --- /dev/null +++ b/userdocs/contributing/debugging.rst @@ -0,0 +1,310 @@ +========= +Debugging +========= + +Whether developing a new feature or fixing a bug, using the automated +test suite together with a debugger is a potent combination. This +guide here can't substitute for full documentation on a given +debugger; but it might help you get started debugging Warewulf. + +Validating the code with vet +============================ + +The Warewulf ``Makefile`` includes a ``vet`` target which runs ``go +vet`` on the full codebase. + +.. code-block:: console + + $ make vet + + +Running the full test suite +=========================== + +The Warewulf ``Makefile`` includes a ``test-it`` target which runs the +full test suite. + +.. code-block:: console + + $ make test-it + + +Using delve +=========== + +If you have a failing test but you're having trouble tracking down +why, try using a debugger to step through the test. These instructions +use delve. + + +Installing delve +---------------- + +You can install delve as a regular user directly with Go. + +.. code-block:: console + + $ go install github.com/go-delve/delve/cmd/dlv@latest + +The ``dlv`` binary will be installed by default at +``$HOME/go/bin/dlv``. You can, of course, add ``$HOME/go/bin`` to your +path if you prefer. + +.. code-block:: console + + $ PATH=$HOME/go/bin:$PATH + + +Running delve against a specific test +------------------------------------- + +You can use delve to specifically run the test suite and, even more +specifically, a single failing test. In this example delve is +instructed to run the tests for Warewulf's ``node`` package, and +specifically the ``Test_GetAllNodeInfoDefaults`` test. + +.. code-block:: console + + $ dlv test github.com/hpcng/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults + Type 'help' for list of commands. + (dlv) break node.Test_GetAllNodeInfoDefaults + Breakpoint 1 set at 0x26c0d0 for github.com/hpcng/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 + +Setting a breakpoint at ``node.Test_GetAllNodeInfoDefaults`` pauses +execution once the test starts, and allows us to ``continue`` through +all the setup prior to that point. + +.. code-block:: console + + (dlv) continue + === RUN Test_GetAllNodeInfoDefaults + > github.com/hpcng/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(35):1 total:1) (PC: 0x26c0d0) + 46: assert.Contains(t, nodeYaml.Nodes, "test_node") + 47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment) + 48: } + 49: + 50: + => 51: func Test_GetAllNodeInfoDefaults(t *testing.T) { + 52: file, writeErr := writeTestConfigFile(` + 53: nodes: + 54: test_node: {}`) + 55: if file != nil { + 56: defer os.Remove(file.Name()) + +Helpful commands from here include + +``next`` + + Execute the current line (marked by ``=>``) and proceed to the next + line. + +``step`` + + Execute the current line (marked by ``=>``) and proceed to the next + line, potentially moving into a function call. + +``list`` + + Display a contextual Go code listing, marking the next instruction. + +``locals`` + + Display all local variables in the current scope. + +``print`` + + Display (in detail) the value of a single variable from the current + scope. + +Read about other commands available within delve using the ``help`` +command. + + +Example +------- + +.. code-block:: console + + $ ~/go/bin/dlv test github.com/hpcng/warewulf/internal/pkg/node -- -test.v -test.run Test_GetAllNodeInfoDefaults + Type 'help' for list of commands. + + (dlv) break node.Test_GetAllNodeInfoDefaults + Breakpoint 1 set at 0x26c0d0 for github.com/hpcng/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 + + (dlv) break nodeinfo.go:417 + Breakpoint 2 set at 0x267f18 for github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417 + + (dlv) continue + === RUN Test_GetAllNodeInfoDefaults + > github.com/hpcng/warewulf/internal/pkg/node.Test_GetAllNodeInfoDefaults() ./internal/pkg/node/nodeyaml_test.go:51 (hits goroutine(19):1 total:1) (PC: 0x26c0d0) + 46: assert.Contains(t, nodeYaml.Nodes, "test_node") + 47: assert.Equal(t, "A single node", nodeYaml.Nodes["test_node"].Comment) + 48: } + 49: + 50: + => 51: func Test_GetAllNodeInfoDefaults(t *testing.T) { + 52: file, writeErr := writeTestConfigFile(` + 53: nodes: + 54: test_node: {}`) + 55: if file != nil { + 56: defer os.Remove(file.Name()) + + (dlv) continue + WARN : Error reading UNDEF/warewulf/defaults.conf: open UNDEF/warewulf/defaults.conf: no such file or directory + > github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:417 (hits goroutine(19):1 total:1) (PC: 0x267f18) + 412: defaultNodeConf.NetDevs = nil + 413: nodeInfo.SetDefFrom(defaultNodeConf) + 414: } + 415: + 416: // Load normal attributes + => 417: if nodeConf != nil { + 418: // If no profiles are included, automatically include the + 419: // default profile. + 420: if len(nodeConf.Profiles) == 0 { + 421: nodeInfo.Profiles.SetSlice([]string{"default"}) + 422: } else { + + (dlv) next + > github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:420 (PC: 0x267f24) + 415: + 416: // Load normal attributes + 417: if nodeConf != nil { + 418: // If no profiles are included, automatically include the + 419: // default profile. + => 420: if len(nodeConf.Profiles) == 0 { + 421: nodeInfo.Profiles.SetSlice([]string{"default"}) + 422: } else { + 423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles) + 424: } + 425: + + (dlv) next + > github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:421 (PC: 0x267f3c) + 416: // Load normal attributes + 417: if nodeConf != nil { + 418: // If no profiles are included, automatically include the + 419: // default profile. + 420: if len(nodeConf.Profiles) == 0 { + => 421: nodeInfo.Profiles.SetSlice([]string{"default"}) + 422: } else { + 423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles) + 424: } + 425: + 426: nodeInfo.SetFrom(nodeConf) + + (dlv) next + > github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:426 (PC: 0x267fec) + 421: nodeInfo.Profiles.SetSlice([]string{"default"}) + 422: } else { + 423: nodeInfo.Profiles.SetSlice(nodeConf.Profiles) + 424: } + 425: + => 426: nodeInfo.SetFrom(nodeConf) + 427: } + 428: + 429: // Load default attributes for each NetDev + 430: if defaultNetDevConf != nil { + 431: for _, netdev := range nodeInfo.NetDevs { + + (dlv) next + > github.com/hpcng/warewulf/internal/pkg/node.NewNodeInfo() ./internal/pkg/node/nodeinfo.go:430 (PC: 0x268000) + 425: + 426: nodeInfo.SetFrom(nodeConf) + 427: } + 428: + 429: // Load default attributes for each NetDev + => 430: if defaultNetDevConf != nil { + 431: for _, netdev := range nodeInfo.NetDevs { + 432: netdev.SetDefFrom(defaultNetDevConf) + 433: } + 434: } + 435: + + (dlv) print nodeInfo + github.com/hpcng/warewulf/internal/pkg/node.NodeInfo { + Id: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 1, cap: 1, [ + "test_node", + ], + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + Comment: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + ClusterName: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + ContainerName: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + Ipxe: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, ["default"],}, + RuntimeOverlay: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, ["generic"],}, + SystemOverlay: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, ["wwinit"],}, + Root: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, [ + "initramfs", + ],}, + Discoverable: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + Init: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, [ + "/sbin/init", + ],}, + AssetKey: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + Kernel: *github.com/hpcng/warewulf/internal/pkg/node.KernelEntry { + Override: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x4000158370), + Args: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001583c8),}, + Ipmi: *github.com/hpcng/warewulf/internal/pkg/node.IpmiEntry { + Ipaddr: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6600), + Netmask: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6658), + Port: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b66b0), + Gateway: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6708), + UserName: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6760), + Password: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b67b8), + Interface: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6810), + Write: (*"github.com/hpcng/warewulf/internal/pkg/node.Entry")(0x40001b6868), + Tags: map[string]*github.com/hpcng/warewulf/internal/pkg/node.Entry [],}, + Profiles: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 1, cap: 1, ["default"], + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 1, cap: 1, ["default"],}, + PrimaryNetDev: github.com/hpcng/warewulf/internal/pkg/node.Entry { + value: []string len: 0, cap: 0, nil, + altvalue: []string len: 0, cap: 0, nil, + from: "", + def: []string len: 0, cap: 0, nil,}, + NetDevs: map[string]*github.com/hpcng/warewulf/internal/pkg/node.NetDevEntry [], + Tags: map[string]*github.com/hpcng/warewulf/internal/pkg/node.Entry [],} From b84908b515a342ec9e3945db91ccb888ecf85ec9 Mon Sep 17 00:00:00 2001 From: Olaf Mersmann Date: Thu, 23 Mar 2023 20:26:10 +0100 Subject: [PATCH 20/22] Add missing packages to build on EL8 Building on a fresh Rocky Linux 8.7 box gpgme-devel and libassum-devel in addition to the packages already listed. --- userdocs/quickstart/el8.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/userdocs/quickstart/el8.rst b/userdocs/quickstart/el8.rst index 4c812914..acd0a848 100644 --- a/userdocs/quickstart/el8.rst +++ b/userdocs/quickstart/el8.rst @@ -9,7 +9,7 @@ Install Warewulf and dependencies sudo dnf groupinstall "Development Tools" sudo dnf install epel-release - sudo dnf install golang tftp-server dhcp-server nfs-utils + sudo dnf install golang tftp-server dhcp-server nfs-utils gpgpme-devel libassuan-devel git clone https://github.com/hpcng/warewulf.git cd warewulf From aa53cf866c056aa49aa6bcfe724222d3ee0db01e Mon Sep 17 00:00:00 2001 From: Brian Clemens Date: Fri, 24 Mar 2023 10:05:50 +0900 Subject: [PATCH 21/22] Add debugging page to doc index --- userdocs/index.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/userdocs/index.rst b/userdocs/index.rst index c65537cd..125a5dc0 100644 --- a/userdocs/index.rst +++ b/userdocs/index.rst @@ -38,6 +38,7 @@ Welcome to the Warewulf User Guide! :caption: Contributing Contributing + Debugging Documentation Development Environment (KVM) Development Environment (VirtualBox) From aee7738be1f7a8883d95bab31dfcb960c9d7de2f Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Fri, 24 Mar 2023 09:52:38 +0100 Subject: [PATCH 22/22] fix linting for disabled batch test Signed-off-by: Christian Goll --- internal/pkg/batch/batch_test.go | 64 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/internal/pkg/batch/batch_test.go b/internal/pkg/batch/batch_test.go index c9276706..98a4ce01 100644 --- a/internal/pkg/batch/batch_test.go +++ b/internal/pkg/batch/batch_test.go @@ -1,34 +1,36 @@ -// package batch +package batch -// import ( -// "testing" -// "time" +import ( + "testing" +) -// "github.com/stretchr/testify/assert" -// ) +/* +Submits 10 jobs into a pool that supports 2 simultaneous jobs, and -// /* Submits 10 jobs into a pool that supports 2 simultaneous jobs, and -// tests that only two of the jobs ran at a time by capturing the time -// that they ran and comparing against the start time. */ -// func TestBatchPool (t *testing.T) { -// pool := New(2) -// var times []time.Time -// for i := 0; i <= 10; i++ { -// pool.Submit(func() { -// times = append(times, time.Now()) -// time.Sleep(1 * time.Second) -// }) -// } -// startTime := time.Now() -// pool.Run() -// assert.Equal(t, 0 * time.Second, times[0].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 0 * time.Second, times[1].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 1 * time.Second, times[2].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 1 * time.Second, times[3].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 2 * time.Second, times[4].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 2 * time.Second, times[5].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 3 * time.Second, times[6].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 3 * time.Second, times[7].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 4 * time.Second, times[8].Sub(startTime).Round(time.Second)) -// assert.Equal(t, 4 * time.Second, times[9].Sub(startTime).Round(time.Second)) -// } + tests that only two of the jobs ran at a time by capturing the time + that they ran and comparing against the start time. +*/ +func TestBatchPool(t *testing.T) { + /* + pool := New(2) + var times []time.Time + for i := 0; i <= 10; i++ { + pool.Submit(func() { + times = append(times, time.Now()) + time.Sleep(1 * time.Second) + }) + } + startTime := time.Now() + pool.Run() + assert.Equal(t, 0 * time.Second, times[0].Sub(startTime).Round(time.Second)) + assert.Equal(t, 0 * time.Second, times[1].Sub(startTime).Round(time.Second)) + assert.Equal(t, 1 * time.Second, times[2].Sub(startTime).Round(time.Second)) + assert.Equal(t, 1 * time.Second, times[3].Sub(startTime).Round(time.Second)) + assert.Equal(t, 2 * time.Second, times[4].Sub(startTime).Round(time.Second)) + assert.Equal(t, 2 * time.Second, times[5].Sub(startTime).Round(time.Second)) + assert.Equal(t, 3 * time.Second, times[6].Sub(startTime).Round(time.Second)) + assert.Equal(t, 3 * time.Second, times[7].Sub(startTime).Round(time.Second)) + assert.Equal(t, 4 * time.Second, times[8].Sub(startTime).Round(time.Second)) + assert.Equal(t, 4 * time.Second, times[9].Sub(startTime).Round(time.Second)) + */ +}