96 lines
		
	
	
		
			2.1 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			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:"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, 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 && 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, errors.Wrap(err, "command")
 | |
| 			}
 | |
| 			if match {
 | |
| 				return true, nil
 | |
| 			}
 | |
| 		}
 | |
| 		return false, nil
 | |
| 	}
 | |
| 
 | |
| 	return matches > 0, nil
 | |
| }
 |