Skip to content

Commit

Permalink
manifest: update kickstart tests
Browse files Browse the repository at this point in the history
1. Kickstart tests now check if the pipeline serialization panic()s when
   unsupported options are combined.
2. When "extra" kickstart content is defined (user kickstart file), the
   pre-defined hardcoded kickstart bits aren't added to the checksum
   calculation.
  • Loading branch information
achilleas-k committed May 7, 2024
1 parent d51a75b commit 26b6c3f
Showing 1 changed file with 90 additions and 65 deletions.
155 changes: 90 additions & 65 deletions pkg/manifest/anaconda_installer_iso_tree_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,19 +146,19 @@ bootc switch --mutate-in-place --transport registry local.example.org/registry/o
func calculateInlineFileChecksum(parts ...string) string {
content := "%include /run/install/repo/test-base.ks\n"
for _, part := range parts {
content += "\n" + part
content += part
}
return fmt.Sprintf("%x", sha256.Sum256([]byte(content)))
}

func checkKickstartUnattendedOptions(stages []*osbuild.Stage, sudobits bool, extra string) error {

func checkKickstartOptions(stages []*osbuild.Stage, unattended, sudobits bool, extra string) error {
ksParts := make([]string, 0)
if sudobits {
ksParts = append(ksParts, ksSudoContent)
ksParts = append(ksParts, "\n"+ksSudoContent)
}
if extra != "" {
ksParts = append(ksParts, extra)
// adding extra bits replaces any other inline kickstart file
ksParts = []string{extra}
}

ksCopyStageOptions := findRawKickstartFileStage(stages)
Expand Down Expand Up @@ -187,42 +187,44 @@ func checkKickstartUnattendedOptions(stages []*osbuild.Stage, sudobits bool, ext
return fmt.Errorf("kickstart file path should be %q but is %q", testKsPath, ksOptions.Path)
}

// check that the unattended kickstart options are set
if ksOptions.DisplayMode != "text" {
return fmt.Errorf("unexpected kickstart display mode for unattended: %q", ksOptions.DisplayMode)
}
if !ksOptions.Reboot.Eject {
return fmt.Errorf("unattended reboot.eject kickstart option unset")
}
if !ksOptions.RootPassword.Lock {
return fmt.Errorf("unattended rootpassword.lock kickstart option unset")
}
if !ksOptions.ZeroMBR {
return fmt.Errorf("unattended zerombr kickstart option unset")
}
if !ksOptions.ClearPart.All {
return fmt.Errorf("unattended clearpart.all kickstart option unset")
}
if !ksOptions.ClearPart.InitLabel {
return fmt.Errorf("unattended clearpart.initlabel kickstart option unset")
}
if unattended {
// check that the unattended kickstart options are set
if ksOptions.DisplayMode != "text" {
return fmt.Errorf("unexpected kickstart display mode for unattended: %q", ksOptions.DisplayMode)
}
if !ksOptions.Reboot.Eject {
return fmt.Errorf("unattended reboot.eject kickstart option unset")
}
if !ksOptions.RootPassword.Lock {
return fmt.Errorf("unattended rootpassword.lock kickstart option unset")
}
if !ksOptions.ZeroMBR {
return fmt.Errorf("unattended zerombr kickstart option unset")
}
if !ksOptions.ClearPart.All {
return fmt.Errorf("unattended clearpart.all kickstart option unset")
}
if !ksOptions.ClearPart.InitLabel {
return fmt.Errorf("unattended clearpart.initlabel kickstart option unset")
}

// just check that some options are set to anything since at this level the
// values don't matter and can change based on distro defaults
if ksOptions.Lang == "" {
return fmt.Errorf("unattended lang kickstart option unset")
}
if ksOptions.Timezone == "" {
return fmt.Errorf("unattended timezone kickstart option unset")
}
if ksOptions.Keyboard == "" {
return fmt.Errorf("unattended keyboard kickstart option unset")
}
if ksOptions.AutoPart == nil {
return fmt.Errorf("unattended autopart kickstart option unset")
}
if ksOptions.Network == nil {
return fmt.Errorf("unattended network kickstart option unset")
// just check that some options are set to anything since at this level the
// values don't matter and can change based on distro defaults
if ksOptions.Lang == "" {
return fmt.Errorf("unattended lang kickstart option unset")
}
if ksOptions.Timezone == "" {
return fmt.Errorf("unattended timezone kickstart option unset")
}
if ksOptions.Keyboard == "" {
return fmt.Errorf("unattended keyboard kickstart option unset")
}
if ksOptions.AutoPart == nil {
return fmt.Errorf("unattended autopart kickstart option unset")
}
if ksOptions.Network == nil {
return fmt.Errorf("unattended network kickstart option unset")
}
}

return nil
Expand All @@ -231,7 +233,7 @@ func checkKickstartUnattendedOptions(stages []*osbuild.Stage, sudobits bool, ext
func checkRawKickstartForContainer(stages []*osbuild.Stage, extra string) error {
ksParts := []string{ksContainerContent}
if extra != "" {
ksParts = append(ksParts, extra)
ksParts = []string{extra}
}
ksCopyStageOptions := findRawKickstartFileStage(stages)
if ksCopyStageOptions == nil { // raw kickstart stage (file stage) should exist
Expand Down Expand Up @@ -330,7 +332,7 @@ func TestAnacondaISOTreeSerializeWithOS(t *testing.T) {
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
})

t.Run("unattended+sudo", func(t *testing.T) {
Expand All @@ -347,7 +349,7 @@ func TestAnacondaISOTreeSerializeWithOS(t *testing.T) {
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
})

t.Run("user-kickstart-without-sudo-bits", func(t *testing.T) {
Expand All @@ -356,7 +358,7 @@ func TestAnacondaISOTreeSerializeWithOS(t *testing.T) {
pipeline.OSPipeline = osPayload
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
Unattended: false,
UserFile: &kickstart.File{
Contents: userks,
},
Expand All @@ -367,30 +369,40 @@ func TestAnacondaISOTreeSerializeWithOS(t *testing.T) {
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
})

t.Run("unhappy/user-kickstart-with-unattended", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.OSPipeline = osPayload
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, nil, nil)
assert.Panics(t, func() { pipeline.serialize() })
})

t.Run("user-kickstart-with-sudo-bits", func(t *testing.T) {
t.Run("unhappy/user-kickstart-with-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.OSPipeline = osPayload
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
SudoNopasswd: []string{`%wheel`, `%sudo`},
UserFile: &kickstart.File{
Contents: userks,
},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, nil, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux", "org.osbuild.kickstart"),
variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
assert.Panics(t, func() { pipeline.serialize() })
})

}

func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
Expand Down Expand Up @@ -441,7 +453,7 @@ func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
})

t.Run("unattended+sudo", func(t *testing.T) {
Expand All @@ -457,15 +469,15 @@ func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, ""))
})

t.Run("user-kickstart-without-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
Unattended: false,
UserFile: &kickstart.File{
Contents: userks,
},
Expand All @@ -476,27 +488,40 @@ func TestAnacondaISOTreeSerializeWithOSTree(t *testing.T) {
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
assert.NoError(t, checkKickstartOptions(sp.Stages, pipeline.Kickstart.Unattended, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
})

t.Run("user-kickstart-with-sudo-bits", func(t *testing.T) {
t.Run("unhappy/user-kickstart-with-unattended", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: true,
SudoNopasswd: []string{`%wheel`, `%sudo`},
Path: testKsPath,
Unattended: true,
UserFile: &kickstart.File{
Contents: userks,
},
OSTree: &kickstart.OSTree{},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, []ostree.CommitSpec{ostreeCommit}, nil)
sp := pipeline.serialize()
pipeline.serializeEnd()
assert.NoError(t, checkISOTreeStages(sp.Stages, append(payloadStages, "org.osbuild.isolinux"), variantStages))
assert.NoError(t, checkKickstartUnattendedOptions(sp.Stages, len(pipeline.Kickstart.SudoNopasswd) > 0, userks))
assert.Panics(t, func() { pipeline.serialize() })
})

t.Run("unhappy/user-kickstart-with-sudo-bits", func(t *testing.T) {
userks := "%post\necho 'Some kind of text in a file sent by post'\n%end"
pipeline := newTestAnacondaISOTree()
pipeline.Kickstart = &kickstart.Options{
Path: testKsPath,
Unattended: false,
UserFile: &kickstart.File{
Contents: userks,
},
SudoNopasswd: []string{`%wheel`, `%sudo`},
OSTree: &kickstart.OSTree{},
}
pipeline.ISOLinux = true
pipeline.serializeStart(nil, nil, []ostree.CommitSpec{ostreeCommit}, nil)
assert.Panics(t, func() { pipeline.serialize() })
})
}

Expand Down

0 comments on commit 26b6c3f

Please sign in to comment.