Files
kata-containers/src/runtime/cmd/kata-runtime/kata-env_test.go
bin 03546f75a6 runtime: change io/ioutil to io/os packages
Change io/ioutil to io/os packages because io/ioutil package
is deprecated from 1.16:

Discard => io.Discard
NopCloser => io.NopCloser
ReadAll => io.ReadAll
ReadDir => os.ReadDir
ReadFile => os.ReadFile
TempDir => os.MkdirTemp
TempFile => os.CreateTemp
WriteFile => os.WriteFile

Details: https://go.dev/doc/go1.16#ioutil

Fixes: #3265

Signed-off-by: bin <bin@hyper.sh>
2021-12-15 07:31:48 +08:00

1007 lines
23 KiB
Go

// Copyright (c) 2017 Intel Corporation
//
// SPDX-License-Identifier: Apache-2.0
//
package main
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"os"
"path"
"path/filepath"
"runtime"
goruntime "runtime"
"strings"
"testing"
"github.com/BurntSushi/toml"
vc "github.com/kata-containers/kata-containers/src/runtime/virtcontainers"
vcUtils "github.com/kata-containers/kata-containers/src/runtime/virtcontainers/utils"
specs "github.com/opencontainers/runtime-spec/specs-go"
"github.com/urfave/cli"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katatestutils"
"github.com/kata-containers/kata-containers/src/runtime/pkg/katautils"
"github.com/kata-containers/kata-containers/src/runtime/pkg/oci"
"github.com/stretchr/testify/assert"
)
var (
testHypervisorVersion = "QEMU emulator version 2.7.0+git.741f430a96-6.1, Copyright (c) 2003-2016 Fabrice Bellard and the QEMU Project developers"
)
var (
hypervisorDebug = false
enableVirtioFS = false
runtimeDebug = false
runtimeTrace = false
agentDebug = false
agentTrace = false
)
// makeVersionBinary creates a shell script with the specified file
// name. When run as "file --version", it will display the specified
// version to stdout and exit successfully.
func makeVersionBinary(file, version string) error {
err := createFile(file,
fmt.Sprintf(`#!/bin/sh
[ "$1" = "--version" ] && echo "%s"`, version))
if err != nil {
return err
}
err = os.Chmod(file, testExeFileMode)
if err != nil {
return err
}
return nil
}
func createConfig(configPath string, fileData string) error {
err := os.WriteFile(configPath, []byte(fileData), testFileMode)
if err != nil {
fmt.Fprintf(os.Stderr, "Unable to create config file %s %v\n", configPath, err)
return err
}
return nil
}
func makeRuntimeConfig(prefixDir string) (configFile string, config oci.RuntimeConfig, err error) {
const logPath = "/log/path"
hypervisorPath := filepath.Join(prefixDir, "hypervisor")
kernelPath := filepath.Join(prefixDir, "kernel")
imagePath := filepath.Join(prefixDir, "image")
kernelParams := "foo=bar xyz"
machineType := "machineType"
disableBlock := true
blockStorageDriver := "virtio-scsi"
enableIOThreads := true
hotplugVFIOOnRootBus := true
pcieRootPort := uint32(2)
disableNewNetNs := false
sharedFS := "virtio-9p"
virtioFSdaemon := filepath.Join(prefixDir, "virtiofsd")
filesToCreate := []string{
hypervisorPath,
kernelPath,
imagePath,
}
for _, file := range filesToCreate {
// files must exist and be >0 bytes.
err := katautils.WriteFile(file, "foo", testFileMode)
if err != nil {
return "", oci.RuntimeConfig{}, err
}
}
err = makeVersionBinary(hypervisorPath, testHypervisorVersion)
if err != nil {
return "", oci.RuntimeConfig{}, err
}
if enableVirtioFS {
sharedFS = "virtio-fs"
}
hypConfig := katautils.GetDefaultHypervisorConfig()
configFileOptions := katatestutils.RuntimeConfigOptions{
Hypervisor: "qemu",
HypervisorPath: hypervisorPath,
KernelPath: kernelPath,
ImagePath: imagePath,
KernelParams: kernelParams,
MachineType: machineType,
LogPath: logPath,
DefaultGuestHookPath: hypConfig.GuestHookPath,
DisableBlock: disableBlock,
BlockDeviceDriver: blockStorageDriver,
EnableIOThreads: enableIOThreads,
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
PCIeRootPort: pcieRootPort,
DisableNewNetNs: disableNewNetNs,
DefaultVCPUCount: hypConfig.NumVCPUs,
DefaultMaxVCPUCount: hypConfig.DefaultMaxVCPUs,
DefaultMemSize: hypConfig.MemorySize,
DefaultMsize9p: hypConfig.Msize9p,
HypervisorDebug: hypervisorDebug,
RuntimeDebug: runtimeDebug,
RuntimeTrace: runtimeTrace,
AgentDebug: agentDebug,
AgentTrace: agentTrace,
SharedFS: sharedFS,
VirtioFSDaemon: virtioFSdaemon,
}
runtimeConfig := katatestutils.MakeRuntimeConfigFileData(configFileOptions)
configFile = path.Join(prefixDir, "runtime.toml")
err = createConfig(configFile, runtimeConfig)
if err != nil {
return "", oci.RuntimeConfig{}, err
}
_, config, err = katautils.LoadConfiguration(configFile, true)
if err != nil {
return "", oci.RuntimeConfig{}, err
}
return configFile, config, nil
}
func getExpectedAgentDetails(config oci.RuntimeConfig) (AgentInfo, error) {
agentConfig := config.AgentConfig
return AgentInfo{
Debug: agentConfig.Debug,
Trace: agentConfig.Trace,
}, nil
}
// nolint: unused, deadcode
func genericGetExpectedHostDetails(tmpdir string, expectedVendor string, expectedModel string, expectedVMContainerCapable bool) (HostInfo, error) {
type filesToCreate struct {
file string
contents string
}
const expectedKernelVersion = "99.1"
const expectedArch = goruntime.GOARCH
expectedDistro := DistroInfo{
Name: "Foo",
Version: "42",
}
expectedCPU := CPUInfo{
Vendor: expectedVendor,
Model: expectedModel,
}
expectedSupportVSocks, _ := vcUtils.SupportsVsocks()
expectedHostDetails := HostInfo{
Kernel: expectedKernelVersion,
Architecture: expectedArch,
Distro: expectedDistro,
CPU: expectedCPU,
VMContainerCapable: expectedVMContainerCapable,
SupportVSocks: expectedSupportVSocks,
}
testProcCPUInfo := filepath.Join(tmpdir, "cpuinfo")
testOSRelease := filepath.Join(tmpdir, "os-release")
// XXX: This file is *NOT* created by this function on purpose
// (to ensure the only file checked by the tests is
// testOSRelease). osReleaseClr handling is tested in
// utils_test.go.
testOSReleaseClr := filepath.Join(tmpdir, "os-release-clr")
testProcVersion := filepath.Join(tmpdir, "proc-version")
// override
procVersion = testProcVersion
osRelease = testOSRelease
osReleaseClr = testOSReleaseClr
procCPUInfo = testProcCPUInfo
procVersionContents := fmt.Sprintf("Linux version %s a b c",
expectedKernelVersion)
osReleaseContents := fmt.Sprintf(`
NAME="%s"
VERSION_ID="%s"
`, expectedDistro.Name, expectedDistro.Version)
procCPUInfoContents := fmt.Sprintf(`
%s : %s
%s : %s
`,
archCPUVendorField,
expectedCPU.Vendor,
archCPUModelField,
expectedCPU.Model)
data := []filesToCreate{
{procVersion, procVersionContents},
{osRelease, osReleaseContents},
{procCPUInfo, procCPUInfoContents},
}
for _, d := range data {
err := createFile(d.file, d.contents)
if err != nil {
return HostInfo{}, err
}
}
if goruntime.GOARCH == "arm64" {
expectedHostDetails.CPU.Vendor = "ARM Limited"
expectedHostDetails.CPU.Model = "v8"
}
// set CPU num.
// will not set memory info, because memory may be changed.
expectedHostDetails.CPU.CPUs = runtime.NumCPU()
return expectedHostDetails, nil
}
func getExpectedHypervisor(config oci.RuntimeConfig) HypervisorInfo {
info := HypervisorInfo{
Version: testHypervisorVersion,
Path: config.HypervisorConfig.HypervisorPath,
MachineType: config.HypervisorConfig.HypervisorMachineType,
BlockDeviceDriver: config.HypervisorConfig.BlockDeviceDriver,
Msize9p: config.HypervisorConfig.Msize9p,
MemorySlots: config.HypervisorConfig.MemSlots,
Debug: config.HypervisorConfig.Debug,
EntropySource: config.HypervisorConfig.EntropySource,
SharedFS: config.HypervisorConfig.SharedFS,
VirtioFSDaemon: config.HypervisorConfig.VirtioFSDaemon,
HotplugVFIOOnRootBus: config.HypervisorConfig.HotplugVFIOOnRootBus,
PCIeRootPort: config.HypervisorConfig.PCIeRootPort,
}
if os.Geteuid() == 0 {
// This assumes the test hypervisor is a non-hybrid-vsock
// one (such as QEMU).
info.SocketPath = ""
} else {
info.SocketPath = unknown
}
return info
}
func getExpectedImage(config oci.RuntimeConfig) ImageInfo {
return ImageInfo{
Path: config.HypervisorConfig.ImagePath,
}
}
func getExpectedKernel(config oci.RuntimeConfig) KernelInfo {
return KernelInfo{
Path: config.HypervisorConfig.KernelPath,
Parameters: strings.Join(vc.SerializeParams(config.HypervisorConfig.KernelParams, "="), " "),
}
}
func getExpectedRuntimeDetails(config oci.RuntimeConfig, configFile string) RuntimeInfo {
runtimePath, _ := os.Executable()
runtimeVersionInfo := constructVersionInfo(katautils.VERSION)
runtimeVersionInfo.Commit = katautils.COMMIT
return RuntimeInfo{
Version: RuntimeVersionInfo{
Version: runtimeVersionInfo,
OCI: specs.Version,
},
Config: RuntimeConfigInfo{
Path: configFile,
},
Path: runtimePath,
Debug: config.Debug,
Trace: config.Trace,
DisableNewNetNs: config.DisableNewNetNs,
}
}
func getExpectedSettings(config oci.RuntimeConfig, tmpdir, configFile string) (EnvInfo, error) {
meta := getExpectedMetaInfo()
runtime := getExpectedRuntimeDetails(config, configFile)
agent, err := getExpectedAgentDetails(config)
if err != nil {
return EnvInfo{}, err
}
host, err := getExpectedHostDetails(tmpdir)
if err != nil {
return EnvInfo{}, err
}
hypervisor := getExpectedHypervisor(config)
kernel := getExpectedKernel(config)
image := getExpectedImage(config)
env := EnvInfo{
Meta: meta,
Runtime: runtime,
Hypervisor: hypervisor,
Image: image,
Kernel: kernel,
Agent: agent,
Host: host,
}
return env, nil
}
func getExpectedMetaInfo() MetaInfo {
return MetaInfo{
Version: formatVersion,
}
}
func TestEnvGetMetaInfo(t *testing.T) {
expectedMeta := getExpectedMetaInfo()
meta := getMetaInfo()
assert.Equal(t, expectedMeta, meta)
}
func TestEnvGetHostInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
host, err := getHostInfo()
assert.NoError(t, err)
// Free/Available are changing
expectedHostDetails.Memory = host.Memory
assert.Equal(t, expectedHostDetails, host)
// check CPU cores and memory info
assert.Equal(t, true, host.CPU.CPUs > 0)
assert.Equal(t, true, host.Memory.Total > 0)
assert.Equal(t, true, host.Memory.Free > 0)
assert.Equal(t, true, host.Memory.Available > 0)
}
func TestEnvGetHostInfoNoProcCPUInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, err = getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
err = os.Remove(procCPUInfo)
assert.NoError(t, err)
_, err = getHostInfo()
assert.Error(t, err)
}
func TestEnvGetHostInfoNoOSRelease(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, err = getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
err = os.Remove(osRelease)
assert.NoError(t, err)
_, err = getHostInfo()
assert.NoError(t, err)
}
func TestEnvGetHostInfoNoProcVersion(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, err = getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
err = os.Remove(procVersion)
assert.NoError(t, err)
_, err = getHostInfo()
assert.Error(t, err)
}
func TestEnvGetEnvInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
// Run test twice to ensure the individual component debug+trace
// options are tested.
for _, toggle := range []bool{false, true} {
hypervisorDebug = toggle
enableVirtioFS = toggle
runtimeDebug = toggle
runtimeTrace = toggle
agentDebug = toggle
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
expectedEnv, err := getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
env, err := getEnvInfo(configFile, config)
assert.NoError(t, err)
// Free/Available are changing
expectedEnv.Host.Memory = env.Host.Memory
assert.Equal(t, expectedEnv, env)
}
}
func TestEnvGetEnvInfoNoHypervisorVersion(t *testing.T) {
assert := assert.New(t)
tmpdir, err := os.MkdirTemp("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(err)
expectedEnv, err := getExpectedSettings(config, tmpdir, configFile)
assert.NoError(err)
err = os.Remove(config.HypervisorConfig.HypervisorPath)
assert.NoError(err)
expectedEnv.Hypervisor.Version = unknown
env, err := getEnvInfo(configFile, config)
assert.NoError(err)
// Free/Available are changing
expectedEnv.Host.Memory = env.Host.Memory
assert.Equal(expectedEnv, env)
}
func TestEnvGetEnvInfoAgentError(t *testing.T) {
assert := assert.New(t)
tmpdir, err := os.MkdirTemp("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
_, _, err = makeRuntimeConfig(tmpdir)
assert.NoError(err)
}
func TestEnvGetEnvInfoNoOSRelease(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
err = os.Remove(osRelease)
assert.NoError(t, err)
_, err = getEnvInfo(configFile, config)
assert.NoError(t, err)
}
func TestEnvGetEnvInfoNoProcCPUInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
err = os.Remove(procCPUInfo)
assert.NoError(t, err)
_, err = getEnvInfo(configFile, config)
assert.Error(t, err)
}
func TestEnvGetEnvInfoNoProcVersion(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
err = os.Remove(procVersion)
assert.NoError(t, err)
_, err = getEnvInfo(configFile, config)
assert.Error(t, err)
}
func TestEnvGetRuntimeInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
expectedRuntime := getExpectedRuntimeDetails(config, configFile)
runtime := getRuntimeInfo(configFile, config)
assert.Equal(t, expectedRuntime, runtime)
}
func TestEnvGetAgentInfo(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
_, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
expectedAgent, err := getExpectedAgentDetails(config)
assert.NoError(t, err)
agent, err := getAgentInfo(config)
assert.NoError(t, err)
assert.Equal(t, expectedAgent, agent)
agentConfig := config.AgentConfig
agentConfig.Debug = true
config.AgentConfig = agentConfig
agent, err = getAgentInfo(config)
assert.NoError(t, err)
assert.True(t, agent.Debug)
agentConfig.Trace = true
config.AgentConfig = agentConfig
agent, err = getAgentInfo(config)
assert.NoError(t, err)
assert.True(t, agent.Trace)
}
func testEnvShowTOMLSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
runtime := RuntimeInfo{}
hypervisor := HypervisorInfo{
Path: "/resolved/hypervisor/path",
MachineType: "hypervisor-machine-type",
}
image := ImageInfo{
Path: "/resolved/image/path",
}
kernel := KernelInfo{
Path: "/kernel/path",
Parameters: "foo=bar xyz",
}
agent := AgentInfo{}
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
env := EnvInfo{
Runtime: runtime,
Hypervisor: hypervisor,
Image: image,
Kernel: kernel,
Agent: agent,
Host: expectedHostDetails,
}
err = writeTOMLSettings(env, tmpfile)
if err != nil {
return err
}
contents, err := katautils.GetFileContents(tmpfile.Name())
assert.NoError(t, err)
buf := new(bytes.Buffer)
encoder := toml.NewEncoder(buf)
err = encoder.Encode(env)
assert.NoError(t, err)
expectedContents := buf.String()
assert.Equal(t, expectedContents, contents)
return nil
}
func testEnvShowJSONSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
runtime := RuntimeInfo{}
hypervisor := HypervisorInfo{
Path: "/resolved/hypervisor/path",
MachineType: "hypervisor-machine-type",
}
image := ImageInfo{
Path: "/resolved/image/path",
}
kernel := KernelInfo{
Path: "/kernel/path",
Parameters: "foo=bar xyz",
}
agent := AgentInfo{}
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
assert.NoError(t, err)
env := EnvInfo{
Runtime: runtime,
Hypervisor: hypervisor,
Image: image,
Kernel: kernel,
Agent: agent,
Host: expectedHostDetails,
}
err = writeJSONSettings(env, tmpfile)
if err != nil {
return err
}
contents, err := katautils.GetFileContents(tmpfile.Name())
assert.NoError(t, err)
buf := new(bytes.Buffer)
encoder := json.NewEncoder(buf)
// Ensure we have the same human readable layout
encoder.SetIndent("", " ")
err = encoder.Encode(env)
assert.NoError(t, err)
expectedContents := buf.String()
assert.Equal(t, expectedContents, contents)
return nil
}
func TestEnvShowSettings(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
tmpfile, err := os.CreateTemp("", "envShowSettings-")
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())
err = testEnvShowTOMLSettings(t, tmpdir, tmpfile)
assert.NoError(t, err)
// Reset the file to empty for next test
tmpfile.Truncate(0)
tmpfile.Seek(0, 0)
err = testEnvShowJSONSettings(t, tmpdir, tmpfile)
assert.NoError(t, err)
}
func TestEnvShowSettingsInvalidFile(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
tmpfile, err := os.CreateTemp("", "envShowSettings-")
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())
// close the file
tmpfile.Close()
err = testEnvShowTOMLSettings(t, tmpdir, tmpfile)
assert.Error(t, err)
// Reset the file to empty for next test
tmpfile.Truncate(0)
tmpfile.Seek(0, 0)
err = testEnvShowJSONSettings(t, tmpdir, tmpfile)
assert.Error(t, err)
}
func TestEnvHandleSettings(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
set := flag.NewFlagSet("test", flag.ContinueOnError)
ctx := createCLIContext(set)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = configFile
ctx.App.Metadata["runtimeConfig"] = config
tmpfile, err := os.CreateTemp("", "")
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())
err = handleSettings(tmpfile, ctx)
assert.NoError(t, err)
var env EnvInfo
_, err = toml.DecodeFile(tmpfile.Name(), &env)
assert.NoError(t, err)
}
func TestEnvHandleSettingsInvalidParams(t *testing.T) {
assert := assert.New(t)
tmpdir, err := os.MkdirTemp("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
configFile, _, err := makeRuntimeConfig(tmpdir)
assert.NoError(err)
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = configFile
err = handleSettings(nil, ctx)
assert.Error(err)
}
func TestEnvHandleSettingsEmptyMap(t *testing.T) {
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata = map[string]interface{}{}
err := handleSettings(os.Stdout, ctx)
assert.Error(t, err)
}
func TestEnvHandleSettingsInvalidFile(t *testing.T) {
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = "foo"
ctx.App.Metadata["runtimeConfig"] = oci.RuntimeConfig{}
err := handleSettings(nil, ctx)
assert.Error(t, err)
}
func TestEnvHandleSettingsInvalidConfigFileType(t *testing.T) {
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = 123
ctx.App.Metadata["runtimeConfig"] = oci.RuntimeConfig{}
err := handleSettings(os.Stderr, ctx)
assert.Error(t, err)
}
func TestEnvHandleSettingsInvalidRuntimeConfigType(t *testing.T) {
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = "/some/where"
ctx.App.Metadata["runtimeConfig"] = true
err := handleSettings(os.Stderr, ctx)
assert.Error(t, err)
}
func TestEnvCLIFunction(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
app := cli.NewApp()
set := flag.NewFlagSet("test", flag.ContinueOnError)
ctx := createCLIContextWithApp(set, app)
app.Name = "foo"
ctx.App.Metadata["configFile"] = configFile
ctx.App.Metadata["runtimeConfig"] = config
fn, ok := kataEnvCLICommand.Action.(func(context *cli.Context) error)
assert.True(t, ok)
devNull, err := os.OpenFile(os.DevNull, os.O_WRONLY, 0666)
assert.NoError(t, err)
// throw away output
savedOutputFile := defaultOutputFile
defaultOutputFile = devNull
defer func() {
defaultOutputFile = savedOutputFile
}()
err = fn(ctx)
assert.NoError(t, err)
set.Bool("json", true, "")
ctx = createCLIContextWithApp(set, app)
err = fn(ctx)
assert.NoError(t, err)
}
func TestEnvCLIFunctionFail(t *testing.T) {
tmpdir, err := os.MkdirTemp("", "")
if err != nil {
panic(err)
}
defer os.RemoveAll(tmpdir)
configFile, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(t, err)
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)
ctx := createCLIContext(nil)
ctx.App.Name = "foo"
ctx.App.Metadata["configFile"] = configFile
ctx.App.Metadata["runtimeConfig"] = config
fn, ok := kataEnvCLICommand.Action.(func(context *cli.Context) error)
assert.True(t, ok)
savedOutputFile := defaultOutputFile
// invalidate
defaultOutputFile = nil
defer func() {
defaultOutputFile = savedOutputFile
}()
err = fn(ctx)
assert.Error(t, err)
}
func TestGetHypervisorInfo(t *testing.T) {
assert := assert.New(t)
tmpdir, err := os.MkdirTemp("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
_, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(err)
info, err := getHypervisorInfo(config)
assert.NoError(err)
assert.Equal(info.Version, testHypervisorVersion)
err = os.Remove(config.HypervisorConfig.HypervisorPath)
assert.NoError(err)
info, err = getHypervisorInfo(config)
assert.NoError(err)
assert.Equal(info.Version, unknown)
}
func TestGetHypervisorInfoSocket(t *testing.T) {
assert := assert.New(t)
tmpdir, err := os.MkdirTemp("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)
_, config, err := makeRuntimeConfig(tmpdir)
assert.NoError(err)
type TestHypervisorDetails struct {
hType vc.HypervisorType
hybridVsock bool
}
hypervisors := []TestHypervisorDetails{
{vc.AcrnHypervisor, false},
{vc.ClhHypervisor, true},
{vc.FirecrackerHypervisor, true},
{vc.MockHypervisor, false},
{vc.QemuHypervisor, false},
}
config.HypervisorConfig.VMStorePath = "/foo"
config.HypervisorConfig.RunStorePath = "/bar"
for i, details := range hypervisors {
msg := fmt.Sprintf("hypervisor[%d]: %+v", i, details)
config.HypervisorType = details.hType
info, err := getHypervisorInfo(config)
assert.NoError(err, msg)
if os.Geteuid() == 0 {
if !details.hybridVsock {
assert.Equal(info.SocketPath, "", msg)
} else {
assert.NotEmpty(info.SocketPath, msg)
assert.True(strings.HasPrefix(info.SocketPath, "/"), msg)
}
} else {
assert.Equal(info.SocketPath, unknown, msg)
}
}
}