Skip to content
This repository was archived by the owner on May 12, 2021. It is now read-only.
Merged
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
59 changes: 42 additions & 17 deletions cli/kata-env.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package main

import (
"encoding/json"
"errors"
"os"
"strings"
Expand Down Expand Up @@ -328,28 +329,17 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e
return env, nil
}

func showSettings(env EnvInfo, file *os.File) error {
encoder := toml.NewEncoder(file)

err := encoder.Encode(env)
if err != nil {
return err
}

return nil
}

func handleSettings(file *os.File, metadata map[string]interface{}) error {
func handleSettings(file *os.File, c *cli.Context) error {
if file == nil {
return errors.New("Invalid output file specified")
}

configFile, ok := metadata["configFile"].(string)
configFile, ok := c.App.Metadata["configFile"].(string)
if !ok {
return errors.New("cannot determine config file")
}

runtimeConfig, ok := metadata["runtimeConfig"].(oci.RuntimeConfig)
runtimeConfig, ok := c.App.Metadata["runtimeConfig"].(oci.RuntimeConfig)
if !ok {
return errors.New("cannot determine runtime config")
}
Expand All @@ -359,13 +349,48 @@ func handleSettings(file *os.File, metadata map[string]interface{}) error {
return err
}

return showSettings(env, file)
if c.Bool("json") {
return writeJSONSettings(env, file)
}

return writeTOMLSettings(env, file)
}

func writeTOMLSettings(env EnvInfo, file *os.File) error {
encoder := toml.NewEncoder(file)

err := encoder.Encode(env)
if err != nil {
return err
}

return nil
}

func writeJSONSettings(env EnvInfo, file *os.File) error {
encoder := json.NewEncoder(file)

// Make it more human readable
encoder.SetIndent("", " ")

err := encoder.Encode(env)
if err != nil {
return err
}

return nil
}

var kataEnvCLICommand = cli.Command{
Name: envCmd,
Usage: "display settings",
Usage: "display settings. Default to TOML",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "json",
Usage: "Format output as JSON",
},
},
Action: func(context *cli.Context) error {
return handleSettings(defaultOutputFile, context.App.Metadata)
return handleSettings(defaultOutputFile, context)
},
}
164 changes: 146 additions & 18 deletions cli/kata-env_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ package main

import (
"bytes"
"encoding/json"
"flag"
"fmt"
"io/ioutil"
"os"
Expand Down Expand Up @@ -668,7 +670,7 @@ func TestEnvGetAgentInfo(t *testing.T) {
assert.Equal(t, expectedAgent, agent)
}

func testEnvShowSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
func testEnvShowTOMLSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {

runtime := RuntimeInfo{}

Expand Down Expand Up @@ -717,7 +719,7 @@ func testEnvShowSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
Host: expectedHostDetails,
}

err = showSettings(env, tmpfile)
err = writeTOMLSettings(env, tmpfile)
if err != nil {
return err
}
Expand All @@ -737,6 +739,77 @@ func testEnvShowSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
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 := 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 {
Expand All @@ -748,7 +821,13 @@ func TestEnvShowSettings(t *testing.T) {
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())

err = testEnvShowSettings(t, tmpdir, tmpfile)
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)
}

Expand All @@ -761,11 +840,18 @@ func TestEnvShowSettingsInvalidFile(t *testing.T) {

tmpfile, err := ioutil.TempFile("", "envShowSettings-")
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())

// close the file
tmpfile.Close()

err = testEnvShowSettings(t, tmpdir, tmpfile)
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)
}

Expand All @@ -782,7 +868,11 @@ func TestEnvHandleSettings(t *testing.T) {
_, err = getExpectedSettings(config, tmpdir, configFile)
assert.NoError(t, err)

m := map[string]interface{}{
app := cli.NewApp()
set := flag.NewFlagSet("test", flag.ContinueOnError)
ctx := cli.NewContext(app, set, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": configFile,
"runtimeConfig": config,
}
Expand All @@ -791,7 +881,7 @@ func TestEnvHandleSettings(t *testing.T) {
assert.NoError(t, err)
defer os.Remove(tmpfile.Name())

err = handleSettings(tmpfile, m)
err = handleSettings(tmpfile, ctx)
assert.NoError(t, err)

var env EnvInfo
Expand All @@ -815,7 +905,10 @@ func TestEnvHandleSettingsInvalidShimConfig(t *testing.T) {

config.ShimConfig = "invalid shim config"

m := map[string]interface{}{
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": configFile,
"runtimeConfig": config,
}
Expand All @@ -824,47 +917,75 @@ func TestEnvHandleSettingsInvalidShimConfig(t *testing.T) {
assert.NoError(err)
defer os.Remove(tmpfile.Name())

err = handleSettings(tmpfile, m)
err = handleSettings(tmpfile, ctx)
assert.Error(err)
}

func TestEnvHandleSettingsInvalidParams(t *testing.T) {
err := handleSettings(nil, map[string]interface{}{})
assert.Error(t, err)
assert := assert.New(t)

tmpdir, err := ioutil.TempDir("", "")
assert.NoError(err)
defer os.RemoveAll(tmpdir)

configFile, _, err := makeRuntimeConfig(tmpdir)
assert.NoError(err)

app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": configFile,
}
err = handleSettings(nil, ctx)
assert.Error(err)
}

func TestEnvHandleSettingsEmptyMap(t *testing.T) {
err := handleSettings(os.Stdout, map[string]interface{}{})
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{}
err := handleSettings(os.Stdout, ctx)
assert.Error(t, err)
}

func TestEnvHandleSettingsInvalidFile(t *testing.T) {
m := map[string]interface{}{
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": "foo",
"runtimeConfig": oci.RuntimeConfig{},
}

err := handleSettings(nil, m)
err := handleSettings(nil, ctx)
assert.Error(t, err)
}

func TestEnvHandleSettingsInvalidConfigFileType(t *testing.T) {
m := map[string]interface{}{
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": 123,
"runtimeConfig": oci.RuntimeConfig{},
}

err := handleSettings(os.Stderr, m)
err := handleSettings(os.Stderr, ctx)
assert.Error(t, err)
}

func TestEnvHandleSettingsInvalidRuntimeConfigType(t *testing.T) {
m := map[string]interface{}{
app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
app.Name = "foo"
ctx.App.Metadata = map[string]interface{}{
"configFile": "/some/where",
"runtimeConfig": true,
}

err := handleSettings(os.Stderr, m)
err := handleSettings(os.Stderr, ctx)
assert.Error(t, err)
}

Expand All @@ -882,7 +1003,8 @@ func TestEnvCLIFunction(t *testing.T) {
assert.NoError(t, err)

app := cli.NewApp()
ctx := cli.NewContext(app, nil, nil)
set := flag.NewFlagSet("test", flag.ContinueOnError)
ctx := cli.NewContext(app, set, nil)
app.Name = "foo"

ctx.App.Metadata = map[string]interface{}{
Expand All @@ -906,6 +1028,12 @@ func TestEnvCLIFunction(t *testing.T) {

err = fn(ctx)
assert.NoError(t, err)

set.Bool("json", true, "")
ctx = cli.NewContext(app, set, nil)

err = fn(ctx)
assert.NoError(t, err)
}

func TestEnvCLIFunctionFail(t *testing.T) {
Expand Down