...

Source file src/github.com/opencontainers/runc/libcontainer/configs/config_test.go

Documentation: github.com/opencontainers/runc/libcontainer/configs

     1  package configs_test
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"os"
     7  	"reflect"
     8  	"testing"
     9  	"time"
    10  
    11  	"github.com/opencontainers/runc/libcontainer/configs"
    12  	"github.com/opencontainers/runtime-spec/specs-go"
    13  )
    14  
    15  func TestUnmarshalHooks(t *testing.T) {
    16  	timeout := time.Second
    17  
    18  	hookCmd := configs.NewCommandHook(configs.Command{
    19  		Path:    "/var/vcap/hooks/hook",
    20  		Args:    []string{"--pid=123"},
    21  		Env:     []string{"FOO=BAR"},
    22  		Dir:     "/var/vcap",
    23  		Timeout: &timeout,
    24  	})
    25  
    26  	hookJson, err := json.Marshal(hookCmd)
    27  	if err != nil {
    28  		t.Fatal(err)
    29  	}
    30  
    31  	for _, hookName := range configs.HookNameList {
    32  		hooks := configs.Hooks{}
    33  		err = hooks.UnmarshalJSON([]byte(fmt.Sprintf(`{"%s" :[%s]}`, hookName, hookJson)))
    34  		if err != nil {
    35  			t.Fatal(err)
    36  		}
    37  
    38  		if !reflect.DeepEqual(hooks[hookName], configs.HookList{hookCmd}) {
    39  			t.Errorf("Expected %s to equal %+v but it was %+v", hookName, hookCmd, hooks[hookName])
    40  		}
    41  	}
    42  }
    43  
    44  func TestUnmarshalHooksWithInvalidData(t *testing.T) {
    45  	hook := configs.Hooks{}
    46  	err := hook.UnmarshalJSON([]byte(`{invalid-json}`))
    47  	if err == nil {
    48  		t.Error("Expected error to occur but it was nil")
    49  	}
    50  }
    51  
    52  func TestMarshalHooks(t *testing.T) {
    53  	timeout := time.Second
    54  
    55  	hookCmd := configs.NewCommandHook(configs.Command{
    56  		Path:    "/var/vcap/hooks/hook",
    57  		Args:    []string{"--pid=123"},
    58  		Env:     []string{"FOO=BAR"},
    59  		Dir:     "/var/vcap",
    60  		Timeout: &timeout,
    61  	})
    62  
    63  	hook := configs.Hooks{
    64  		configs.Prestart:        configs.HookList{hookCmd},
    65  		configs.CreateRuntime:   configs.HookList{hookCmd},
    66  		configs.CreateContainer: configs.HookList{hookCmd},
    67  		configs.StartContainer:  configs.HookList{hookCmd},
    68  		configs.Poststart:       configs.HookList{hookCmd},
    69  		configs.Poststop:        configs.HookList{hookCmd},
    70  	}
    71  	hooks, err := hook.MarshalJSON()
    72  	if err != nil {
    73  		t.Fatal(err)
    74  	}
    75  
    76  	// Note Marshal seems to output fields in alphabetical order
    77  	hookCmdJson := `[{"path":"/var/vcap/hooks/hook","args":["--pid=123"],"env":["FOO=BAR"],"dir":"/var/vcap","timeout":1000000000}]`
    78  	h := fmt.Sprintf(`{"createContainer":%[1]s,"createRuntime":%[1]s,"poststart":%[1]s,"poststop":%[1]s,"prestart":%[1]s,"startContainer":%[1]s}`, hookCmdJson)
    79  	if string(hooks) != h {
    80  		t.Errorf("Expected hooks %s to equal %s", string(hooks), h)
    81  	}
    82  }
    83  
    84  func TestMarshalUnmarshalHooks(t *testing.T) {
    85  	timeout := time.Second
    86  
    87  	hookCmd := configs.NewCommandHook(configs.Command{
    88  		Path:    "/var/vcap/hooks/hook",
    89  		Args:    []string{"--pid=123"},
    90  		Env:     []string{"FOO=BAR"},
    91  		Dir:     "/var/vcap",
    92  		Timeout: &timeout,
    93  	})
    94  
    95  	hook := configs.Hooks{
    96  		configs.Prestart:        configs.HookList{hookCmd},
    97  		configs.CreateRuntime:   configs.HookList{hookCmd},
    98  		configs.CreateContainer: configs.HookList{hookCmd},
    99  		configs.StartContainer:  configs.HookList{hookCmd},
   100  		configs.Poststart:       configs.HookList{hookCmd},
   101  		configs.Poststop:        configs.HookList{hookCmd},
   102  	}
   103  	hooks, err := hook.MarshalJSON()
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  
   108  	umMhook := configs.Hooks{}
   109  	err = umMhook.UnmarshalJSON(hooks)
   110  	if err != nil {
   111  		t.Fatal(err)
   112  	}
   113  	if !reflect.DeepEqual(umMhook, hook) {
   114  		t.Errorf("Expected hooks to be equal after mashaling -> unmarshaling them: %+v, %+v", umMhook, hook)
   115  	}
   116  }
   117  
   118  func TestMarshalHooksWithUnexpectedType(t *testing.T) {
   119  	fHook := configs.NewFunctionHook(func(*specs.State) error {
   120  		return nil
   121  	})
   122  	hook := configs.Hooks{
   123  		configs.CreateRuntime: configs.HookList{fHook},
   124  	}
   125  	hooks, err := hook.MarshalJSON()
   126  	if err != nil {
   127  		t.Fatal(err)
   128  	}
   129  
   130  	h := `{"createContainer":null,"createRuntime":null,"poststart":null,"poststop":null,"prestart":null,"startContainer":null}`
   131  	if string(hooks) != h {
   132  		t.Errorf("Expected hooks %s to equal %s", string(hooks), h)
   133  	}
   134  }
   135  
   136  func TestFuncHookRun(t *testing.T) {
   137  	state := &specs.State{
   138  		Version: "1",
   139  		ID:      "1",
   140  		Status:  "created",
   141  		Pid:     1,
   142  		Bundle:  "/bundle",
   143  	}
   144  
   145  	fHook := configs.NewFunctionHook(func(s *specs.State) error {
   146  		if !reflect.DeepEqual(state, s) {
   147  			return fmt.Errorf("expected state %+v to equal %+v", state, s)
   148  		}
   149  		return nil
   150  	})
   151  
   152  	err := fHook.Run(state)
   153  	if err != nil {
   154  		t.Fatal(err)
   155  	}
   156  }
   157  
   158  func TestCommandHookRun(t *testing.T) {
   159  	state := &specs.State{
   160  		Version: "1",
   161  		ID:      "1",
   162  		Status:  "created",
   163  		Pid:     1,
   164  		Bundle:  "/bundle",
   165  	}
   166  
   167  	stateJson, err := json.Marshal(state)
   168  	if err != nil {
   169  		t.Fatal(err)
   170  	}
   171  
   172  	verifyCommandTemplate := `#!/bin/sh
   173  if [ "$1" != "testarg" ]; then
   174  	echo "Bad value for $1. Expected 'testarg', found '$1'"
   175  	exit 1
   176  fi
   177  if [ -z "$FOO" ] || [ "$FOO" != BAR ]; then
   178  	echo "Bad value for FOO. Expected 'BAR', found '$FOO'"
   179  	exit 1
   180  fi
   181  expectedJson=%q
   182  read JSON
   183  if [ "$JSON" != "$expectedJson" ]; then
   184  	echo "Bad JSON received. Expected '$expectedJson', found '$JSON'"
   185  	exit 1
   186  fi
   187  exit 0
   188  	`
   189  	verifyCommand := fmt.Sprintf(verifyCommandTemplate, stateJson)
   190  	filename := "/tmp/runc-hooktest.sh"
   191  	os.Remove(filename)
   192  	if err := os.WriteFile(filename, []byte(verifyCommand), 0o700); err != nil {
   193  		t.Fatalf("Failed to create tmp file: %v", err)
   194  	}
   195  	defer os.Remove(filename)
   196  
   197  	cmdHook := configs.NewCommandHook(configs.Command{
   198  		Path: filename,
   199  		Args: []string{filename, "testarg"},
   200  		Env:  []string{"FOO=BAR"},
   201  		Dir:  "/",
   202  	})
   203  
   204  	if err := cmdHook.Run(state); err != nil {
   205  		t.Errorf(fmt.Sprintf("Expected error to not occur but it was %+v", err))
   206  	}
   207  }
   208  
   209  func TestCommandHookRunTimeout(t *testing.T) {
   210  	state := &specs.State{
   211  		Version: "1",
   212  		ID:      "1",
   213  		Status:  "created",
   214  		Pid:     1,
   215  		Bundle:  "/bundle",
   216  	}
   217  	timeout := 100 * time.Millisecond
   218  
   219  	cmdHook := configs.NewCommandHook(configs.Command{
   220  		Path:    "/bin/sleep",
   221  		Args:    []string{"/bin/sleep", "1"},
   222  		Timeout: &timeout,
   223  	})
   224  
   225  	if err := cmdHook.Run(state); err == nil {
   226  		t.Error("Expected error to occur but it was nil")
   227  	}
   228  }
   229  

View as plain text