github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/pkg/hooks/hooks_test.go (about)

     1  package hooks
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"path/filepath"
     8  	"runtime"
     9  	"testing"
    10  
    11  	current "github.com/hanks177/podman/v4/pkg/hooks/1.0.0"
    12  	rspec "github.com/opencontainers/runtime-spec/specs-go"
    13  	"github.com/stretchr/testify/assert"
    14  )
    15  
    16  // path is the path to an example hook executable.
    17  var path string
    18  
    19  func TestGoodNew(t *testing.T) {
    20  	ctx := context.Background()
    21  
    22  	dir := t.TempDir()
    23  
    24  	for i, name := range []string{
    25  		"01-my-hook.json",
    26  		"01-UPPERCASE.json",
    27  		"02-another-hook.json",
    28  	} {
    29  		jsonPath := filepath.Join(dir, name)
    30  		var extraStages string
    31  		if i == 0 {
    32  			extraStages = ", \"poststart\", \"poststop\""
    33  		}
    34  		err := ioutil.WriteFile(jsonPath, []byte(fmt.Sprintf("{\"version\": \"1.0.0\", \"hook\": {\"path\": \"%s\", \"timeout\": %d}, \"when\": {\"always\": true}, \"stages\": [\"prestart\"%s]}", path, i+1, extraStages)), 0644)
    35  		if err != nil {
    36  			t.Fatal(err)
    37  		}
    38  	}
    39  
    40  	manager, err := New(ctx, []string{dir}, []string{})
    41  	if err != nil {
    42  		t.Fatal(err)
    43  	}
    44  
    45  	config := &rspec.Spec{}
    46  	extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false)
    47  	if err != nil {
    48  		t.Fatal(err)
    49  	}
    50  
    51  	one := 1
    52  	two := 2
    53  	three := 3
    54  	assert.Equal(t, &rspec.Hooks{
    55  		Prestart: []rspec.Hook{
    56  			{
    57  				Path:    path,
    58  				Timeout: &one,
    59  			},
    60  			{
    61  				Path:    path,
    62  				Timeout: &two,
    63  			},
    64  			{
    65  				Path:    path,
    66  				Timeout: &three,
    67  			},
    68  		},
    69  		Poststart: []rspec.Hook{
    70  			{
    71  				Path:    path,
    72  				Timeout: &one,
    73  			},
    74  		},
    75  		Poststop: []rspec.Hook{
    76  			{
    77  				Path:    path,
    78  				Timeout: &one,
    79  			},
    80  		},
    81  	}, config.Hooks)
    82  
    83  	var nilExtensionStageHooks map[string][]rspec.Hook
    84  	assert.Equal(t, nilExtensionStageHooks, extensionStageHooks)
    85  }
    86  
    87  func TestBadNew(t *testing.T) {
    88  	ctx := context.Background()
    89  
    90  	dir := t.TempDir()
    91  
    92  	jsonPath := filepath.Join(dir, "a.json")
    93  	err := ioutil.WriteFile(jsonPath, []byte("{\"version\": \"-1\"}"), 0644)
    94  	if err != nil {
    95  		t.Fatal(err)
    96  	}
    97  
    98  	_, err = New(ctx, []string{dir}, []string{})
    99  	if err == nil {
   100  		t.Fatal("unexpected success")
   101  	}
   102  	assert.Regexp(t, "^parsing hook \"[^\"]*a.json\": unrecognized hook version: \"-1\"$", err.Error())
   103  }
   104  
   105  func TestBrokenMatch(t *testing.T) {
   106  	manager := Manager{
   107  		hooks: map[string]*current.Hook{
   108  			"a.json": {
   109  				Version: current.Version,
   110  				Hook: rspec.Hook{
   111  					Path: "/a/b/c",
   112  				},
   113  				When: current.When{
   114  					Commands: []string{"["},
   115  				},
   116  				Stages: []string{"prestart"},
   117  			},
   118  		},
   119  	}
   120  	config := &rspec.Spec{
   121  		Process: &rspec.Process{
   122  			Args: []string{"/bin/sh"},
   123  		},
   124  	}
   125  	extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false)
   126  	if err == nil {
   127  		t.Fatal("unexpected success")
   128  	}
   129  	assert.Regexp(t, "^matching hook \"a\\.json\": command: error parsing regexp: .*", err.Error())
   130  
   131  	var nilExtensionStageHooks map[string][]rspec.Hook
   132  	assert.Equal(t, nilExtensionStageHooks, extensionStageHooks)
   133  }
   134  
   135  func TestInvalidStage(t *testing.T) {
   136  	always := true
   137  	manager := Manager{
   138  		hooks: map[string]*current.Hook{
   139  			"a.json": {
   140  				Version: current.Version,
   141  				Hook: rspec.Hook{
   142  					Path: "/a/b/c",
   143  				},
   144  				When: current.When{
   145  					Always: &always,
   146  				},
   147  				Stages: []string{"does-not-exist"},
   148  			},
   149  		},
   150  	}
   151  	extensionStageHooks, err := manager.Hooks(&rspec.Spec{}, map[string]string{}, false)
   152  	if err == nil {
   153  		t.Fatal("unexpected success")
   154  	}
   155  	assert.Regexp(t, "^hook \"a\\.json\": unknown stage \"does-not-exist\"$", err.Error())
   156  
   157  	var nilExtensionStageHooks map[string][]rspec.Hook
   158  	assert.Equal(t, nilExtensionStageHooks, extensionStageHooks)
   159  }
   160  
   161  func TestExtensionStage(t *testing.T) {
   162  	always := true
   163  	manager := Manager{
   164  		hooks: map[string]*current.Hook{
   165  			"a.json": {
   166  				Version: current.Version,
   167  				Hook: rspec.Hook{
   168  					Path: "/a/b/c",
   169  				},
   170  				When: current.When{
   171  					Always: &always,
   172  				},
   173  				Stages: []string{"prestart", "poststop", "a", "b"},
   174  			},
   175  		},
   176  		extensionStages: []string{"poststop", "a", "b", "c"},
   177  	}
   178  
   179  	config := &rspec.Spec{}
   180  	extensionStageHooks, err := manager.Hooks(config, map[string]string{}, false)
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  
   185  	assert.Equal(t, &rspec.Hooks{
   186  		Prestart: []rspec.Hook{
   187  			{
   188  				Path: "/a/b/c",
   189  			},
   190  		},
   191  	}, config.Hooks)
   192  
   193  	assert.Equal(t, map[string][]rspec.Hook{
   194  		"poststop": {
   195  			{
   196  				Path: "/a/b/c",
   197  			},
   198  		},
   199  		"a": {
   200  			{
   201  				Path: "/a/b/c",
   202  			},
   203  		},
   204  		"b": {
   205  			{
   206  				Path: "/a/b/c",
   207  			},
   208  		},
   209  	}, extensionStageHooks)
   210  }
   211  
   212  func init() {
   213  	if runtime.GOOS != "windows" {
   214  		path = "/bin/sh"
   215  	} else {
   216  		panic("we need a reliable executable path on Windows")
   217  	}
   218  }