Merge pull request #1303 from mslacken/softlink
create soft links from overlays
This commit is contained in:
@@ -29,6 +29,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
||||
- Document "known issues."
|
||||
- Add `wwctl <node|profile> <add|set> --kernelversion` to specify the desired kernel version or path. #1556
|
||||
- Add `wwctl container kernels` to list discovered kernels from containers. #1556
|
||||
- Add possibility to define a softlink target with an overlay template
|
||||
- Support defining a symlink with an overlay template. #1303
|
||||
- New "localtime" overlay to define the system time zone. #1303
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
warewulfconf "github.com/warewulf/warewulf/internal/pkg/config"
|
||||
@@ -122,3 +123,16 @@ func createIgnitionJson(node *node.Node) string {
|
||||
tmpYaml, _ := json.Marshal(&conf)
|
||||
return string(tmpYaml)
|
||||
}
|
||||
|
||||
func importSoftlink(lnk string) string {
|
||||
target, err := filepath.EvalSymlinks(lnk)
|
||||
if err != nil {
|
||||
return "abort"
|
||||
}
|
||||
wwlog.Debug("importing softlink pointing to: %s", target)
|
||||
return softlink(target)
|
||||
}
|
||||
|
||||
func softlink(target string) string {
|
||||
return fmt.Sprintf("{{ /* softlink \"%s\" */ }}", target)
|
||||
}
|
||||
|
||||
@@ -238,13 +238,18 @@ func BuildOverlayIndir(nodeData node.Node, overlayNames []string, outputDir stri
|
||||
// search for magic file name comment
|
||||
fileScanner := bufio.NewScanner(bytes.NewReader(buffer.Bytes()))
|
||||
fileScanner.Split(ScanLines)
|
||||
reg := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
|
||||
regFile := regexp.MustCompile(`.*{{\s*/\*\s*file\s*["'](.*)["']\s*\*/\s*}}.*`)
|
||||
regLink := regexp.MustCompile(`.*{{\s*/\*\s*softlink\s*["'](.*)["']\s*\*/\s*}}.*`)
|
||||
foundFileComment := false
|
||||
for fileScanner.Scan() {
|
||||
line := fileScanner.Text()
|
||||
filenameFromTemplate := reg.FindAllStringSubmatch(line, -1)
|
||||
if len(filenameFromTemplate) != 0 {
|
||||
wwlog.Debug("Found multiple comment, new filename %s", filenameFromTemplate[0][1])
|
||||
filenameFromTemplate := regFile.FindAllStringSubmatch(line, -1)
|
||||
softlinkFromTemplate := regLink.FindAllStringSubmatch(line, -1)
|
||||
if len(softlinkFromTemplate) != 0 {
|
||||
wwlog.Debug("Creating soft link %s -> %s", destFileName, softlinkFromTemplate[0][1])
|
||||
return os.Symlink(softlinkFromTemplate[0][1], path.Join(outputDir, destFileName))
|
||||
} else if len(filenameFromTemplate) != 0 {
|
||||
wwlog.Debug("Writing file %s", filenameFromTemplate[0][1])
|
||||
if foundFileComment {
|
||||
err = CarefulWriteBuffer(path.Join(outputDir, destFileName),
|
||||
fileBuffer, backupFile, info.Mode())
|
||||
@@ -371,10 +376,13 @@ func RenderTemplateFile(fileName string, data TemplateStruct) (
|
||||
"Include": templateFileInclude,
|
||||
"IncludeFrom": templateContainerFileInclude,
|
||||
"IncludeBlock": templateFileBlock,
|
||||
"ImportLink": importSoftlink,
|
||||
"basename": path.Base,
|
||||
"inc": func(i int) int { return i + 1 },
|
||||
"dec": func(i int) int { return i - 1 },
|
||||
"file": func(str string) string { return fmt.Sprintf("{{ /* file \"%s\" */ }}", str) },
|
||||
"softlink": softlink,
|
||||
"readlink": filepath.EvalSymlinks,
|
||||
"IgnitionJson": func() string {
|
||||
str := createIgnitionJson(data.ThisNode)
|
||||
if str != "" {
|
||||
|
||||
56
overlays/localtime/internal/localtime_test.go
Normal file
56
overlays/localtime/internal/localtime_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package localtime
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/warewulf/warewulf/internal/app/wwctl/overlay/show"
|
||||
"github.com/warewulf/warewulf/internal/pkg/config"
|
||||
"github.com/warewulf/warewulf/internal/pkg/testenv"
|
||||
"github.com/warewulf/warewulf/internal/pkg/wwlog"
|
||||
)
|
||||
|
||||
func Test_localtimeOverlay(t *testing.T) {
|
||||
env := testenv.New(t)
|
||||
defer env.RemoveAll(t)
|
||||
env.ImportFile(t, "etc/warewulf/nodes.conf", "nodes.conf")
|
||||
assert.NoError(t, config.Get().Read(env.GetPath("etc/warewulf/warewulf.conf")))
|
||||
env.ImportFile(t, "var/lib/warewulf/overlays/localtime/rootfs/etc/localtime.ww", "../rootfs/etc/localtime.ww")
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
args []string
|
||||
log string
|
||||
}{
|
||||
{
|
||||
name: "/etc/localtime",
|
||||
args: []string{"--render", "node1", "localtime", "etc/localtime.ww"},
|
||||
log: localtime,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
cmd := show.GetCommand()
|
||||
cmd.SetArgs(tt.args)
|
||||
stdout := bytes.NewBufferString("")
|
||||
stderr := bytes.NewBufferString("")
|
||||
logbuf := bytes.NewBufferString("")
|
||||
cmd.SetOut(stdout)
|
||||
cmd.SetErr(stderr)
|
||||
wwlog.SetLogWriter(logbuf)
|
||||
err := cmd.Execute()
|
||||
assert.NoError(t, err)
|
||||
assert.Empty(t, stdout.String())
|
||||
assert.Empty(t, stderr.String())
|
||||
assert.Equal(t, tt.log, logbuf.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const localtime string = `backupFile: true
|
||||
writeFile: true
|
||||
Filename: etc/localtime
|
||||
{{ /* softlink "/usr/share/zoneinfo/GMT" */ }}
|
||||
`
|
||||
4
overlays/localtime/internal/nodes.conf
Normal file
4
overlays/localtime/internal/nodes.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
nodes:
|
||||
node1:
|
||||
tags:
|
||||
localtime: "GMT"
|
||||
1
overlays/localtime/rootfs/etc/localtime.ww
Normal file
1
overlays/localtime/rootfs/etc/localtime.ww
Normal file
@@ -0,0 +1 @@
|
||||
{{ if .Tags.localtime }}{{ printf "%s/%s" "/usr/share/zoneinfo" .Tags.localtime | softlink }}{{ else }}{{ ImportLink "/etc/localtime" }}{{ end }}
|
||||
@@ -212,6 +212,22 @@ A given string can be split into substrings.
|
||||
{{ $y := (split $x ":") -}}
|
||||
{{ range $y }} {{.}} {{ end }}
|
||||
|
||||
softlink
|
||||
^^^^^^^^
|
||||
|
||||
Creates a soft link to the given string for the template.
|
||||
|
||||
ImportLink
|
||||
^^^^^^^^^^
|
||||
|
||||
Evaluates the soft link on the Warewulf server and
|
||||
then create the soft link to it in the overlay.
|
||||
|
||||
readlink
|
||||
^^^^^^^^
|
||||
|
||||
Evaluates the soft link on the Warewulf server and returns the target.
|
||||
|
||||
|
||||
Node specific files
|
||||
-------------------
|
||||
|
||||
@@ -212,6 +212,7 @@ getent group %{wwgroup} >/dev/null || groupadd -r %{wwgroup}
|
||||
%attr(-, root, root) %{_sharedstatedir}/warewulf/overlays/wicked/rootfs/*
|
||||
%attr(-, root, root) %{_sharedstatedir}/warewulf/overlays/wwclient/rootfs/*
|
||||
%attr(-, root, root) %{_sharedstatedir}/warewulf/overlays/wwinit/rootfs/*
|
||||
%attr(-, root, root) %{_sharedstatedir}/warewulf/overlays/localtime/rootfs/*
|
||||
|
||||
%attr(-, root, root) %{_bindir}/wwctl
|
||||
%attr(-, root, root) %{_prefix}/lib/firewalld/services/warewulf.xml
|
||||
|
||||
Reference in New Issue
Block a user