github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/pkg/hooks/1.0.0/when.go (about)

     1  package hook
     2  
     3  import (
     4  	"regexp"
     5  
     6  	rspec "github.com/opencontainers/runtime-spec/specs-go"
     7  	"github.com/pkg/errors"
     8  )
     9  
    10  // When holds hook-injection conditions.
    11  type When struct {
    12  	Always        *bool             `json:"always,omitempty"`
    13  	Annotations   map[string]string `json:"annotations,omitempty"`
    14  	Commands      []string          `json:"commands,omitempty"`
    15  	HasBindMounts *bool             `json:"hasBindMounts,omitempty"`
    16  
    17  	// Or enables any-of matching.
    18  	//
    19  	// Deprecated: this property is for is backwards-compatibility with
    20  	// 0.1.0 hooks.  It will be removed when we drop support for them.
    21  	Or bool `json:"-"`
    22  }
    23  
    24  // Match returns true if the given conditions match the configuration.
    25  func (when *When) Match(config *rspec.Spec, annotations map[string]string, hasBindMounts bool) (match bool, err error) {
    26  	matches := 0
    27  
    28  	if when.Always != nil {
    29  		if *when.Always {
    30  			if when.Or {
    31  				return true, nil
    32  			}
    33  			matches++
    34  		} else if !when.Or {
    35  			return false, nil
    36  		}
    37  	}
    38  
    39  	if when.HasBindMounts != nil {
    40  		if *when.HasBindMounts && hasBindMounts {
    41  			if when.Or {
    42  				return true, nil
    43  			}
    44  			matches++
    45  		} else if !when.Or {
    46  			return false, nil
    47  		}
    48  	}
    49  
    50  	for keyPattern, valuePattern := range when.Annotations {
    51  		match := false
    52  		for key, value := range annotations {
    53  			match, err = regexp.MatchString(keyPattern, key)
    54  			if err != nil {
    55  				return false, errors.Wrap(err, "annotation key")
    56  			}
    57  			if match {
    58  				match, err = regexp.MatchString(valuePattern, value)
    59  				if err != nil {
    60  					return false, errors.Wrap(err, "annotation value")
    61  				}
    62  				if match {
    63  					break
    64  				}
    65  			}
    66  		}
    67  		if match {
    68  			if when.Or {
    69  				return true, nil
    70  			}
    71  			matches++
    72  		} else if !when.Or {
    73  			return false, nil
    74  		}
    75  	}
    76  
    77  	if config.Process != nil && len(when.Commands) > 0 {
    78  		if len(config.Process.Args) == 0 {
    79  			return false, errors.New("process.args must have at least one entry")
    80  		}
    81  		command := config.Process.Args[0]
    82  		for _, cmdPattern := range when.Commands {
    83  			match, err := regexp.MatchString(cmdPattern, command)
    84  			if err != nil {
    85  				return false, errors.Wrap(err, "command")
    86  			}
    87  			if match {
    88  				return true, nil
    89  			}
    90  		}
    91  		return false, nil
    92  	}
    93  
    94  	return matches > 0, nil
    95  }