mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-09-20 00:07:55 +00:00
Merge pull request #475 from grahamwhaley/20180706_env_json
kata-env: Add ability to output as JSON
This commit is contained in:
@@ -6,6 +6,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -328,7 +329,34 @@ func getEnvInfo(configFile string, config oci.RuntimeConfig) (env EnvInfo, err e
|
|||||||
return env, nil
|
return env, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func showSettings(env EnvInfo, file *os.File) error {
|
func handleSettings(file *os.File, c *cli.Context) error {
|
||||||
|
if file == nil {
|
||||||
|
return errors.New("Invalid output file specified")
|
||||||
|
}
|
||||||
|
|
||||||
|
configFile, ok := c.App.Metadata["configFile"].(string)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("cannot determine config file")
|
||||||
|
}
|
||||||
|
|
||||||
|
runtimeConfig, ok := c.App.Metadata["runtimeConfig"].(oci.RuntimeConfig)
|
||||||
|
if !ok {
|
||||||
|
return errors.New("cannot determine runtime config")
|
||||||
|
}
|
||||||
|
|
||||||
|
env, err := getEnvInfo(configFile, runtimeConfig)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Bool("json") {
|
||||||
|
return writeJSONSettings(env, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
return writeTOMLSettings(env, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
func writeTOMLSettings(env EnvInfo, file *os.File) error {
|
||||||
encoder := toml.NewEncoder(file)
|
encoder := toml.NewEncoder(file)
|
||||||
|
|
||||||
err := encoder.Encode(env)
|
err := encoder.Encode(env)
|
||||||
@@ -339,33 +367,30 @@ func showSettings(env EnvInfo, file *os.File) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handleSettings(file *os.File, metadata map[string]interface{}) error {
|
func writeJSONSettings(env EnvInfo, file *os.File) error {
|
||||||
if file == nil {
|
encoder := json.NewEncoder(file)
|
||||||
return errors.New("Invalid output file specified")
|
|
||||||
}
|
|
||||||
|
|
||||||
configFile, ok := metadata["configFile"].(string)
|
// Make it more human readable
|
||||||
if !ok {
|
encoder.SetIndent("", " ")
|
||||||
return errors.New("cannot determine config file")
|
|
||||||
}
|
|
||||||
|
|
||||||
runtimeConfig, ok := metadata["runtimeConfig"].(oci.RuntimeConfig)
|
err := encoder.Encode(env)
|
||||||
if !ok {
|
|
||||||
return errors.New("cannot determine runtime config")
|
|
||||||
}
|
|
||||||
|
|
||||||
env, err := getEnvInfo(configFile, runtimeConfig)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return showSettings(env, file)
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
var kataEnvCLICommand = cli.Command{
|
var kataEnvCLICommand = cli.Command{
|
||||||
Name: envCmd,
|
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 {
|
Action: func(context *cli.Context) error {
|
||||||
return handleSettings(defaultOutputFile, context.App.Metadata)
|
return handleSettings(defaultOutputFile, context)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@@ -7,6 +7,8 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -668,7 +670,7 @@ func TestEnvGetAgentInfo(t *testing.T) {
|
|||||||
assert.Equal(t, expectedAgent, agent)
|
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{}
|
runtime := RuntimeInfo{}
|
||||||
|
|
||||||
@@ -717,7 +719,7 @@ func testEnvShowSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
|
|||||||
Host: expectedHostDetails,
|
Host: expectedHostDetails,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = showSettings(env, tmpfile)
|
err = writeTOMLSettings(env, tmpfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -737,6 +739,77 @@ func testEnvShowSettings(t *testing.T, tmpdir string, tmpfile *os.File) error {
|
|||||||
return nil
|
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) {
|
func TestEnvShowSettings(t *testing.T) {
|
||||||
tmpdir, err := ioutil.TempDir("", "")
|
tmpdir, err := ioutil.TempDir("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -748,7 +821,13 @@ func TestEnvShowSettings(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.Remove(tmpfile.Name())
|
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)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -761,11 +840,18 @@ func TestEnvShowSettingsInvalidFile(t *testing.T) {
|
|||||||
|
|
||||||
tmpfile, err := ioutil.TempFile("", "envShowSettings-")
|
tmpfile, err := ioutil.TempFile("", "envShowSettings-")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
// close the file
|
// close the file
|
||||||
tmpfile.Close()
|
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)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -782,7 +868,11 @@ func TestEnvHandleSettings(t *testing.T) {
|
|||||||
_, err = getExpectedSettings(config, tmpdir, configFile)
|
_, err = getExpectedSettings(config, tmpdir, configFile)
|
||||||
assert.NoError(t, err)
|
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,
|
"configFile": configFile,
|
||||||
"runtimeConfig": config,
|
"runtimeConfig": config,
|
||||||
}
|
}
|
||||||
@@ -791,7 +881,7 @@ func TestEnvHandleSettings(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
err = handleSettings(tmpfile, m)
|
err = handleSettings(tmpfile, ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
var env EnvInfo
|
var env EnvInfo
|
||||||
@@ -815,7 +905,10 @@ func TestEnvHandleSettingsInvalidShimConfig(t *testing.T) {
|
|||||||
|
|
||||||
config.ShimConfig = "invalid shim config"
|
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,
|
"configFile": configFile,
|
||||||
"runtimeConfig": config,
|
"runtimeConfig": config,
|
||||||
}
|
}
|
||||||
@@ -824,47 +917,75 @@ func TestEnvHandleSettingsInvalidShimConfig(t *testing.T) {
|
|||||||
assert.NoError(err)
|
assert.NoError(err)
|
||||||
defer os.Remove(tmpfile.Name())
|
defer os.Remove(tmpfile.Name())
|
||||||
|
|
||||||
err = handleSettings(tmpfile, m)
|
err = handleSettings(tmpfile, ctx)
|
||||||
assert.Error(err)
|
assert.Error(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvHandleSettingsInvalidParams(t *testing.T) {
|
func TestEnvHandleSettingsInvalidParams(t *testing.T) {
|
||||||
err := handleSettings(nil, map[string]interface{}{})
|
assert := assert.New(t)
|
||||||
assert.Error(t, err)
|
|
||||||
|
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) {
|
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)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvHandleSettingsInvalidFile(t *testing.T) {
|
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",
|
"configFile": "foo",
|
||||||
"runtimeConfig": oci.RuntimeConfig{},
|
"runtimeConfig": oci.RuntimeConfig{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := handleSettings(nil, m)
|
err := handleSettings(nil, ctx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvHandleSettingsInvalidConfigFileType(t *testing.T) {
|
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,
|
"configFile": 123,
|
||||||
"runtimeConfig": oci.RuntimeConfig{},
|
"runtimeConfig": oci.RuntimeConfig{},
|
||||||
}
|
}
|
||||||
|
|
||||||
err := handleSettings(os.Stderr, m)
|
err := handleSettings(os.Stderr, ctx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEnvHandleSettingsInvalidRuntimeConfigType(t *testing.T) {
|
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",
|
"configFile": "/some/where",
|
||||||
"runtimeConfig": true,
|
"runtimeConfig": true,
|
||||||
}
|
}
|
||||||
|
|
||||||
err := handleSettings(os.Stderr, m)
|
err := handleSettings(os.Stderr, ctx)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -882,7 +1003,8 @@ func TestEnvCLIFunction(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
ctx := cli.NewContext(app, nil, nil)
|
set := flag.NewFlagSet("test", flag.ContinueOnError)
|
||||||
|
ctx := cli.NewContext(app, set, nil)
|
||||||
app.Name = "foo"
|
app.Name = "foo"
|
||||||
|
|
||||||
ctx.App.Metadata = map[string]interface{}{
|
ctx.App.Metadata = map[string]interface{}{
|
||||||
@@ -906,6 +1028,12 @@ func TestEnvCLIFunction(t *testing.T) {
|
|||||||
|
|
||||||
err = fn(ctx)
|
err = fn(ctx)
|
||||||
assert.NoError(t, err)
|
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) {
|
func TestEnvCLIFunctionFail(t *testing.T) {
|
||||||
|
Reference in New Issue
Block a user