github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/pkg/hooks/read.go (about)

     1  // Package hooks implements CRI-O's hook handling.
     2  package hooks
     3  
     4  import (
     5  	"encoding/json"
     6  	"io/ioutil"
     7  	"os"
     8  	"path/filepath"
     9  	"strings"
    10  
    11  	old "github.com/containers/podman/v2/pkg/hooks/0.1.0"
    12  	current "github.com/containers/podman/v2/pkg/hooks/1.0.0"
    13  	"github.com/pkg/errors"
    14  	"github.com/sirupsen/logrus"
    15  )
    16  
    17  type reader func(content []byte) (*current.Hook, error)
    18  
    19  var (
    20  	// ErrNoJSONSuffix represents hook-add attempts where the filename
    21  	// does not end in '.json'.
    22  	ErrNoJSONSuffix = errors.New("hook filename does not end in '.json'")
    23  
    24  	// Readers registers per-version hook readers.
    25  	Readers = map[string]reader{}
    26  )
    27  
    28  // Read reads a hook JSON file, verifies it, and returns the hook configuration.
    29  func Read(path string, extensionStages []string) (*current.Hook, error) {
    30  	if !strings.HasSuffix(path, ".json") {
    31  		return nil, ErrNoJSONSuffix
    32  	}
    33  	content, err := ioutil.ReadFile(path)
    34  	if err != nil {
    35  		return nil, err
    36  	}
    37  	hook, err := read(content)
    38  	if err != nil {
    39  		return nil, errors.Wrapf(err, "parsing hook %q", path)
    40  	}
    41  	err = hook.Validate(extensionStages)
    42  	return hook, err
    43  }
    44  
    45  func read(content []byte) (hook *current.Hook, err error) {
    46  	var ver version
    47  	if err := json.Unmarshal(content, &ver); err != nil {
    48  		return nil, errors.Wrap(err, "version check")
    49  	}
    50  	reader, ok := Readers[ver.Version]
    51  	if !ok {
    52  		return nil, errors.Errorf("unrecognized hook version: %q", ver.Version)
    53  	}
    54  
    55  	hook, err = reader(content)
    56  	if err != nil {
    57  		return hook, errors.Wrap(err, ver.Version)
    58  	}
    59  	return hook, err
    60  }
    61  
    62  // ReadDir reads hook JSON files from a directory into the given map,
    63  // clobbering any previous entries with the same filenames.
    64  func ReadDir(path string, extensionStages []string, hooks map[string]*current.Hook) error {
    65  	logrus.Debugf("reading hooks from %s", path)
    66  	files, err := ioutil.ReadDir(path)
    67  	if err != nil {
    68  		return err
    69  	}
    70  	res := err
    71  	for _, file := range files {
    72  		filePath := filepath.Join(path, file.Name())
    73  		hook, err := Read(filePath, extensionStages)
    74  		if err != nil {
    75  			if err == ErrNoJSONSuffix {
    76  				continue
    77  			}
    78  			if os.IsNotExist(err) {
    79  				if err2, ok := err.(*os.PathError); ok && err2.Path == filePath {
    80  					continue
    81  				}
    82  			}
    83  			if res == nil {
    84  				res = err
    85  			} else {
    86  				res = errors.Wrapf(res, "%v", err)
    87  			}
    88  			continue
    89  		}
    90  		hooks[file.Name()] = hook
    91  		logrus.Debugf("added hook %s", filePath)
    92  	}
    93  	return res
    94  }
    95  
    96  func init() {
    97  	Readers[current.Version] = current.Read
    98  	Readers[old.Version] = old.Read
    99  	Readers[""] = old.Read
   100  }