Files
podman/pkg/hooks/1.0.0/when.go
W. Trevor King a7180cd545 hooks/1.0.0: Error on empty process.args instead of panicking
The process property is optional [1], which this package already
handled appropriately, although I've added a new test here to guard
against regressions.

The process.args entry is required when process is set [2], and it's
also required to contain at least one entry [3].  The previous
implementation here assumed that would always be satisfied, and
panicked on empty process.args.  With this commit, we avoid the panic
and instead return an error message explaining why the input was
invalid.

[1]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/config.md#L145
[2]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/config.md#L157
[3]: https://github.com/opencontainers/runtime-spec/blame/v1.0.1/config.md#L158

Reported-by: Brent Baude <bbaude@redhat.com>
Signed-off-by: W. Trevor King <wking@tremily.us>

Closes: #829
Approved by: mheon
2018-05-24 21:27:05 +00:00

96 lines
2.1 KiB
Go

package hook
import (
"regexp"
rspec "github.com/opencontainers/runtime-spec/specs-go"
"github.com/pkg/errors"
)
// When holds hook-injection conditions.
type When struct {
Always *bool `json:"always,omitempty"`
Annotations map[string]string `json:"annotation,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, errors.Wrap(err, "annotation key")
}
if match {
match, err = regexp.MatchString(valuePattern, value)
if err != nil {
return false, errors.Wrap(err, "annotation value")
}
if match {
break
}
}
}
if match {
if when.Or {
return true, nil
}
matches++
} else if !when.Or {
return false, nil
}
}
if config.Process != nil {
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, errors.Wrap(err, "command")
}
if match {
return true, nil
}
}
return false, nil
}
return matches > 0, nil
}