github.com/quay/claircore@v1.5.28/libvuln/driver/updaterset.go (about)

     1  package driver
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"regexp"
     7  )
     8  
     9  // ErrExists is an error returned if the updater
    10  // already exists in the set.
    11  type ErrExists struct {
    12  	Updater []string
    13  }
    14  
    15  func (e ErrExists) Error() string {
    16  	return fmt.Sprintf("reused names: %v", e.Updater)
    17  }
    18  
    19  // UpdaterSetFactory is used to construct updaters at run-time.
    20  type UpdaterSetFactory interface {
    21  	UpdaterSet(context.Context) (UpdaterSet, error)
    22  }
    23  
    24  type UpdaterSetFactoryFunc func(context.Context) (UpdaterSet, error)
    25  
    26  func (u UpdaterSetFactoryFunc) UpdaterSet(ctx context.Context) (UpdaterSet, error) {
    27  	return u(ctx)
    28  }
    29  
    30  // StaticSet creates an UpdaterSetFunc returning the provided set.
    31  func StaticSet(s UpdaterSet) UpdaterSetFactory {
    32  	return UpdaterSetFactoryFunc(func(_ context.Context) (UpdaterSet, error) {
    33  		return s, nil
    34  	})
    35  }
    36  
    37  // UpdaterSet holds a deduplicated set of updaters.
    38  type UpdaterSet struct {
    39  	set map[string]Updater
    40  }
    41  
    42  // NewUpdaterSet returns an initialized UpdaterSet.
    43  func NewUpdaterSet() UpdaterSet {
    44  	return UpdaterSet{
    45  		set: map[string]Updater{},
    46  	}
    47  }
    48  
    49  // Add will add an Updater to the set.
    50  //
    51  // An error will be reported if an updater with the same name already exists.
    52  func (s *UpdaterSet) Add(u Updater) error {
    53  	if _, ok := s.set[u.Name()]; ok {
    54  		return ErrExists{[]string{u.Name()}}
    55  	}
    56  
    57  	s.set[u.Name()] = u
    58  	return nil
    59  }
    60  
    61  // Merge will merge the UpdaterSet provided as argument
    62  // into the UpdaterSet provided as the function receiver.
    63  //
    64  // If an updater exists in the target set an error
    65  // specifying which updaters could not be merged is returned.
    66  func (s *UpdaterSet) Merge(set UpdaterSet) error {
    67  	exists := make([]string, 0, len(set.set))
    68  	for n := range set.set {
    69  		if _, ok := s.set[n]; ok {
    70  			exists = append(exists, n)
    71  		}
    72  	}
    73  
    74  	if len(exists) > 0 {
    75  		return ErrExists{exists}
    76  	}
    77  
    78  	for n, u := range set.set {
    79  		s.set[n] = u
    80  	}
    81  	return nil
    82  }
    83  
    84  // Updaters returns the updaters within the set as slice.
    85  func (s *UpdaterSet) Updaters() []Updater {
    86  	u := make([]Updater, 0, len(s.set))
    87  	for _, v := range s.set {
    88  		u = append(u, v)
    89  	}
    90  	return u
    91  }
    92  
    93  // RegexFilter will remove any updaters from the set whose reported names do not
    94  // match the provided regexp string.
    95  func (s *UpdaterSet) RegexFilter(regex string) error {
    96  	re, err := regexp.Compile(regex)
    97  	if err != nil {
    98  		return fmt.Errorf("regex failed to compile: %v", err)
    99  	}
   100  	for name, u := range s.set {
   101  		if !re.MatchString(u.Name()) {
   102  			delete(s.set, name)
   103  		}
   104  	}
   105  	return nil
   106  }