vendor: upgrade containers/storage
Signed-off-by: Antonio Murdaca <runcom@redhat.com>
This commit is contained in:
parent
5addc8caf0
commit
ecd0006e80
114 changed files with 11464 additions and 1003 deletions
426
vendor/github.com/containers/storage/images.go
generated
vendored
Normal file
426
vendor/github.com/containers/storage/images.go
generated
vendored
Normal file
|
@ -0,0 +1,426 @@
|
|||
package storage
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"github.com/containers/storage/pkg/ioutils"
|
||||
"github.com/containers/storage/pkg/stringid"
|
||||
"github.com/containers/storage/pkg/truncindex"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrImageUnknown indicates that there was no image with the specified name or ID
|
||||
ErrImageUnknown = errors.New("image not known")
|
||||
)
|
||||
|
||||
// An Image is a reference to a layer and an associated metadata string.
|
||||
type Image struct {
|
||||
// ID is either one which was specified at create-time, or a random
|
||||
// value which was generated by the library.
|
||||
ID string `json:"id"`
|
||||
|
||||
// Names is an optional set of user-defined convenience values. The
|
||||
// image can be referred to by its ID or any of its names. Names are
|
||||
// unique among images.
|
||||
Names []string `json:"names,omitempty"`
|
||||
|
||||
// TopLayer is the ID of the topmost layer of the image itself.
|
||||
// Multiple images can refer to the same top layer.
|
||||
TopLayer string `json:"layer"`
|
||||
|
||||
// Metadata is data we keep for the convenience of the caller. It is not
|
||||
// expected to be large, since it is kept in memory.
|
||||
Metadata string `json:"metadata,omitempty"`
|
||||
|
||||
// BigDataNames is a list of names of data items that we keep for the
|
||||
// convenience of the caller. They can be large, and are only in
|
||||
// memory when being read from or written to disk.
|
||||
BigDataNames []string `json:"big-data-names,omitempty"`
|
||||
|
||||
// BigDataSizes maps the names in BigDataNames to the sizes of the data
|
||||
// that has been stored, if they're known.
|
||||
BigDataSizes map[string]int64 `json:"big-data-sizes,omitempty"`
|
||||
|
||||
Flags map[string]interface{} `json:"flags,omitempty"`
|
||||
}
|
||||
|
||||
// ImageStore provides bookkeeping for information about Images.
|
||||
type ImageStore interface {
|
||||
FileBasedStore
|
||||
MetadataStore
|
||||
BigDataStore
|
||||
FlaggableStore
|
||||
|
||||
// Create creates an image that has a specified ID (or a random one) and
|
||||
// optional names, using the specified layer as its topmost (hopefully
|
||||
// read-only) layer. That layer can be referenced by multiple images.
|
||||
Create(id string, names []string, layer, metadata string) (*Image, error)
|
||||
|
||||
// SetNames replaces the list of names associated with an image with the
|
||||
// supplied values.
|
||||
SetNames(id string, names []string) error
|
||||
|
||||
// Exists checks if there is an image with the given ID or name.
|
||||
Exists(id string) bool
|
||||
|
||||
// Get retrieves information about an image given an ID or name.
|
||||
Get(id string) (*Image, error)
|
||||
|
||||
// Delete removes the record of the image.
|
||||
Delete(id string) error
|
||||
|
||||
// Wipe removes records of all images.
|
||||
Wipe() error
|
||||
|
||||
// Lookup attempts to translate a name to an ID. Most methods do this
|
||||
// implicitly.
|
||||
Lookup(name string) (string, error)
|
||||
|
||||
// Images returns a slice enumerating the known images.
|
||||
Images() ([]Image, error)
|
||||
}
|
||||
|
||||
type imageStore struct {
|
||||
lockfile Locker
|
||||
dir string
|
||||
images []Image
|
||||
idindex *truncindex.TruncIndex
|
||||
byid map[string]*Image
|
||||
byname map[string]*Image
|
||||
}
|
||||
|
||||
func (r *imageStore) Images() ([]Image, error) {
|
||||
return r.images, nil
|
||||
}
|
||||
|
||||
func (r *imageStore) imagespath() string {
|
||||
return filepath.Join(r.dir, "images.json")
|
||||
}
|
||||
|
||||
func (r *imageStore) datadir(id string) string {
|
||||
return filepath.Join(r.dir, id)
|
||||
}
|
||||
|
||||
func (r *imageStore) datapath(id, key string) string {
|
||||
return filepath.Join(r.datadir(id), makeBigDataBaseName(key))
|
||||
}
|
||||
|
||||
func (r *imageStore) Load() error {
|
||||
needSave := false
|
||||
rpath := r.imagespath()
|
||||
data, err := ioutil.ReadFile(rpath)
|
||||
if err != nil && !os.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
images := []Image{}
|
||||
idlist := []string{}
|
||||
ids := make(map[string]*Image)
|
||||
names := make(map[string]*Image)
|
||||
if err = json.Unmarshal(data, &images); len(data) == 0 || err == nil {
|
||||
for n, image := range images {
|
||||
ids[image.ID] = &images[n]
|
||||
idlist = append(idlist, image.ID)
|
||||
for _, name := range image.Names {
|
||||
if conflict, ok := names[name]; ok {
|
||||
r.removeName(conflict, name)
|
||||
needSave = true
|
||||
}
|
||||
names[name] = &images[n]
|
||||
}
|
||||
}
|
||||
}
|
||||
r.images = images
|
||||
r.idindex = truncindex.NewTruncIndex(idlist)
|
||||
r.byid = ids
|
||||
r.byname = names
|
||||
if needSave {
|
||||
r.Touch()
|
||||
return r.Save()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *imageStore) Save() error {
|
||||
rpath := r.imagespath()
|
||||
if err := os.MkdirAll(filepath.Dir(rpath), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
jdata, err := json.Marshal(&r.images)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return ioutils.AtomicWriteFile(rpath, jdata, 0600)
|
||||
}
|
||||
|
||||
func newImageStore(dir string) (ImageStore, error) {
|
||||
if err := os.MkdirAll(dir, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lockfile, err := GetLockfile(filepath.Join(dir, "images.lock"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lockfile.Lock()
|
||||
defer lockfile.Unlock()
|
||||
istore := imageStore{
|
||||
lockfile: lockfile,
|
||||
dir: dir,
|
||||
images: []Image{},
|
||||
byid: make(map[string]*Image),
|
||||
byname: make(map[string]*Image),
|
||||
}
|
||||
if err := istore.Load(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &istore, nil
|
||||
}
|
||||
|
||||
func (r *imageStore) lookup(id string) (*Image, bool) {
|
||||
if image, ok := r.byid[id]; ok {
|
||||
return image, ok
|
||||
} else if image, ok := r.byname[id]; ok {
|
||||
return image, ok
|
||||
} else if longid, err := r.idindex.Get(id); err == nil {
|
||||
image, ok := r.byid[longid]
|
||||
return image, ok
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (r *imageStore) ClearFlag(id string, flag string) error {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrImageUnknown
|
||||
}
|
||||
delete(image.Flags, flag)
|
||||
return r.Save()
|
||||
}
|
||||
|
||||
func (r *imageStore) SetFlag(id string, flag string, value interface{}) error {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrImageUnknown
|
||||
}
|
||||
image.Flags[flag] = value
|
||||
return r.Save()
|
||||
}
|
||||
|
||||
func (r *imageStore) Create(id string, names []string, layer, metadata string) (image *Image, err error) {
|
||||
if id == "" {
|
||||
id = stringid.GenerateRandomID()
|
||||
_, idInUse := r.byid[id]
|
||||
for idInUse {
|
||||
id = stringid.GenerateRandomID()
|
||||
_, idInUse = r.byid[id]
|
||||
}
|
||||
}
|
||||
if _, idInUse := r.byid[id]; idInUse {
|
||||
return nil, ErrDuplicateID
|
||||
}
|
||||
for _, name := range names {
|
||||
if _, nameInUse := r.byname[name]; nameInUse {
|
||||
return nil, ErrDuplicateName
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
newImage := Image{
|
||||
ID: id,
|
||||
Names: names,
|
||||
TopLayer: layer,
|
||||
Metadata: metadata,
|
||||
BigDataNames: []string{},
|
||||
BigDataSizes: make(map[string]int64),
|
||||
Flags: make(map[string]interface{}),
|
||||
}
|
||||
r.images = append(r.images, newImage)
|
||||
image = &r.images[len(r.images)-1]
|
||||
r.idindex.Add(id)
|
||||
r.byid[id] = image
|
||||
for _, name := range names {
|
||||
r.byname[name] = image
|
||||
}
|
||||
err = r.Save()
|
||||
}
|
||||
return image, err
|
||||
}
|
||||
|
||||
func (r *imageStore) Metadata(id string) (string, error) {
|
||||
if image, ok := r.lookup(id); ok {
|
||||
return image.Metadata, nil
|
||||
}
|
||||
return "", ErrImageUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) SetMetadata(id, metadata string) error {
|
||||
if image, ok := r.lookup(id); ok {
|
||||
image.Metadata = metadata
|
||||
return r.Save()
|
||||
}
|
||||
return ErrImageUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) removeName(image *Image, name string) {
|
||||
image.Names = stringSliceWithoutValue(image.Names, name)
|
||||
}
|
||||
|
||||
func (r *imageStore) SetNames(id string, names []string) error {
|
||||
if image, ok := r.lookup(id); ok {
|
||||
for _, name := range image.Names {
|
||||
delete(r.byname, name)
|
||||
}
|
||||
for _, name := range names {
|
||||
if otherImage, ok := r.byname[name]; ok {
|
||||
r.removeName(otherImage, name)
|
||||
}
|
||||
r.byname[name] = image
|
||||
}
|
||||
image.Names = names
|
||||
return r.Save()
|
||||
}
|
||||
return ErrImageUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) Delete(id string) error {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrImageUnknown
|
||||
}
|
||||
id = image.ID
|
||||
newImages := []Image{}
|
||||
for _, candidate := range r.images {
|
||||
if candidate.ID != id {
|
||||
newImages = append(newImages, candidate)
|
||||
}
|
||||
}
|
||||
delete(r.byid, id)
|
||||
r.idindex.Delete(id)
|
||||
for _, name := range image.Names {
|
||||
delete(r.byname, name)
|
||||
}
|
||||
r.images = newImages
|
||||
if err := r.Save(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := os.RemoveAll(r.datadir(id)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *imageStore) Get(id string) (*Image, error) {
|
||||
if image, ok := r.lookup(id); ok {
|
||||
return image, nil
|
||||
}
|
||||
return nil, ErrImageUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) Lookup(name string) (id string, err error) {
|
||||
if image, ok := r.lookup(name); ok {
|
||||
return image.ID, nil
|
||||
}
|
||||
return "", ErrImageUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) Exists(id string) bool {
|
||||
_, ok := r.lookup(id)
|
||||
return ok
|
||||
}
|
||||
|
||||
func (r *imageStore) BigData(id, key string) ([]byte, error) {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return nil, ErrImageUnknown
|
||||
}
|
||||
return ioutil.ReadFile(r.datapath(image.ID, key))
|
||||
}
|
||||
|
||||
func (r *imageStore) BigDataSize(id, key string) (int64, error) {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return -1, ErrImageUnknown
|
||||
}
|
||||
if size, ok := image.BigDataSizes[key]; ok {
|
||||
return size, nil
|
||||
}
|
||||
return -1, ErrSizeUnknown
|
||||
}
|
||||
|
||||
func (r *imageStore) BigDataNames(id string) ([]string, error) {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return nil, ErrImageUnknown
|
||||
}
|
||||
return image.BigDataNames, nil
|
||||
}
|
||||
|
||||
func (r *imageStore) SetBigData(id, key string, data []byte) error {
|
||||
image, ok := r.lookup(id)
|
||||
if !ok {
|
||||
return ErrImageUnknown
|
||||
}
|
||||
if err := os.MkdirAll(r.datadir(image.ID), 0700); err != nil {
|
||||
return err
|
||||
}
|
||||
err := ioutils.AtomicWriteFile(r.datapath(image.ID, key), data, 0600)
|
||||
if err == nil {
|
||||
add := true
|
||||
save := false
|
||||
oldSize, ok := image.BigDataSizes[key]
|
||||
image.BigDataSizes[key] = int64(len(data))
|
||||
if !ok || oldSize != image.BigDataSizes[key] {
|
||||
save = true
|
||||
}
|
||||
for _, name := range image.BigDataNames {
|
||||
if name == key {
|
||||
add = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if add {
|
||||
image.BigDataNames = append(image.BigDataNames, key)
|
||||
save = true
|
||||
}
|
||||
if save {
|
||||
err = r.Save()
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (r *imageStore) Wipe() error {
|
||||
ids := []string{}
|
||||
for id := range r.byid {
|
||||
ids = append(ids, id)
|
||||
}
|
||||
for _, id := range ids {
|
||||
if err := r.Delete(id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *imageStore) Lock() {
|
||||
r.lockfile.Lock()
|
||||
}
|
||||
|
||||
func (r *imageStore) Unlock() {
|
||||
r.lockfile.Unlock()
|
||||
}
|
||||
|
||||
func (r *imageStore) Touch() error {
|
||||
return r.lockfile.Touch()
|
||||
}
|
||||
|
||||
func (r *imageStore) Modified() (bool, error) {
|
||||
return r.lockfile.Modified()
|
||||
}
|
||||
|
||||
func (r *imageStore) TouchedSince(when time.Time) bool {
|
||||
return r.lockfile.TouchedSince(when)
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue