Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 12 additions & 4 deletions bootstrap/kubeadm/pkg/ignition/clc/clc.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import (
"strings"
"text/template"

"github.com/coreos/go-systemd/v22/unit"
clct "github.com/flatcar/container-linux-config-transpiler/config"
ignition "github.com/flatcar/ignition/config/v2_3"
ignitionTypes "github.com/flatcar/ignition/config/v2_3/types"
Expand Down Expand Up @@ -148,7 +149,9 @@ storage:
mount:
device: {{ .Device }}
format: {{ .Filesystem }}
wipe_filesystem: {{ .Overwrite }}
{{- with .Overwrite }}
wipe_filesystem: {{ . }}
{{- end }}
label: {{ .Label }}
{{- if .ExtraOpts }}
options:
Expand Down Expand Up @@ -201,9 +204,9 @@ storage:
{{ end -}}
contents:
{{ if eq .Encoding "base64" -}}
inline: !!binary |
inline: !!binary |2
{{- else -}}
inline: |
inline: |2
{{- end }}
{{ .Content | Indent 10 }}
{{- end }}
Expand Down Expand Up @@ -274,8 +277,13 @@ func defaultTemplateFuncMap() template.FuncMap {
}
}

// mountpointName returns the systemd unit name for a given mount path, without
// the ".mount" suffix. systemd requires mount units to be named after the
// escaped mount point, and refuses to load a unit whose name does not match its
// Where= setting, so the path has to be escaped the same way `systemd-escape
// --path` does it.
func mountpointName(name string) string {
return strings.TrimPrefix(strings.ReplaceAll(name, "/", "-"), "-")
return unit.UnitNamePathEscape(name)
}

func templateYAMLIndent(i int, input string) string {
Expand Down
156 changes: 156 additions & 0 deletions bootstrap/kubeadm/pkg/ignition/clc/clc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ limitations under the License.
package clc_test

import (
"net/url"
"strings"
"testing"

ignition "github.com/flatcar/ignition/config/v2_3"
Expand Down Expand Up @@ -648,3 +650,157 @@ func TestRender(t *testing.T) {
}
})
}

func TestRenderMountUnitNames(t *testing.T) {
tests := []struct {
mountPoint string
wantUnit string
}{
{
mountPoint: "/var/lib/testdir",
wantUnit: "var-lib-testdir.mount",
},
{
mountPoint: "/var/lib/etcd-data",
wantUnit: `var-lib-etcd\x2ddata.mount`,
},
{
mountPoint: "/mnt/data-disk",
wantUnit: `mnt-data\x2ddisk.mount`,
},
{
mountPoint: "/var/lib/containerd/",
wantUnit: "var-lib-containerd.mount",
},
}

for _, tt := range tests {
t.Run(tt.mountPoint, func(t *testing.T) {
input := &cloudinit.BaseUserData{
KubeadmCommand: "kubeadm join",
DiskSetup: &bootstrapv1.DiskSetup{
Filesystems: []bootstrapv1.Filesystem{
{
Device: "/dev/disk/azure/scsi1/lun0",
Filesystem: "ext4",
Label: "test_disk",
Overwrite: ptr.To(true),
},
},
},
Mounts: []bootstrapv1.MountPoints{{"test_disk", tt.mountPoint}},
}

ignitionBytes, _, err := clc.Render(input, &bootstrapv1.ContainerLinuxConfig{}, "foo")
if err != nil {
t.Fatalf("rendering: %v", err)
}

ign, reports, err := ignition.Parse(ignitionBytes)
if err != nil {
t.Fatalf("Parsing generated Ignition: %v", err)
}

if reports.IsFatal() {
t.Fatalf("Generated Ignition has fatal reports: %s", reports)
}

var got []string
for _, unit := range ign.Systemd.Units {
if unit.Name == "kubeadm.service" {
continue
}
got = append(got, unit.Name)
}

if diff := cmp.Diff([]string{tt.wantUnit}, got); diff != "" {
t.Fatalf("Mount unit name mismatch (-want +got):\n%s", diff)
}
})
}
}

func TestRenderOptionalFilesystemOverwrite(t *testing.T) {
tests := []struct {
name string
overwrite *bool
}{
{name: "overwrite set to true", overwrite: ptr.To(true)},
{name: "overwrite set to false", overwrite: ptr.To(false)},
{name: "overwrite not set", overwrite: nil},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := &cloudinit.BaseUserData{
KubeadmCommand: "kubeadm join",
DiskSetup: &bootstrapv1.DiskSetup{
Filesystems: []bootstrapv1.Filesystem{
{
Device: "/dev/disk/azure/scsi1/lun0",
Filesystem: "ext4",
Label: "test_disk",
Overwrite: tt.overwrite,
},
},
},
}

if _, _, err := clc.Render(input, &bootstrapv1.ContainerLinuxConfig{}, "foo"); err != nil {
t.Fatalf("rendering: %v", err)
}
})
}
}

func TestRenderIndentedFileContent(t *testing.T) {
tests := []struct {
name string
content string
}{
{name: "first line indented with spaces", content: " foo: bar\nbaz: qux\n"},
{name: "first line indented with a tab", content: "\tfoo: bar\nbaz: qux\n"},
{name: "content indented deeper than the following lines", content: " foo: bar\n baz: qux\n"},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
input := &cloudinit.BaseUserData{
KubeadmCommand: "kubeadm join",
WriteFiles: []bootstrapv1.File{
{
Path: "/etc/testfile.yaml",
Content: tt.content,
Permissions: "0644",
},
},
}

ignitionBytes, _, err := clc.Render(input, &bootstrapv1.ContainerLinuxConfig{}, "foo")
if err != nil {
t.Fatalf("rendering: %v", err)
}

ign, _, err := ignition.Parse(ignitionBytes)
if err != nil {
t.Fatalf("Parsing generated Ignition: %v", err)
}

var source string
for _, file := range ign.Storage.Files {
if file.Path == "/etc/testfile.yaml" {
source = file.Contents.Source
}
}

got, err := url.PathUnescape(strings.TrimPrefix(source, "data:,"))
if err != nil {
t.Fatalf("Decoding file contents: %v", err)
}

if diff := cmp.Diff(tt.content, got); diff != "" {
t.Fatalf("File contents mismatch (-want +got):\n%s", diff)
}
})
}
}
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ require (
github.com/adrg/xdg v0.5.3
github.com/blang/semver/v4 v4.0.0
github.com/coredns/corefile-migration v1.0.34
github.com/coreos/go-systemd/v22 v22.7.0
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc
github.com/distribution/reference v0.6.0
github.com/drone/envsubst/v2 v2.0.0-20210730161058-179042472c46
Expand Down Expand Up @@ -78,7 +79,6 @@ require (
github.com/coredns/caddy v1.1.1 // indirect
github.com/coreos/go-semver v0.3.1 // indirect
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf // indirect
github.com/coreos/go-systemd/v22 v22.7.0 // indirect
github.com/emicklei/go-restful/v3 v3.13.0 // indirect
github.com/evanphx/json-patch v5.7.0+incompatible // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
Expand Down