mirror of
https://github.com/aljazceru/kata-containers.git
synced 2026-01-07 08:24:23 +01:00
Previously, the agent behaviour was controlled entirely using the `kernel_params=` config option. This mechanism suffers from a subtle problem - the runtime is not aware of how the agent will behave. From now on, all significant agent options will be controlled from the agent section in the configuration file. This allows the runtime to be more aware of -- and in control of -- such agent settings. It would also allow the underlying kernel CLI options to be modified in the future if required. This PR adds the only useful agent option as an explicit option by adding an `enable_debug=true` option to the Kata agent section in `configuration.toml`. This allows controlling agent debug to be handled in the same manner as the other debug options. This change is somewhat foundational: it permits the agent to be handled consistently with other config file sections which is useful, but arguably not essential (the old way worked). However, the new way of handling agent options will be essential when introducing agent tracing control as the runtime must be aware of the agent trace mode to allow the runtime to modify its behaviour accordingly. Signed-off-by: James O. D. Hunt <james.o.hunt@intel.com>
1230 lines
28 KiB
Go
1230 lines
28 KiB
Go
// Copyright (c) 2017 Intel Corporation
|
|
//
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
|
|
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"flag"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"os"
|
|
"path"
|
|
"path/filepath"
|
|
goruntime "runtime"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/BurntSushi/toml"
|
|
vc "github.com/kata-containers/runtime/virtcontainers"
|
|
vcUtils "github.com/kata-containers/runtime/virtcontainers/utils"
|
|
specs "github.com/opencontainers/runtime-spec/specs-go"
|
|
"github.com/urfave/cli"
|
|
|
|
"github.com/kata-containers/runtime/pkg/katatestutils"
|
|
"github.com/kata-containers/runtime/pkg/katautils"
|
|
"github.com/kata-containers/runtime/virtcontainers/pkg/oci"
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
const testProxyVersion = "proxy version 0.1"
|
|
const testShimVersion = "shim version 0.1"
|
|
const testNetmonVersion = "netmon version 0.1"
|
|
const 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
|
|
proxyDebug = false
|
|
runtimeDebug = false
|
|
runtimeTrace = false
|
|
shimDebug = false
|
|
netmonDebug = false
|
|
agentDebug = 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 := ioutil.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"
|
|
shimPath := filepath.Join(prefixDir, "shim")
|
|
proxyPath := filepath.Join(prefixDir, "proxy")
|
|
netmonPath := filepath.Join(prefixDir, "netmon")
|
|
disableBlock := true
|
|
blockStorageDriver := "virtio-scsi"
|
|
enableIOThreads := true
|
|
hotplugVFIOOnRootBus := true
|
|
disableNewNetNs := false
|
|
|
|
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(shimPath, testShimVersion)
|
|
if err != nil {
|
|
return "", oci.RuntimeConfig{}, err
|
|
}
|
|
|
|
err = makeVersionBinary(proxyPath, testProxyVersion)
|
|
if err != nil {
|
|
return "", oci.RuntimeConfig{}, err
|
|
}
|
|
|
|
err = makeVersionBinary(netmonPath, testNetmonVersion)
|
|
if err != nil {
|
|
return "", oci.RuntimeConfig{}, err
|
|
}
|
|
|
|
err = makeVersionBinary(hypervisorPath, testHypervisorVersion)
|
|
if err != nil {
|
|
return "", oci.RuntimeConfig{}, err
|
|
}
|
|
|
|
hypConfig := katautils.GetDefaultHypervisorConfig()
|
|
|
|
configFileOptions := katatestutils.RuntimeConfigOptions{
|
|
Hypervisor: "qemu",
|
|
HypervisorPath: hypervisorPath,
|
|
KernelPath: kernelPath,
|
|
ImagePath: imagePath,
|
|
KernelParams: kernelParams,
|
|
MachineType: machineType,
|
|
ShimPath: shimPath,
|
|
ProxyPath: proxyPath,
|
|
NetmonPath: netmonPath,
|
|
LogPath: logPath,
|
|
DefaultGuestHookPath: hypConfig.GuestHookPath,
|
|
DisableBlock: disableBlock,
|
|
BlockDeviceDriver: blockStorageDriver,
|
|
EnableIOThreads: enableIOThreads,
|
|
HotplugVFIOOnRootBus: hotplugVFIOOnRootBus,
|
|
DisableNewNetNs: disableNewNetNs,
|
|
DefaultVCPUCount: hypConfig.NumVCPUs,
|
|
DefaultMaxVCPUCount: hypConfig.DefaultMaxVCPUs,
|
|
DefaultMemSize: hypConfig.MemorySize,
|
|
DefaultMsize9p: hypConfig.Msize9p,
|
|
HypervisorDebug: hypervisorDebug,
|
|
RuntimeDebug: runtimeDebug,
|
|
RuntimeTrace: runtimeTrace,
|
|
ProxyDebug: proxyDebug,
|
|
ShimDebug: shimDebug,
|
|
NetmonDebug: netmonDebug,
|
|
AgentDebug: agentDebug,
|
|
}
|
|
|
|
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, false)
|
|
if err != nil {
|
|
return "", oci.RuntimeConfig{}, err
|
|
}
|
|
|
|
return configFile, config, nil
|
|
}
|
|
|
|
func getExpectedProxyDetails(config oci.RuntimeConfig) (ProxyInfo, error) {
|
|
return ProxyInfo{
|
|
Type: string(config.ProxyType),
|
|
Version: testProxyVersion,
|
|
Path: config.ProxyConfig.Path,
|
|
Debug: config.ProxyConfig.Debug,
|
|
}, nil
|
|
}
|
|
|
|
func getExpectedNetmonDetails(config oci.RuntimeConfig) (NetmonInfo, error) {
|
|
return NetmonInfo{
|
|
Version: testNetmonVersion,
|
|
Path: config.NetmonConfig.Path,
|
|
Debug: config.NetmonConfig.Debug,
|
|
Enable: config.NetmonConfig.Enable,
|
|
}, nil
|
|
}
|
|
|
|
func getExpectedShimDetails(config oci.RuntimeConfig) (ShimInfo, error) {
|
|
shimConfig, ok := config.ShimConfig.(vc.ShimConfig)
|
|
if !ok {
|
|
return ShimInfo{}, fmt.Errorf("failed to get shim config")
|
|
}
|
|
|
|
shimPath := shimConfig.Path
|
|
|
|
return ShimInfo{
|
|
Type: string(config.ShimType),
|
|
Version: testShimVersion,
|
|
Path: shimPath,
|
|
Debug: shimConfig.Debug,
|
|
}, nil
|
|
}
|
|
|
|
func getExpectedAgentDetails(config oci.RuntimeConfig) (AgentInfo, error) {
|
|
|
|
agentConfig, ok := config.AgentConfig.(vc.KataAgentConfig)
|
|
if !ok {
|
|
return AgentInfo{}, fmt.Errorf("expected KataAgentConfig, got %T", config.AgentConfig)
|
|
}
|
|
|
|
return AgentInfo{
|
|
Type: string(config.AgentType),
|
|
Debug: agentConfig.Debug,
|
|
}, 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,
|
|
}
|
|
|
|
expectedHostDetails := HostInfo{
|
|
Kernel: expectedKernelVersion,
|
|
Architecture: expectedArch,
|
|
Distro: expectedDistro,
|
|
CPU: expectedCPU,
|
|
VMContainerCapable: expectedVMContainerCapable,
|
|
SupportVSocks: vcUtils.SupportsVsocks(),
|
|
}
|
|
|
|
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"
|
|
}
|
|
|
|
return expectedHostDetails, nil
|
|
}
|
|
|
|
func getExpectedHypervisor(config oci.RuntimeConfig) HypervisorInfo {
|
|
return 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,
|
|
}
|
|
}
|
|
|
|
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()
|
|
|
|
return RuntimeInfo{
|
|
Version: RuntimeVersionInfo{
|
|
Semver: version,
|
|
Commit: commit,
|
|
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)
|
|
|
|
proxy, err := getExpectedProxyDetails(config)
|
|
if err != nil {
|
|
return EnvInfo{}, err
|
|
}
|
|
|
|
shim, err := getExpectedShimDetails(config)
|
|
if err != nil {
|
|
return EnvInfo{}, err
|
|
}
|
|
|
|
agent, err := getExpectedAgentDetails(config)
|
|
if err != nil {
|
|
return EnvInfo{}, err
|
|
}
|
|
|
|
host, err := getExpectedHostDetails(tmpdir)
|
|
if err != nil {
|
|
return EnvInfo{}, err
|
|
}
|
|
|
|
netmon, err := getExpectedNetmonDetails(config)
|
|
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,
|
|
Proxy: proxy,
|
|
Shim: shim,
|
|
Agent: agent,
|
|
Host: host,
|
|
Netmon: netmon,
|
|
}
|
|
|
|
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 := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
host, err := getHostInfo()
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedHostDetails, host)
|
|
}
|
|
|
|
func TestEnvGetHostInfoNoProcCPUInfo(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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
|
|
proxyDebug = toggle
|
|
runtimeDebug = toggle
|
|
runtimeTrace = toggle
|
|
shimDebug = 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)
|
|
|
|
assert.Equal(t, expectedEnv, env)
|
|
}
|
|
}
|
|
|
|
func TestEnvGetEnvInfoNoHypervisorVersion(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
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)
|
|
|
|
assert.Equal(expectedEnv, env)
|
|
}
|
|
|
|
func TestEnvGetEnvInfoShimError(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
configFile, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(err)
|
|
|
|
config.ShimConfig = "invalid shim config"
|
|
|
|
_, err = getEnvInfo(configFile, config)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestEnvGetEnvInfoAgentError(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
configFile, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(err)
|
|
|
|
config.AgentConfig = "invalid agent config"
|
|
|
|
_, err = getEnvInfo(configFile, config)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestEnvGetEnvInfoNoOSRelease(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 TestEnvGetProxyInfo(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedProxy, err := getExpectedProxyDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
proxy, err := getProxyInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedProxy, proxy)
|
|
}
|
|
|
|
func TestEnvGetProxyInfoNoVersion(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedProxy, err := getExpectedProxyDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
// remove the proxy ensuring its version cannot be queried
|
|
err = os.Remove(config.ProxyConfig.Path)
|
|
assert.NoError(t, err)
|
|
|
|
expectedProxy.Version = unknown
|
|
|
|
proxy, err := getProxyInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedProxy, proxy)
|
|
}
|
|
|
|
func TestEnvGetNetmonInfo(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedNetmon, err := getExpectedNetmonDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
netmon, err := getNetmonInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedNetmon, netmon)
|
|
}
|
|
|
|
func TestEnvGetNetmonInfoNoVersion(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedNetmon, err := getExpectedNetmonDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
// remove the netmon ensuring its version cannot be queried
|
|
err = os.Remove(config.NetmonConfig.Path)
|
|
assert.NoError(t, err)
|
|
|
|
expectedNetmon.Version = unknown
|
|
|
|
netmon, err := getNetmonInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedNetmon, netmon)
|
|
}
|
|
|
|
func TestEnvGetShimInfo(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedShim, err := getExpectedShimDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
shim, err := getShimInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedShim, shim)
|
|
}
|
|
|
|
func TestEnvGetShimInfoNoVersion(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
expectedShim, err := getExpectedShimDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
shimPath := expectedShim.Path
|
|
|
|
// ensure querying the shim version fails
|
|
err = createFile(shimPath, `#!/bin/sh
|
|
exit 1`)
|
|
assert.NoError(t, err)
|
|
|
|
expectedShim.Version = unknown
|
|
|
|
shim, err := getShimInfo(config)
|
|
assert.NoError(t, err)
|
|
|
|
assert.Equal(t, expectedShim, shim)
|
|
}
|
|
|
|
func TestEnvGetShimInfoInvalidType(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
_, err = getExpectedShimDetails(config)
|
|
assert.NoError(t, err)
|
|
|
|
config.ShimConfig = "foo"
|
|
_, err = getShimInfo(config)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
func TestEnvGetAgentInfo(t *testing.T) {
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
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, ok := config.AgentConfig.(vc.KataAgentConfig)
|
|
assert.True(t, ok)
|
|
|
|
agentConfig.Debug = true
|
|
config.AgentConfig = agentConfig
|
|
agent, err = getAgentInfo(config)
|
|
assert.NoError(t, err)
|
|
assert.True(t, agent.Debug)
|
|
|
|
config.AgentConfig = "I am the wrong type"
|
|
_, err = getAgentInfo(config)
|
|
assert.Error(t, err)
|
|
}
|
|
|
|
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",
|
|
}
|
|
|
|
proxy := ProxyInfo{
|
|
Type: "proxy-type",
|
|
Version: "proxy-version",
|
|
Path: "file:///proxy-url",
|
|
Debug: false,
|
|
}
|
|
|
|
shim := ShimInfo{
|
|
Type: "shim-type",
|
|
Version: "shim-version",
|
|
Path: "/resolved/shim/path",
|
|
}
|
|
|
|
agent := AgentInfo{
|
|
Type: "agent-type",
|
|
}
|
|
|
|
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
env := EnvInfo{
|
|
Runtime: runtime,
|
|
Hypervisor: hypervisor,
|
|
Image: image,
|
|
Kernel: kernel,
|
|
Proxy: proxy,
|
|
Shim: shim,
|
|
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",
|
|
}
|
|
|
|
proxy := ProxyInfo{
|
|
Type: "proxy-type",
|
|
Version: "proxy-version",
|
|
Path: "file:///proxy-url",
|
|
Debug: false,
|
|
}
|
|
|
|
shim := ShimInfo{
|
|
Type: "shim-type",
|
|
Version: "shim-version",
|
|
Path: "/resolved/shim/path",
|
|
}
|
|
|
|
agent := AgentInfo{
|
|
Type: "agent-type",
|
|
}
|
|
|
|
expectedHostDetails, err := getExpectedHostDetails(tmpdir)
|
|
assert.NoError(t, err)
|
|
|
|
env := EnvInfo{
|
|
Runtime: runtime,
|
|
Hypervisor: hypervisor,
|
|
Image: image,
|
|
Kernel: kernel,
|
|
Proxy: proxy,
|
|
Shim: shim,
|
|
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 := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
tmpfile, err := ioutil.TempFile("", "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 := ioutil.TempDir("", "")
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
tmpfile, err := ioutil.TempFile("", "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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempFile("", "")
|
|
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 TestEnvHandleSettingsInvalidShimConfig(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
configFile, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(err)
|
|
|
|
_, err = getExpectedSettings(config, tmpdir, configFile)
|
|
assert.NoError(err)
|
|
|
|
config.ShimConfig = "invalid shim config"
|
|
|
|
ctx := createCLIContext(nil)
|
|
ctx.App.Name = "foo"
|
|
ctx.App.Metadata["configFile"] = configFile
|
|
ctx.App.Metadata["runtimeConfig"] = config
|
|
|
|
tmpfile, err := ioutil.TempFile("", "")
|
|
assert.NoError(err)
|
|
defer os.Remove(tmpfile.Name())
|
|
|
|
err = handleSettings(tmpfile, ctx)
|
|
assert.Error(err)
|
|
}
|
|
|
|
func TestEnvHandleSettingsInvalidParams(t *testing.T) {
|
|
assert := assert.New(t)
|
|
|
|
tmpdir, err := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
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 := ioutil.TempDir("", "")
|
|
assert.NoError(err)
|
|
defer os.RemoveAll(tmpdir)
|
|
|
|
_, config, err := makeRuntimeConfig(tmpdir)
|
|
assert.NoError(err)
|
|
|
|
info := getHypervisorInfo(config)
|
|
assert.Equal(info.Version, testHypervisorVersion)
|
|
|
|
err = os.Remove(config.HypervisorConfig.HypervisorPath)
|
|
assert.NoError(err)
|
|
|
|
info = getHypervisorInfo(config)
|
|
assert.Equal(info.Version, unknown)
|
|
}
|