From 73ecc5a4bdd620124650dbdb621df667beb8438f Mon Sep 17 00:00:00 2001 From: Aditya R Date: Tue, 12 Jul 2022 18:34:44 +0530 Subject: pkg,libpod: remove pkg/hooks and use hooks from c/common PR https://github.com/containers/common/pull/1071 moved `pkg/hooks` to `c/common` hence remove that from podman and use `pkg/hooks` from `c/common` [NO NEW TESTS NEEDED] [NO TESTS NEEDED] Signed-off-by: Aditya R --- pkg/hooks/1.0.0/hook.go | 89 ------------ pkg/hooks/1.0.0/hook_test.go | 214 ---------------------------- pkg/hooks/1.0.0/when.go | 96 ------------- pkg/hooks/1.0.0/when_test.go | 329 ------------------------------------------- 4 files changed, 728 deletions(-) delete mode 100644 pkg/hooks/1.0.0/hook.go delete mode 100644 pkg/hooks/1.0.0/hook_test.go delete mode 100644 pkg/hooks/1.0.0/when.go delete mode 100644 pkg/hooks/1.0.0/when_test.go (limited to 'pkg/hooks/1.0.0') diff --git a/pkg/hooks/1.0.0/hook.go b/pkg/hooks/1.0.0/hook.go deleted file mode 100644 index 71f940a64..000000000 --- a/pkg/hooks/1.0.0/hook.go +++ /dev/null @@ -1,89 +0,0 @@ -// Package hook is the 1.0.0 hook configuration structure. -package hook - -import ( - "encoding/json" - "errors" - "fmt" - "os" - "regexp" - - rspec "github.com/opencontainers/runtime-spec/specs-go" -) - -// Version is the hook configuration version defined in this package. -const Version = "1.0.0" - -// Hook is the hook configuration structure. -type Hook struct { - Version string `json:"version"` - Hook rspec.Hook `json:"hook"` - When When `json:"when"` - Stages []string `json:"stages"` -} - -// Read reads hook JSON bytes, verifies them, and returns the hook configuration. -func Read(content []byte) (hook *Hook, err error) { - if err = json.Unmarshal(content, &hook); err != nil { - return nil, err - } - return hook, nil -} - -// Validate performs load-time hook validation. -func (hook *Hook) Validate(extensionStages []string) (err error) { - if hook == nil { - return errors.New("nil hook") - } - - if hook.Version != Version { - return fmt.Errorf("unexpected hook version %q (expecting %v)", hook.Version, Version) - } - - if hook.Hook.Path == "" { - return errors.New("missing required property: hook.path") - } - - if _, err := os.Stat(hook.Hook.Path); err != nil { - return err - } - - for key, value := range hook.When.Annotations { - if _, err = regexp.Compile(key); err != nil { - return fmt.Errorf("invalid annotation key %q: %w", key, err) - } - if _, err = regexp.Compile(value); err != nil { - return fmt.Errorf("invalid annotation value %q: %w", value, err) - } - } - - for _, command := range hook.When.Commands { - if _, err = regexp.Compile(command); err != nil { - return fmt.Errorf("invalid command %q: %w", command, err) - } - } - - if hook.Stages == nil { - return errors.New("missing required property: stages") - } - - validStages := map[string]bool{ - "createContainer": true, - "createRuntime": true, - "prestart": true, - "poststart": true, - "poststop": true, - "startContainer": true, - } - for _, stage := range extensionStages { - validStages[stage] = true - } - - for _, stage := range hook.Stages { - if !validStages[stage] { - return fmt.Errorf("unknown stage %q", stage) - } - } - - return nil -} diff --git a/pkg/hooks/1.0.0/hook_test.go b/pkg/hooks/1.0.0/hook_test.go deleted file mode 100644 index bd6d6b654..000000000 --- a/pkg/hooks/1.0.0/hook_test.go +++ /dev/null @@ -1,214 +0,0 @@ -package hook - -import ( - "os" - "path/filepath" - "runtime" - "testing" - - rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/stretchr/testify/assert" -) - -// path is the path to an example hook executable. -var path string - -func TestGoodRead(t *testing.T) { - hook, err := Read([]byte("{\"version\": \"1.0.0\", \"hook\": {\"path\": \"/a/b/c\"}, \"when\": {\"always\": true}, \"stages\": [\"prestart\"]}")) - if err != nil { - t.Fatal(err) - } - always := true - assert.Equal(t, &Hook{ - Version: Version, - Hook: rspec.Hook{ - Path: "/a/b/c", - }, - When: When{ - Always: &always, - }, - Stages: []string{"prestart"}, - }, hook) -} - -func TestInvalidJSON(t *testing.T) { - _, err := Read([]byte("{")) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^unexpected end of JSON input$", err.Error()) -} - -func TestGoodValidate(t *testing.T) { - always := true - hook := &Hook{ - Version: Version, - Hook: rspec.Hook{ - Path: path, - }, - When: When{ - Always: &always, - }, - Stages: []string{"prestart"}, - } - err := hook.Validate([]string{}) - if err != nil { - t.Fatal(err) - } -} - -func TestNilValidation(t *testing.T) { - var hook *Hook - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^nil hook$", err.Error()) -} - -func TestWrongVersion(t *testing.T) { - hook := Hook{Version: "0.1.0"} - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^unexpected hook version \"0.1.0\" \\(expecting 1.0.0\\)$", err.Error()) -} - -func TestNoHookPath(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{}, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^missing required property: hook.path$", err.Error()) -} - -func TestUnknownHookPath(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: filepath.Join("does", "not", "exist"), - }, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^stat does/not/exist: no such file or directory$", err.Error()) - if !os.IsNotExist(err) { - t.Fatal("opaque wrapping for not-exist errors") - } -} - -func TestNoStages(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^missing required property: stages$", err.Error()) -} - -func TestInvalidStage(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - Stages: []string{"does-not-exist"}, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^unknown stage \"does-not-exist\"$", err.Error()) -} - -func TestExtensionStage(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - Stages: []string{"prestart", "b"}, - } - err := hook.Validate([]string{"a", "b", "c"}) - if err != nil { - t.Fatal(err) - } -} - -func TestInvalidAnnotationKey(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - When: When{ - Annotations: map[string]string{ - "[": "a", - }, - }, - Stages: []string{"prestart"}, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^invalid annotation key \"\\[\": error parsing regexp: .*", err.Error()) -} - -func TestInvalidAnnotationValue(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - When: When{ - Annotations: map[string]string{ - "a": "[", - }, - }, - Stages: []string{"prestart"}, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^invalid annotation value \"\\[\": error parsing regexp: .*", err.Error()) -} - -func TestInvalidCommand(t *testing.T) { - hook := Hook{ - Version: "1.0.0", - Hook: rspec.Hook{ - Path: path, - }, - When: When{ - Commands: []string{"["}, - }, - Stages: []string{"prestart"}, - } - err := hook.Validate([]string{}) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^invalid command \"\\[\": error parsing regexp: .*", err.Error()) -} - -func init() { - if runtime.GOOS != "windows" { - path = "/bin/sh" - } else { - panic("we need a reliable executable path on Windows") - } -} diff --git a/pkg/hooks/1.0.0/when.go b/pkg/hooks/1.0.0/when.go deleted file mode 100644 index a1351890f..000000000 --- a/pkg/hooks/1.0.0/when.go +++ /dev/null @@ -1,96 +0,0 @@ -package hook - -import ( - "errors" - "fmt" - "regexp" - - rspec "github.com/opencontainers/runtime-spec/specs-go" -) - -// When holds hook-injection conditions. -type When struct { - Always *bool `json:"always,omitempty"` - Annotations map[string]string `json:"annotations,omitempty"` - Commands []string `json:"commands,omitempty"` - HasBindMounts *bool `json:"hasBindMounts,omitempty"` - - // Or enables any-of matching. - // - // Deprecated: this property is for is backwards-compatibility with - // 0.1.0 hooks. It will be removed when we drop support for them. - Or bool `json:"-"` -} - -// Match returns true if the given conditions match the configuration. -func (when *When) Match(config *rspec.Spec, annotations map[string]string, hasBindMounts bool) (match bool, err error) { - matches := 0 - - if when.Always != nil { - if *when.Always { - if when.Or { - return true, nil - } - matches++ - } else if !when.Or { - return false, nil - } - } - - if when.HasBindMounts != nil { - if *when.HasBindMounts && hasBindMounts { - if when.Or { - return true, nil - } - matches++ - } else if !when.Or { - return false, nil - } - } - - for keyPattern, valuePattern := range when.Annotations { - match := false - for key, value := range annotations { - match, err = regexp.MatchString(keyPattern, key) - if err != nil { - return false, fmt.Errorf("annotation key: %w", err) - } - if match { - match, err = regexp.MatchString(valuePattern, value) - if err != nil { - return false, fmt.Errorf("annotation value: %w", err) - } - if match { - break - } - } - } - if match { - if when.Or { - return true, nil - } - matches++ - } else if !when.Or { - return false, nil - } - } - - if config.Process != nil && len(when.Commands) > 0 { - if len(config.Process.Args) == 0 { - return false, errors.New("process.args must have at least one entry") - } - command := config.Process.Args[0] - for _, cmdPattern := range when.Commands { - match, err := regexp.MatchString(cmdPattern, command) - if err != nil { - return false, fmt.Errorf("command: %w", err) - } - if match { - return true, nil - } - } - return false, nil - } - - return matches > 0, nil -} diff --git a/pkg/hooks/1.0.0/when_test.go b/pkg/hooks/1.0.0/when_test.go deleted file mode 100644 index 94b0c3830..000000000 --- a/pkg/hooks/1.0.0/when_test.go +++ /dev/null @@ -1,329 +0,0 @@ -package hook - -import ( - "fmt" - "testing" - - rspec "github.com/opencontainers/runtime-spec/specs-go" - "github.com/stretchr/testify/assert" -) - -func TestNoMatch(t *testing.T) { - config := &rspec.Spec{} - for _, o := range []bool{true, false} { - or := o - t.Run(fmt.Sprintf("or %t", or), func(t *testing.T) { - when := When{Or: or} - match, err := when.Match(config, map[string]string{}, false) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, false, match) - }) - } -} - -func TestAlways(t *testing.T) { - config := &rspec.Spec{} - processStruct := &rspec.Process{ - Args: []string{"/bin/sh", "a", "b"}, - } - for _, a := range []bool{true, false} { - always := a - for _, o := range []bool{true, false} { - or := o - for _, p := range []*rspec.Process{processStruct, nil} { - process := p - t.Run(fmt.Sprintf("always %t, or %t, has process %t", always, or, process != nil), func(t *testing.T) { - config.Process = process - when := When{Always: &always, Or: or} - match, err := when.Match(config, map[string]string{}, false) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, always, match) - }) - } - } - } -} - -func TestHasBindMountsAnd(t *testing.T) { - hasBindMounts := true - when := When{HasBindMounts: &hasBindMounts} - config := &rspec.Spec{} - for _, b := range []bool{false, true} { - containerHasBindMounts := b - t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) { - match, err := when.Match(config, map[string]string{}, containerHasBindMounts) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, containerHasBindMounts, match) - }) - } -} - -func TestHasBindMountsOr(t *testing.T) { - hasBindMounts := true - when := When{HasBindMounts: &hasBindMounts, Or: true} - config := &rspec.Spec{} - for _, b := range []bool{false, true} { - containerHasBindMounts := b - t.Run(fmt.Sprintf("%t", containerHasBindMounts), func(t *testing.T) { - match, err := when.Match(config, map[string]string{}, containerHasBindMounts) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, containerHasBindMounts, match) - }) - } -} - -func TestAnnotations(t *testing.T) { - when := When{ - Annotations: map[string]string{ - "^a$": "^b$", - "^c$": "^d$", - }, - } - config := &rspec.Spec{} - for _, tt := range []struct { - name string - annotations map[string]string - or bool - match bool - }{ - { - name: "matching both, and", - annotations: map[string]string{ - "a": "b", - "c": "d", - "e": "f", - }, - or: false, - match: true, - }, - { - name: "matching one, and", - annotations: map[string]string{ - "a": "b", - }, - or: false, - match: false, - }, - { - name: "matching one, or", - annotations: map[string]string{ - "a": "b", - }, - or: true, - match: true, - }, - { - name: "key-only, or", - annotations: map[string]string{ - "a": "bc", - }, - or: true, - match: false, - }, - { - name: "value-only, or", - annotations: map[string]string{ - "ac": "b", - }, - or: true, - match: false, - }, - } { - test := tt - t.Run(test.name, func(t *testing.T) { - when.Or = test.or - match, err := when.Match(config, test.annotations, false) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, test.match, match) - }) - } -} - -func TestCommands(t *testing.T) { - when := When{ - Commands: []string{ - "^/bin/sh$", - }, - } - config := &rspec.Spec{} - for _, tt := range []struct { - name string - process *rspec.Process - match bool - }{ - { - name: "good", - process: &rspec.Process{ - Args: []string{"/bin/sh", "a", "b"}, - }, - match: true, - }, - { - name: "extra characters", - process: &rspec.Process{ - Args: []string{"/bin/shell", "a", "b"}, - }, - match: false, - }, - { - name: "process unset", - match: false, - }, - } { - test := tt - t.Run(test.name, func(t *testing.T) { - config.Process = test.process - match, err := when.Match(config, map[string]string{}, false) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, test.match, match) - }) - } -} - -func TestCommandsEmptyProcessArgs(t *testing.T) { - when := When{ - Commands: []string{ - "^/bin/sh$", - }, - } - config := &rspec.Spec{ - Process: &rspec.Process{}, - } - _, err := when.Match(config, map[string]string{}, false) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, "^process\\.args must have at least one entry$", err.Error()) -} - -func TestHasBindMountsAndCommands(t *testing.T) { - hasBindMounts := true - when := When{ - HasBindMounts: &hasBindMounts, - Commands: []string{ - "^/bin/sh$", - }, - } - config := &rspec.Spec{Process: &rspec.Process{}} - for _, tt := range []struct { - name string - command string - hasBindMounts bool - or bool - match bool - }{ - { - name: "both, and", - command: "/bin/sh", - hasBindMounts: true, - or: false, - match: true, - }, - { - name: "both, or", - command: "/bin/sh", - hasBindMounts: true, - or: true, - match: true, - }, - { - name: "bind, and", - command: "/bin/shell", - hasBindMounts: true, - or: false, - match: false, - }, - { - name: "bind, or", - command: "/bin/shell", - hasBindMounts: true, - or: true, - match: true, - }, - { - name: "command, and", - command: "/bin/sh", - hasBindMounts: false, - or: false, - match: false, - }, - { - name: "command, or", - command: "/bin/sh", - hasBindMounts: false, - or: true, - match: true, - }, - { - name: "neither, and", - command: "/bin/shell", - hasBindMounts: false, - or: false, - match: false, - }, - { - name: "neither, or", - command: "/bin/shell", - hasBindMounts: false, - or: true, - match: false, - }, - } { - test := tt - t.Run(test.name, func(t *testing.T) { - config.Process.Args = []string{test.command} - when.Or = test.or - match, err := when.Match(config, map[string]string{}, test.hasBindMounts) - if err != nil { - t.Fatal(err) - } - assert.Equal(t, test.match, match) - }) - } -} - -func TestInvalidRegexp(t *testing.T) { - config := &rspec.Spec{Process: &rspec.Process{Args: []string{"/bin/sh"}}} - for _, tt := range []struct { - name string - when When - expected string - }{ - { - name: "invalid-annotation-key", - when: When{Annotations: map[string]string{"[": "a"}}, - expected: "^annotation key: error parsing regexp: .*", - }, - { - name: "invalid-annotation-value", - when: When{Annotations: map[string]string{"a": "["}}, - expected: "^annotation value: error parsing regexp: .*", - }, - { - name: "invalid-command", - when: When{Commands: []string{"["}}, - expected: "^command: error parsing regexp: .*", - }, - } { - test := tt - t.Run(test.name, func(t *testing.T) { - _, err := test.when.Match(config, map[string]string{"a": "b"}, false) - if err == nil { - t.Fatal("unexpected success") - } - assert.Regexp(t, test.expected, err.Error()) - }) - } -} -- cgit v1.2.3-54-g00ecf