From bb4f77a0c5711583fad5afbfc3cbfe556096d9ed Mon Sep 17 00:00:00 2001 From: Sascha Grunert Date: Fri, 29 Nov 2019 08:59:25 +0100 Subject: [PATCH] Add ability to list images on push Signed-off-by: Sascha Grunert --- go.mod | 2 + go.sum | 19 + libpod/storage.go | 4 +- test/system/050-stop.bats | 6 +- vendor/github.com/containers/storage/Makefile | 11 +- vendor/github.com/containers/storage/VERSION | 2 +- .../containers/storage/containers.go | 4 + .../github.com/containers/storage/images.go | 4 + .../containers/storage/images_ffjson.go | 2 +- .../github.com/containers/storage/layers.go | 16 +- .../containers/storage/layers_ffjson.go | 2156 +++++++++++++++++ .../containers/storage/lockfile_compat.go | 4 + .../storage/pkg/lockfile/lockfile.go | 24 +- .../storage/pkg/lockfile/lockfile_unix.go | 12 +- vendor/github.com/containers/storage/store.go | 215 +- vendor/modules.txt | 2 +- 16 files changed, 2411 insertions(+), 72 deletions(-) create mode 100644 vendor/github.com/containers/storage/layers_ffjson.go diff --git a/go.mod b/go.mod index 9947467044..882f48aae5 100644 --- a/go.mod +++ b/go.mod @@ -82,3 +82,5 @@ require ( k8s.io/client-go v0.0.0-20190620085101-78d2af792bab k8s.io/utils v0.0.0-20190607212802-c55fbcfc754a // indirect ) + +replace github.com/containers/storage => github.com/saschagrunert/storage v1.12.3-0.20200225133936-b4f34141d69e diff --git a/go.sum b/go.sum index 0b959646c4..0ece67c6d0 100644 --- a/go.sum +++ b/go.sum @@ -396,6 +396,25 @@ github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8 h1:2c1EFnZHIPCW8qKWgHMH/fX2PkSabFc5mrVzfUNdg5U= github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiBQGYcxhMZ6gUqHn6pYNLypFAvaL3UvgZLR0U4= +github.com/saschagrunert/storage v1.12.3-0.20200210095711-e760119c4258 h1:iGKGMWqU1zwxlSstCWbJdyka/vLngJfyk+9EOj/1zII= +github.com/saschagrunert/storage v1.12.3-0.20200210095711-e760119c4258/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200210135817-4d931f858050 h1:Uy+tPmj3uJaOh7BWGobSr9154CCgAO+en1qdFh4/KNU= +github.com/saschagrunert/storage v1.12.3-0.20200210135817-4d931f858050/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200211085627-66295e35a07d h1:Mv4SDxIB+uJUB1wuVtspU0HUOLSQvaV/GFqjjwRMKS0= +github.com/saschagrunert/storage v1.12.3-0.20200211085627-66295e35a07d/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200211090017-75375da2a194 h1:D0Dj3OleEsBhdICzyHG8ALxvf+7qapCT1x3BNRkTiSs= +github.com/saschagrunert/storage v1.12.3-0.20200211090017-75375da2a194/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200211092915-485fad532f1b h1:FQr/wMBmEDG6X6dzL1oT6dkUfTaAKIFl9HgtKvqGNmk= +github.com/saschagrunert/storage v1.12.3-0.20200211092915-485fad532f1b/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200212083334-632bd41bbbe6 h1:PLfqsUujUizh3OHFaicll+jLobcxu3xTGpZfcfAKO8o= +github.com/saschagrunert/storage v1.12.3-0.20200212083334-632bd41bbbe6/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200212083441-9fef53d70652 h1:tWV38lp3QIiVgagqcQpfVwooOpYnq/aH90Mm87JEHWc= +github.com/saschagrunert/storage v1.12.3-0.20200212083441-9fef53d70652/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200225133615-0f950a484f27 h1:H6lwkveMoYj4AJIh1aOqCstUM8TiGrjluHuv/BD9r3E= +github.com/saschagrunert/storage v1.12.3-0.20200225133615-0f950a484f27/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/saschagrunert/storage v1.12.3-0.20200225133936-b4f34141d69e h1:aAPWr45ev3v5eTCLeEZV4lMiZMysJrIN9PXxuo1vnww= +github.com/saschagrunert/storage v1.12.3-0.20200225133936-b4f34141d69e/go.mod h1:zhvjIIl/fR6wt/lgqQAC+xanHQ+8gUQ0GBVeXYN81qI= +github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4 h1:rOG9oHVIndNR14f3HRyBy9UPQYmIPniWqTU1TDdHhq4= github.com/seccomp/containers-golang v0.0.0-20180629143253-cdfdaa7543f4/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA= github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f h1:OtU/w6sBKmXYaw2KEODxjcYi3oPSyyslhgGFgIJVGAI= github.com/seccomp/containers-golang v0.0.0-20190312124753-8ca8945ccf5f/go.mod h1:f/98/SnvAzhAEFQJ3u836FePXvcbE8BS0YGMQNn4mhA= diff --git a/libpod/storage.go b/libpod/storage.go index 6375d031bc..39d1ede5bd 100644 --- a/libpod/storage.go +++ b/libpod/storage.go @@ -282,12 +282,12 @@ func (r *storageService) GetMountpoint(id string) (string, error) { } return "", err } - layer, err := r.store.Layer(container.LayerID) + mountPoint, err := r.store.LayerMountpoint(container.LayerID) if err != nil { return "", err } - return layer.MountPoint, nil + return mountPoint, nil } func (r *storageService) GetWorkDir(id string) (string, error) { diff --git a/test/system/050-stop.bats b/test/system/050-stop.bats index 093606ecea..1a094fcdd4 100644 --- a/test/system/050-stop.bats +++ b/test/system/050-stop.bats @@ -14,7 +14,7 @@ load helpers # Confirm that container is stopped run_podman inspect --format '{{.State.Status}} {{.State.ExitCode}}' $cid - is "$output" "exited \+137" "Status and exit code of stopped container" + is "$output" ".* 137" "Status and exit code of stopped container" # The initial SIGTERM is ignored, so this operation should take # exactly 10 seconds. Give it some leeway. @@ -57,8 +57,8 @@ load helpers # The 'stop' command should return almost instantaneously delta_t=$(( $t1 - $t0 )) - [ $delta_t -le 2 ] ||\ - die "podman stop: took too long ($delta_t seconds; expected <= 2)" + [ $delta_t -le 3 ] ||\ + die "podman stop: took too long ($delta_t seconds; expected <= 3)" run_podman rm $cid done diff --git a/vendor/github.com/containers/storage/Makefile b/vendor/github.com/containers/storage/Makefile index 1b69d6060d..09937303b4 100644 --- a/vendor/github.com/containers/storage/Makefile +++ b/vendor/github.com/containers/storage/Makefile @@ -54,19 +54,19 @@ sources := $(wildcard *.go cmd/containers-storage/*.go drivers/*.go drivers/*/*. containers-storage: $(sources) ## build using gc on the host $(GO_BUILD) -compiler gc $(BUILDFLAGS) ./cmd/containers-storage -layers_ffjson.go: layers.go +layers_ffjson.go: $(FFJSON) layers.go $(RM) $@ $(FFJSON) layers.go -images_ffjson.go: images.go +images_ffjson.go: $(FFJSON) images.go $(RM) $@ $(FFJSON) images.go -containers_ffjson.go: containers.go +containers_ffjson.go: $(FFJSON) containers.go $(RM) $@ $(FFJSON) containers.go -pkg/archive/archive_ffjson.go: pkg/archive/archive.go +pkg/archive/archive_ffjson.go: $(FFJSON) pkg/archive/archive.go $(RM) $@ $(FFJSON) pkg/archive/archive.go @@ -118,6 +118,9 @@ validate: ## validate DCO, gofmt, ./pkg/ isolation, golint,\ngo vet and vendor u install.tools: make -C tests/tools +$(FFJSON): + make -C tests/tools build/ffjson + install.docs: docs make -C docs install diff --git a/vendor/github.com/containers/storage/VERSION b/vendor/github.com/containers/storage/VERSION index 98e863cdf8..9fc9cad08f 100644 --- a/vendor/github.com/containers/storage/VERSION +++ b/vendor/github.com/containers/storage/VERSION @@ -1 +1 @@ -1.15.8 +1.15.9-dev diff --git a/vendor/github.com/containers/storage/containers.go b/vendor/github.com/containers/storage/containers.go index 0c9434a38b..6dc382cdc9 100644 --- a/vendor/github.com/containers/storage/containers.go +++ b/vendor/github.com/containers/storage/containers.go @@ -603,3 +603,7 @@ func (r *containerStore) TouchedSince(when time.Time) bool { func (r *containerStore) Locked() bool { return r.lockfile.Locked() } + +func (r *containerStore) SetReadOnly(ro bool) { + r.lockfile.SetReadOnly(ro) +} diff --git a/vendor/github.com/containers/storage/images.go b/vendor/github.com/containers/storage/images.go index ef95598b8c..35c5650474 100644 --- a/vendor/github.com/containers/storage/images.go +++ b/vendor/github.com/containers/storage/images.go @@ -786,3 +786,7 @@ func (r *imageStore) TouchedSince(when time.Time) bool { func (r *imageStore) Locked() bool { return r.lockfile.Locked() } + +func (r *imageStore) SetReadOnly(ro bool) { + r.lockfile.SetReadOnly(ro) +} diff --git a/vendor/github.com/containers/storage/images_ffjson.go b/vendor/github.com/containers/storage/images_ffjson.go index 0dde97c183..e1954ad041 100644 --- a/vendor/github.com/containers/storage/images_ffjson.go +++ b/vendor/github.com/containers/storage/images_ffjson.go @@ -1,5 +1,5 @@ // Code generated by ffjson . DO NOT EDIT. -// source: ./images.go +// source: images.go package storage diff --git a/vendor/github.com/containers/storage/layers.go b/vendor/github.com/containers/storage/layers.go index dccfc169dc..833946e8bd 100644 --- a/vendor/github.com/containers/storage/layers.go +++ b/vendor/github.com/containers/storage/layers.go @@ -496,11 +496,11 @@ func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Dri if err := os.MkdirAll(layerdir, 0700); err != nil { return nil, err } - lockfile, err := GetLockfile(filepath.Join(layerdir, "layers.lock")) + lockfile, err := GetLockfileRWRO(filepath.Join(layerdir, "layers.lock"), false) if err != nil { return nil, err } - mountsLockfile, err := GetLockfile(filepath.Join(rundir, "mountpoints.lock")) + mountsLockfile, err := GetLockfileRWRO(filepath.Join(rundir, "mountpoints.lock"), false) if err != nil { return nil, err } @@ -523,13 +523,17 @@ func (s *store) newLayerStore(rundir string, layerdir string, driver drivers.Dri } func newROLayerStore(rundir string, layerdir string, driver drivers.Driver) (ROLayerStore, error) { - lockfile, err := GetROLockfile(filepath.Join(layerdir, "layers.lock")) + lockfile, err := GetLockfileRWRO(filepath.Join(layerdir, "layers.lock"), true) + if err != nil { + return nil, err + } + mountsLockfile, err := GetLockfileRWRO(filepath.Join(rundir, "mountpoints.lock"), true) if err != nil { return nil, err } rlstore := layerStore{ lockfile: lockfile, - mountsLockfile: nil, + mountsLockfile: mountsLockfile, driver: driver, rundir: rundir, layerdir: layerdir, @@ -1439,3 +1443,7 @@ func (r *layerStore) TouchedSince(when time.Time) bool { func (r *layerStore) Locked() bool { return r.lockfile.Locked() } + +func (r *layerStore) SetReadOnly(ro bool) { + r.lockfile.SetReadOnly(ro) +} diff --git a/vendor/github.com/containers/storage/layers_ffjson.go b/vendor/github.com/containers/storage/layers_ffjson.go new file mode 100644 index 0000000000..3a10952263 --- /dev/null +++ b/vendor/github.com/containers/storage/layers_ffjson.go @@ -0,0 +1,2156 @@ +// Code generated by ffjson . DO NOT EDIT. +// source: layers.go + +package storage + +import ( + "bytes" + "encoding/json" + "fmt" + "github.com/containers/storage/pkg/archive" + "github.com/containers/storage/pkg/idtools" + "github.com/opencontainers/go-digest" + fflib "github.com/pquerna/ffjson/fflib/v1" +) + +// MarshalJSON marshal bytes to json - template +func (j *DiffOptions) MarshalJSON() ([]byte, error) { + var buf fflib.Buffer + if j == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := j.MarshalJSONBuf(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalJSONBuf marshal buff to json - template +func (j *DiffOptions) MarshalJSONBuf(buf fflib.EncodingBuffer) error { + if j == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + if j.Compression != nil { + buf.WriteString(`{"Compression":`) + fflib.FormatBits2(buf, uint64(*j.Compression), 10, *j.Compression < 0) + } else { + buf.WriteString(`{"Compression":null`) + } + buf.WriteByte('}') + return nil +} + +const ( + ffjtDiffOptionsbase = iota + ffjtDiffOptionsnosuchkey + + ffjtDiffOptionsCompression +) + +var ffjKeyDiffOptionsCompression = []byte("Compression") + +// UnmarshalJSON umarshall json - template of ffjson +func (j *DiffOptions) UnmarshalJSON(input []byte) error { + fs := fflib.NewFFLexer(input) + return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +// UnmarshalJSONFFLexer fast json unmarshall - template ffjson +func (j *DiffOptions) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error + currentKey := ffjtDiffOptionsbase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffjtDiffOptionsnosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + case 'C': + + if bytes.Equal(ffjKeyDiffOptionsCompression, kn) { + currentKey = ffjtDiffOptionsCompression + state = fflib.FFParse_want_colon + goto mainparse + } + + } + + if fflib.EqualFoldRight(ffjKeyDiffOptionsCompression, kn) { + currentKey = ffjtDiffOptionsCompression + state = fflib.FFParse_want_colon + goto mainparse + } + + currentKey = ffjtDiffOptionsnosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffjtDiffOptionsCompression: + goto handle_Compression + + case ffjtDiffOptionsnosuchkey: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +handle_Compression: + + /* handler: j.Compression type=archive.Compression kind=int quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + j.Compression = nil + + } else { + + tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) + + if err != nil { + return fs.WrapErr(err) + } + + ttypval := archive.Compression(tval) + j.Compression = &ttypval + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + + return nil +} + +// MarshalJSON marshal bytes to json - template +func (j *Layer) MarshalJSON() ([]byte, error) { + var buf fflib.Buffer + if j == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := j.MarshalJSONBuf(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalJSONBuf marshal buff to json - template +func (j *Layer) MarshalJSONBuf(buf fflib.EncodingBuffer) error { + if j == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + buf.WriteString(`{ "id":`) + fflib.WriteJsonString(buf, string(j.ID)) + buf.WriteByte(',') + if len(j.Names) != 0 { + buf.WriteString(`"names":`) + if j.Names != nil { + buf.WriteString(`[`) + for i, v := range j.Names { + if i != 0 { + buf.WriteString(`,`) + } + fflib.WriteJsonString(buf, string(v)) + } + buf.WriteString(`]`) + } else { + buf.WriteString(`null`) + } + buf.WriteByte(',') + } + if len(j.Parent) != 0 { + buf.WriteString(`"parent":`) + fflib.WriteJsonString(buf, string(j.Parent)) + buf.WriteByte(',') + } + if len(j.Metadata) != 0 { + buf.WriteString(`"metadata":`) + fflib.WriteJsonString(buf, string(j.Metadata)) + buf.WriteByte(',') + } + if len(j.MountLabel) != 0 { + buf.WriteString(`"mountlabel":`) + fflib.WriteJsonString(buf, string(j.MountLabel)) + buf.WriteByte(',') + } + if true { + buf.WriteString(`"created":`) + + { + + obj, err = j.Created.MarshalJSON() + if err != nil { + return err + } + buf.Write(obj) + + } + buf.WriteByte(',') + } + if len(j.CompressedDigest) != 0 { + buf.WriteString(`"compressed-diff-digest":`) + fflib.WriteJsonString(buf, string(j.CompressedDigest)) + buf.WriteByte(',') + } + if j.CompressedSize != 0 { + buf.WriteString(`"compressed-size":`) + fflib.FormatBits2(buf, uint64(j.CompressedSize), 10, j.CompressedSize < 0) + buf.WriteByte(',') + } + if len(j.UncompressedDigest) != 0 { + buf.WriteString(`"diff-digest":`) + fflib.WriteJsonString(buf, string(j.UncompressedDigest)) + buf.WriteByte(',') + } + if j.UncompressedSize != 0 { + buf.WriteString(`"diff-size":`) + fflib.FormatBits2(buf, uint64(j.UncompressedSize), 10, j.UncompressedSize < 0) + buf.WriteByte(',') + } + if j.CompressionType != 0 { + buf.WriteString(`"compression":`) + fflib.FormatBits2(buf, uint64(j.CompressionType), 10, j.CompressionType < 0) + buf.WriteByte(',') + } + if len(j.UIDs) != 0 { + buf.WriteString(`"uidset":`) + if j.UIDs != nil { + buf.WriteString(`[`) + for i, v := range j.UIDs { + if i != 0 { + buf.WriteString(`,`) + } + fflib.FormatBits2(buf, uint64(v), 10, false) + } + buf.WriteString(`]`) + } else { + buf.WriteString(`null`) + } + buf.WriteByte(',') + } + if len(j.GIDs) != 0 { + buf.WriteString(`"gidset":`) + if j.GIDs != nil { + buf.WriteString(`[`) + for i, v := range j.GIDs { + if i != 0 { + buf.WriteString(`,`) + } + fflib.FormatBits2(buf, uint64(v), 10, false) + } + buf.WriteString(`]`) + } else { + buf.WriteString(`null`) + } + buf.WriteByte(',') + } + if len(j.Flags) != 0 { + buf.WriteString(`"flags":`) + /* Falling back. type=map[string]interface {} kind=map */ + err = buf.Encode(j.Flags) + if err != nil { + return err + } + buf.WriteByte(',') + } + if len(j.UIDMap) != 0 { + buf.WriteString(`"uidmap":`) + if j.UIDMap != nil { + buf.WriteString(`[`) + for i, v := range j.UIDMap { + if i != 0 { + buf.WriteString(`,`) + } + /* Struct fall back. type=idtools.IDMap kind=struct */ + err = buf.Encode(&v) + if err != nil { + return err + } + } + buf.WriteString(`]`) + } else { + buf.WriteString(`null`) + } + buf.WriteByte(',') + } + if len(j.GIDMap) != 0 { + buf.WriteString(`"gidmap":`) + if j.GIDMap != nil { + buf.WriteString(`[`) + for i, v := range j.GIDMap { + if i != 0 { + buf.WriteString(`,`) + } + /* Struct fall back. type=idtools.IDMap kind=struct */ + err = buf.Encode(&v) + if err != nil { + return err + } + } + buf.WriteString(`]`) + } else { + buf.WriteString(`null`) + } + buf.WriteByte(',') + } + buf.Rewind(1) + buf.WriteByte('}') + return nil +} + +const ( + ffjtLayerbase = iota + ffjtLayernosuchkey + + ffjtLayerID + + ffjtLayerNames + + ffjtLayerParent + + ffjtLayerMetadata + + ffjtLayerMountLabel + + ffjtLayerCreated + + ffjtLayerCompressedDigest + + ffjtLayerCompressedSize + + ffjtLayerUncompressedDigest + + ffjtLayerUncompressedSize + + ffjtLayerCompressionType + + ffjtLayerUIDs + + ffjtLayerGIDs + + ffjtLayerFlags + + ffjtLayerUIDMap + + ffjtLayerGIDMap +) + +var ffjKeyLayerID = []byte("id") + +var ffjKeyLayerNames = []byte("names") + +var ffjKeyLayerParent = []byte("parent") + +var ffjKeyLayerMetadata = []byte("metadata") + +var ffjKeyLayerMountLabel = []byte("mountlabel") + +var ffjKeyLayerCreated = []byte("created") + +var ffjKeyLayerCompressedDigest = []byte("compressed-diff-digest") + +var ffjKeyLayerCompressedSize = []byte("compressed-size") + +var ffjKeyLayerUncompressedDigest = []byte("diff-digest") + +var ffjKeyLayerUncompressedSize = []byte("diff-size") + +var ffjKeyLayerCompressionType = []byte("compression") + +var ffjKeyLayerUIDs = []byte("uidset") + +var ffjKeyLayerGIDs = []byte("gidset") + +var ffjKeyLayerFlags = []byte("flags") + +var ffjKeyLayerUIDMap = []byte("uidmap") + +var ffjKeyLayerGIDMap = []byte("gidmap") + +// UnmarshalJSON umarshall json - template of ffjson +func (j *Layer) UnmarshalJSON(input []byte) error { + fs := fflib.NewFFLexer(input) + return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +// UnmarshalJSONFFLexer fast json unmarshall - template ffjson +func (j *Layer) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error + currentKey := ffjtLayerbase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffjtLayernosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + case 'c': + + if bytes.Equal(ffjKeyLayerCreated, kn) { + currentKey = ffjtLayerCreated + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerCompressedDigest, kn) { + currentKey = ffjtLayerCompressedDigest + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerCompressedSize, kn) { + currentKey = ffjtLayerCompressedSize + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerCompressionType, kn) { + currentKey = ffjtLayerCompressionType + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'd': + + if bytes.Equal(ffjKeyLayerUncompressedDigest, kn) { + currentKey = ffjtLayerUncompressedDigest + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerUncompressedSize, kn) { + currentKey = ffjtLayerUncompressedSize + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'f': + + if bytes.Equal(ffjKeyLayerFlags, kn) { + currentKey = ffjtLayerFlags + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'g': + + if bytes.Equal(ffjKeyLayerGIDs, kn) { + currentKey = ffjtLayerGIDs + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerGIDMap, kn) { + currentKey = ffjtLayerGIDMap + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'i': + + if bytes.Equal(ffjKeyLayerID, kn) { + currentKey = ffjtLayerID + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'm': + + if bytes.Equal(ffjKeyLayerMetadata, kn) { + currentKey = ffjtLayerMetadata + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerMountLabel, kn) { + currentKey = ffjtLayerMountLabel + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'n': + + if bytes.Equal(ffjKeyLayerNames, kn) { + currentKey = ffjtLayerNames + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'p': + + if bytes.Equal(ffjKeyLayerParent, kn) { + currentKey = ffjtLayerParent + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'u': + + if bytes.Equal(ffjKeyLayerUIDs, kn) { + currentKey = ffjtLayerUIDs + state = fflib.FFParse_want_colon + goto mainparse + + } else if bytes.Equal(ffjKeyLayerUIDMap, kn) { + currentKey = ffjtLayerUIDMap + state = fflib.FFParse_want_colon + goto mainparse + } + + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerGIDMap, kn) { + currentKey = ffjtLayerGIDMap + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerUIDMap, kn) { + currentKey = ffjtLayerUIDMap + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerFlags, kn) { + currentKey = ffjtLayerFlags + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerGIDs, kn) { + currentKey = ffjtLayerGIDs + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerUIDs, kn) { + currentKey = ffjtLayerUIDs + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerCompressionType, kn) { + currentKey = ffjtLayerCompressionType + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerUncompressedSize, kn) { + currentKey = ffjtLayerUncompressedSize + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerUncompressedDigest, kn) { + currentKey = ffjtLayerUncompressedDigest + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerCompressedSize, kn) { + currentKey = ffjtLayerCompressedSize + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerCompressedDigest, kn) { + currentKey = ffjtLayerCompressedDigest + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerCreated, kn) { + currentKey = ffjtLayerCreated + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerMountLabel, kn) { + currentKey = ffjtLayerMountLabel + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerMetadata, kn) { + currentKey = ffjtLayerMetadata + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerParent, kn) { + currentKey = ffjtLayerParent + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.EqualFoldRight(ffjKeyLayerNames, kn) { + currentKey = ffjtLayerNames + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeyLayerID, kn) { + currentKey = ffjtLayerID + state = fflib.FFParse_want_colon + goto mainparse + } + + currentKey = ffjtLayernosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffjtLayerID: + goto handle_ID + + case ffjtLayerNames: + goto handle_Names + + case ffjtLayerParent: + goto handle_Parent + + case ffjtLayerMetadata: + goto handle_Metadata + + case ffjtLayerMountLabel: + goto handle_MountLabel + + case ffjtLayerCreated: + goto handle_Created + + case ffjtLayerCompressedDigest: + goto handle_CompressedDigest + + case ffjtLayerCompressedSize: + goto handle_CompressedSize + + case ffjtLayerUncompressedDigest: + goto handle_UncompressedDigest + + case ffjtLayerUncompressedSize: + goto handle_UncompressedSize + + case ffjtLayerCompressionType: + goto handle_CompressionType + + case ffjtLayerUIDs: + goto handle_UIDs + + case ffjtLayerGIDs: + goto handle_GIDs + + case ffjtLayerFlags: + goto handle_Flags + + case ffjtLayerUIDMap: + goto handle_UIDMap + + case ffjtLayerGIDMap: + goto handle_GIDMap + + case ffjtLayernosuchkey: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +handle_ID: + + /* handler: j.ID type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.ID = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_Names: + + /* handler: j.Names type=[]string kind=slice quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.Names = nil + } else { + + j.Names = []string{} + + wantVal := true + + for { + + var tmpJNames string + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_brace { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: tmpJNames type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + tmpJNames = string(string(outBuf)) + + } + } + + j.Names = append(j.Names, tmpJNames) + + wantVal = false + } + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_Parent: + + /* handler: j.Parent type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.Parent = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_Metadata: + + /* handler: j.Metadata type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.Metadata = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_MountLabel: + + /* handler: j.MountLabel type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.MountLabel = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_Created: + + /* handler: j.Created type=time.Time kind=struct quoted=false*/ + + { + if tok == fflib.FFTok_null { + + } else { + + tbuf, err := fs.CaptureField(tok) + if err != nil { + return fs.WrapErr(err) + } + + err = j.Created.UnmarshalJSON(tbuf) + if err != nil { + return fs.WrapErr(err) + } + } + state = fflib.FFParse_after_value + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_CompressedDigest: + + /* handler: j.CompressedDigest type=digest.Digest kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.CompressedDigest = digest.Digest(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_CompressedSize: + + /* handler: j.CompressedSize type=int64 kind=int64 quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) + + if err != nil { + return fs.WrapErr(err) + } + + j.CompressedSize = int64(tval) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_UncompressedDigest: + + /* handler: j.UncompressedDigest type=digest.Digest kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Digest", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.UncompressedDigest = digest.Digest(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_UncompressedSize: + + /* handler: j.UncompressedSize type=int64 kind=int64 quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int64", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) + + if err != nil { + return fs.WrapErr(err) + } + + j.UncompressedSize = int64(tval) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_CompressionType: + + /* handler: j.CompressionType type=archive.Compression kind=int quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for Compression", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) + + if err != nil { + return fs.WrapErr(err) + } + + j.CompressionType = archive.Compression(tval) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_UIDs: + + /* handler: j.UIDs type=[]uint32 kind=slice quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.UIDs = nil + } else { + + j.UIDs = []uint32{} + + wantVal := true + + for { + + var tmpJUIDs uint32 + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_brace { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: tmpJUIDs type=uint32 kind=uint32 quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32) + + if err != nil { + return fs.WrapErr(err) + } + + tmpJUIDs = uint32(tval) + + } + } + + j.UIDs = append(j.UIDs, tmpJUIDs) + + wantVal = false + } + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_GIDs: + + /* handler: j.GIDs type=[]uint32 kind=slice quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.GIDs = nil + } else { + + j.GIDs = []uint32{} + + wantVal := true + + for { + + var tmpJGIDs uint32 + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_brace { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: tmpJGIDs type=uint32 kind=uint32 quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for uint32", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseUint(fs.Output.Bytes(), 10, 32) + + if err != nil { + return fs.WrapErr(err) + } + + tmpJGIDs = uint32(tval) + + } + } + + j.GIDs = append(j.GIDs, tmpJGIDs) + + wantVal = false + } + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_Flags: + + /* handler: j.Flags type=map[string]interface {} kind=map quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_bracket && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.Flags = nil + } else { + + j.Flags = make(map[string]interface{}, 0) + + wantVal := true + + for { + + var k string + + var tmpJFlags interface{} + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_bracket { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: k type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + k = string(string(outBuf)) + + } + } + + // Expect ':' after key + tok = fs.Scan() + if tok != fflib.FFTok_colon { + return fs.WrapErr(fmt.Errorf("wanted colon token, but got token: %v", tok)) + } + + tok = fs.Scan() + /* handler: tmpJFlags type=interface {} kind=interface quoted=false*/ + + { + /* Falling back. type=interface {} kind=interface */ + tbuf, err := fs.CaptureField(tok) + if err != nil { + return fs.WrapErr(err) + } + + err = json.Unmarshal(tbuf, &tmpJFlags) + if err != nil { + return fs.WrapErr(err) + } + } + + j.Flags[k] = tmpJFlags + + wantVal = false + } + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_UIDMap: + + /* handler: j.UIDMap type=[]idtools.IDMap kind=slice quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.UIDMap = nil + } else { + + j.UIDMap = []idtools.IDMap{} + + wantVal := true + + for { + + var tmpJUIDMap idtools.IDMap + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_brace { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: tmpJUIDMap type=idtools.IDMap kind=struct quoted=false*/ + + { + /* Falling back. type=idtools.IDMap kind=struct */ + tbuf, err := fs.CaptureField(tok) + if err != nil { + return fs.WrapErr(err) + } + + err = json.Unmarshal(tbuf, &tmpJUIDMap) + if err != nil { + return fs.WrapErr(err) + } + } + + j.UIDMap = append(j.UIDMap, tmpJUIDMap) + + wantVal = false + } + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_GIDMap: + + /* handler: j.GIDMap type=[]idtools.IDMap kind=slice quoted=false*/ + + { + + { + if tok != fflib.FFTok_left_brace && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for ", tok)) + } + } + + if tok == fflib.FFTok_null { + j.GIDMap = nil + } else { + + j.GIDMap = []idtools.IDMap{} + + wantVal := true + + for { + + var tmpJGIDMap idtools.IDMap + + tok = fs.Scan() + if tok == fflib.FFTok_error { + goto tokerror + } + if tok == fflib.FFTok_right_brace { + break + } + + if tok == fflib.FFTok_comma { + if wantVal == true { + // TODO(pquerna): this isn't an ideal error message, this handles + // things like [,,,] as an array value. + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) + } + continue + } else { + wantVal = true + } + + /* handler: tmpJGIDMap type=idtools.IDMap kind=struct quoted=false*/ + + { + /* Falling back. type=idtools.IDMap kind=struct */ + tbuf, err := fs.CaptureField(tok) + if err != nil { + return fs.WrapErr(err) + } + + err = json.Unmarshal(tbuf, &tmpJGIDMap) + if err != nil { + return fs.WrapErr(err) + } + } + + j.GIDMap = append(j.GIDMap, tmpJGIDMap) + + wantVal = false + } + } + } + + state = fflib.FFParse_after_value + goto mainparse + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + + return nil +} + +// MarshalJSON marshal bytes to json - template +func (j *layerMountPoint) MarshalJSON() ([]byte, error) { + var buf fflib.Buffer + if j == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := j.MarshalJSONBuf(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalJSONBuf marshal buff to json - template +func (j *layerMountPoint) MarshalJSONBuf(buf fflib.EncodingBuffer) error { + if j == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + buf.WriteString(`{"id":`) + fflib.WriteJsonString(buf, string(j.ID)) + buf.WriteString(`,"path":`) + fflib.WriteJsonString(buf, string(j.MountPoint)) + buf.WriteString(`,"count":`) + fflib.FormatBits2(buf, uint64(j.MountCount), 10, j.MountCount < 0) + buf.WriteByte('}') + return nil +} + +const ( + ffjtlayerMountPointbase = iota + ffjtlayerMountPointnosuchkey + + ffjtlayerMountPointID + + ffjtlayerMountPointMountPoint + + ffjtlayerMountPointMountCount +) + +var ffjKeylayerMountPointID = []byte("id") + +var ffjKeylayerMountPointMountPoint = []byte("path") + +var ffjKeylayerMountPointMountCount = []byte("count") + +// UnmarshalJSON umarshall json - template of ffjson +func (j *layerMountPoint) UnmarshalJSON(input []byte) error { + fs := fflib.NewFFLexer(input) + return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +// UnmarshalJSONFFLexer fast json unmarshall - template ffjson +func (j *layerMountPoint) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error + currentKey := ffjtlayerMountPointbase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffjtlayerMountPointnosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + case 'c': + + if bytes.Equal(ffjKeylayerMountPointMountCount, kn) { + currentKey = ffjtlayerMountPointMountCount + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'i': + + if bytes.Equal(ffjKeylayerMountPointID, kn) { + currentKey = ffjtlayerMountPointID + state = fflib.FFParse_want_colon + goto mainparse + } + + case 'p': + + if bytes.Equal(ffjKeylayerMountPointMountPoint, kn) { + currentKey = ffjtlayerMountPointMountPoint + state = fflib.FFParse_want_colon + goto mainparse + } + + } + + if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountCount, kn) { + currentKey = ffjtlayerMountPointMountCount + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointMountPoint, kn) { + currentKey = ffjtlayerMountPointMountPoint + state = fflib.FFParse_want_colon + goto mainparse + } + + if fflib.SimpleLetterEqualFold(ffjKeylayerMountPointID, kn) { + currentKey = ffjtlayerMountPointID + state = fflib.FFParse_want_colon + goto mainparse + } + + currentKey = ffjtlayerMountPointnosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffjtlayerMountPointID: + goto handle_ID + + case ffjtlayerMountPointMountPoint: + goto handle_MountPoint + + case ffjtlayerMountPointMountCount: + goto handle_MountCount + + case ffjtlayerMountPointnosuchkey: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +handle_ID: + + /* handler: j.ID type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.ID = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_MountPoint: + + /* handler: j.MountPoint type=string kind=string quoted=false*/ + + { + + { + if tok != fflib.FFTok_string && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for string", tok)) + } + } + + if tok == fflib.FFTok_null { + + } else { + + outBuf := fs.Output.Bytes() + + j.MountPoint = string(string(outBuf)) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +handle_MountCount: + + /* handler: j.MountCount type=int kind=int quoted=false*/ + + { + if tok != fflib.FFTok_integer && tok != fflib.FFTok_null { + return fs.WrapErr(fmt.Errorf("cannot unmarshal %s into Go value for int", tok)) + } + } + + { + + if tok == fflib.FFTok_null { + + } else { + + tval, err := fflib.ParseInt(fs.Output.Bytes(), 10, 64) + + if err != nil { + return fs.WrapErr(err) + } + + j.MountCount = int(tval) + + } + } + + state = fflib.FFParse_after_value + goto mainparse + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + + return nil +} + +// MarshalJSON marshal bytes to json - template +func (j *layerStore) MarshalJSON() ([]byte, error) { + var buf fflib.Buffer + if j == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := j.MarshalJSONBuf(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalJSONBuf marshal buff to json - template +func (j *layerStore) MarshalJSONBuf(buf fflib.EncodingBuffer) error { + if j == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + buf.WriteString(`{}`) + return nil +} + +const ( + ffjtlayerStorebase = iota + ffjtlayerStorenosuchkey +) + +// UnmarshalJSON umarshall json - template of ffjson +func (j *layerStore) UnmarshalJSON(input []byte) error { + fs := fflib.NewFFLexer(input) + return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +// UnmarshalJSONFFLexer fast json unmarshall - template ffjson +func (j *layerStore) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error + currentKey := ffjtlayerStorebase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffjtlayerStorenosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + } + + currentKey = ffjtlayerStorenosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffjtlayerStorenosuchkey: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + + return nil +} + +// MarshalJSON marshal bytes to json - template +func (j *simpleGetCloser) MarshalJSON() ([]byte, error) { + var buf fflib.Buffer + if j == nil { + buf.WriteString("null") + return buf.Bytes(), nil + } + err := j.MarshalJSONBuf(&buf) + if err != nil { + return nil, err + } + return buf.Bytes(), nil +} + +// MarshalJSONBuf marshal buff to json - template +func (j *simpleGetCloser) MarshalJSONBuf(buf fflib.EncodingBuffer) error { + if j == nil { + buf.WriteString("null") + return nil + } + var err error + var obj []byte + _ = obj + _ = err + buf.WriteString(`{}`) + return nil +} + +const ( + ffjtsimpleGetCloserbase = iota + ffjtsimpleGetClosernosuchkey +) + +// UnmarshalJSON umarshall json - template of ffjson +func (j *simpleGetCloser) UnmarshalJSON(input []byte) error { + fs := fflib.NewFFLexer(input) + return j.UnmarshalJSONFFLexer(fs, fflib.FFParse_map_start) +} + +// UnmarshalJSONFFLexer fast json unmarshall - template ffjson +func (j *simpleGetCloser) UnmarshalJSONFFLexer(fs *fflib.FFLexer, state fflib.FFParseState) error { + var err error + currentKey := ffjtsimpleGetCloserbase + _ = currentKey + tok := fflib.FFTok_init + wantedTok := fflib.FFTok_init + +mainparse: + for { + tok = fs.Scan() + // println(fmt.Sprintf("debug: tok: %v state: %v", tok, state)) + if tok == fflib.FFTok_error { + goto tokerror + } + + switch state { + + case fflib.FFParse_map_start: + if tok != fflib.FFTok_left_bracket { + wantedTok = fflib.FFTok_left_bracket + goto wrongtokenerror + } + state = fflib.FFParse_want_key + continue + + case fflib.FFParse_after_value: + if tok == fflib.FFTok_comma { + state = fflib.FFParse_want_key + } else if tok == fflib.FFTok_right_bracket { + goto done + } else { + wantedTok = fflib.FFTok_comma + goto wrongtokenerror + } + + case fflib.FFParse_want_key: + // json {} ended. goto exit. woo. + if tok == fflib.FFTok_right_bracket { + goto done + } + if tok != fflib.FFTok_string { + wantedTok = fflib.FFTok_string + goto wrongtokenerror + } + + kn := fs.Output.Bytes() + if len(kn) <= 0 { + // "" case. hrm. + currentKey = ffjtsimpleGetClosernosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } else { + switch kn[0] { + + } + + currentKey = ffjtsimpleGetClosernosuchkey + state = fflib.FFParse_want_colon + goto mainparse + } + + case fflib.FFParse_want_colon: + if tok != fflib.FFTok_colon { + wantedTok = fflib.FFTok_colon + goto wrongtokenerror + } + state = fflib.FFParse_want_value + continue + case fflib.FFParse_want_value: + + if tok == fflib.FFTok_left_brace || tok == fflib.FFTok_left_bracket || tok == fflib.FFTok_integer || tok == fflib.FFTok_double || tok == fflib.FFTok_string || tok == fflib.FFTok_bool || tok == fflib.FFTok_null { + switch currentKey { + + case ffjtsimpleGetClosernosuchkey: + err = fs.SkipField(tok) + if err != nil { + return fs.WrapErr(err) + } + state = fflib.FFParse_after_value + goto mainparse + } + } else { + goto wantedvalue + } + } + } + +wantedvalue: + return fs.WrapErr(fmt.Errorf("wanted value token, but got token: %v", tok)) +wrongtokenerror: + return fs.WrapErr(fmt.Errorf("ffjson: wanted token: %v, but got token: %v output=%s", wantedTok, tok, fs.Output.String())) +tokerror: + if fs.BigError != nil { + return fs.WrapErr(fs.BigError) + } + err = fs.Error.ToError() + if err != nil { + return fs.WrapErr(err) + } + panic("ffjson-generated: unreachable, please report bug.") +done: + + return nil +} diff --git a/vendor/github.com/containers/storage/lockfile_compat.go b/vendor/github.com/containers/storage/lockfile_compat.go index 6fac2ebac6..56710277c9 100644 --- a/vendor/github.com/containers/storage/lockfile_compat.go +++ b/vendor/github.com/containers/storage/lockfile_compat.go @@ -13,3 +13,7 @@ func GetLockfile(path string) (lockfile.Locker, error) { func GetROLockfile(path string) (lockfile.Locker, error) { return lockfile.GetROLockfile(path) } + +func GetLockfileRWRO(path string, readOnly bool) (lockfile.Locker, error) { + return lockfile.GetLockfileRWRO(path, readOnly) +} diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile.go index a5b72c5435..1381769a6f 100644 --- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile.go +++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile.go @@ -41,6 +41,10 @@ type Locker interface { // Locked() checks if lock is locked for writing by a thread in this process Locked() bool + + // SetReadOnly can be used to set the locker either to `read-only` or + // `read-write` + SetReadOnly(bool) } var ( @@ -52,14 +56,21 @@ var ( // Locker object may already be locked if the path has already been requested // by the current process. func GetLockfile(path string) (Locker, error) { - return getLockfile(path, false) + return getLockfile(path, false, false) } // GetROLockfile opens a read-only lock file, creating it if necessary. The // Locker object may already be locked if the path has already been requested // by the current process. func GetROLockfile(path string) (Locker, error) { - return getLockfile(path, true) + return getLockfile(path, true, false) +} + +// GetLockfileRWRO opens a read-only or read-write lock file, depending on its +// use. The Locker object may already be locked if the path has already been +// requested by the current process. +func GetLockfileRWRO(path string, readOnly bool) (Locker, error) { + return getLockfile(path, readOnly, true) } // getLockfile returns a Locker object, possibly (depending on the platform) @@ -69,11 +80,15 @@ func GetROLockfile(path string) (Locker, error) { // “lock for reading” (shared) operation; otherwise, the lock is either an exclusive lock, // or a read-write lock and Locker should correspond to the “lock for writing” (exclusive) operation. // +// `overWriteReadOnly` indicates if the locker should be used as universal +// `read-write` and `read-only` lock. If `overWriteReadOnly` is false, then +// the function will fail if the locker does not match its desired state. +// // WARNING: // - The lock may or MAY NOT be inter-process. // - There may or MAY NOT be an actual object on the filesystem created for the specified path. // - Even if ro, the lock MAY be exclusive. -func getLockfile(path string, ro bool) (Locker, error) { +func getLockfile(path string, ro, overWriteReadOnly bool) (Locker, error) { lockfilesLock.Lock() defer lockfilesLock.Unlock() if lockfiles == nil { @@ -84,6 +99,9 @@ func getLockfile(path string, ro bool) (Locker, error) { return nil, errors.Wrapf(err, "error ensuring that path %q is an absolute path", path) } if locker, ok := lockfiles[cleanPath]; ok { + if overWriteReadOnly { + locker.SetReadOnly(ro) + } if ro && locker.IsReadWrite() { return nil, errors.Errorf("lock %q is not a read-only lock", cleanPath) } diff --git a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go index 302a523f56..d06b3b48ef 100644 --- a/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go +++ b/vendor/github.com/containers/storage/pkg/lockfile/lockfile_unix.go @@ -35,7 +35,7 @@ type lockfile struct { // necessary. func openLock(path string, ro bool) (int, error) { if ro { - return unix.Open(path, os.O_RDONLY, 0) + return unix.Open(path, os.O_RDONLY|os.O_CREATE, 0) } return unix.Open(path, os.O_RDWR|os.O_CREATE, unix.S_IRUSR|unix.S_IWUSR) } @@ -253,3 +253,13 @@ func (l *lockfile) TouchedSince(when time.Time) bool { touched := time.Unix(mtim.Unix()) return when.Before(touched) } + +// SetReadOnly can be used to set the locker either to `read-only` or `read-write` +func (l *lockfile) SetReadOnly(ro bool) { + locktype := unix.F_WRLCK + if ro { + locktype = unix.F_RDLCK + } + l.locktype = int16(locktype) + l.ro = ro +} diff --git a/vendor/github.com/containers/storage/store.go b/vendor/github.com/containers/storage/store.go index b84be4424e..d6f97e6c8d 100644 --- a/vendor/github.com/containers/storage/store.go +++ b/vendor/github.com/containers/storage/store.go @@ -322,9 +322,14 @@ type Store interface { // any are defined) don't contain corresponding IDs. LayerParentOwners(id string) ([]int, []int, error) - // Layers returns a list of the currently known layers. + // Layers returns a list of the currently known layers from the read-only + // store. Layers() ([]Layer, error) + // Layers returns a list of the currently known layers from the read-write + // store. + RWLayers() ([]Layer, error) + // Images returns a list of the currently known images. Images() ([]Image, error) @@ -390,6 +395,9 @@ type Store interface { // Layer returns a specific layer. Layer(id string) (*Layer, error) + // LayerMountpoint returns a specific mountpoint for a layer. + LayerMountpoint(id string) (string, error) + // Image returns a specific image. Image(id string) (*Image, error) @@ -528,6 +536,7 @@ type store struct { gidMap []idtools.IDMap graphDriver drivers.Driver layerStore LayerStore + roLayerStore ROLayerStore roLayerStores []ROLayerStore imageStore ImageStore roImageStores []ROImageStore @@ -742,35 +751,88 @@ func (s *store) GraphDriver() (drivers.Driver, error) { // used by the Store. Accessing this store directly will bypass locking and // synchronization, so it is not a part of the exported Store interface. func (s *store) LayerStore() (LayerStore, error) { - s.graphLock.Lock() - defer s.graphLock.Unlock() - if s.graphLock.TouchedSince(s.lastLoaded) { - s.graphDriver = nil - s.layerStore = nil - s.lastLoaded = time.Now() - } + return s.RWLayerStore() +} + +// RWLayerStore obtains and returns a handle to the writeable layer store object +// used by the Store. Accessing this store directly will bypass locking and +// synchronization, so it is not a part of the exported Store interface. +func (s *store) RWLayerStore() (LayerStore, error) { + s.resetIfNeeded() + + // Memoized read-write layer store if s.layerStore != nil { return s.layerStore, nil } - driver, err := s.getGraphDriver() + + rlpath, glpath, driver, err := s.getLayerPaths() if err != nil { return nil, err } - driverPrefix := s.graphDriverName + "-" - rlpath := filepath.Join(s.runRoot, driverPrefix+"layers") - if err := os.MkdirAll(rlpath, 0700); err != nil { + + rls, err := s.newLayerStore(rlpath, glpath, driver) + if err != nil { return nil, err } - glpath := filepath.Join(s.graphRoot, driverPrefix+"layers") - if err := os.MkdirAll(glpath, 0700); err != nil { + + s.layerStore = rls + return s.layerStore, nil +} + +// ROLayerStore obtains and returns a handle to the read-only layer store object +// used by the Store. +func (s *store) ROLayerStore() (ROLayerStore, error) { + s.resetIfNeeded() + + // Memoized read-only layer store + if s.roLayerStore != nil { + return s.roLayerStore, nil + } + + rlpath, glpath, driver, err := s.getLayerPaths() + if err != nil { return nil, err } - rls, err := s.newLayerStore(rlpath, glpath, driver) + + rls, err := newROLayerStore(rlpath, glpath, driver) if err != nil { return nil, err } - s.layerStore = rls - return s.layerStore, nil + + s.roLayerStore = rls + return s.roLayerStore, nil +} + +// getLayerPaths retrieves the run directory (`rlpath`) the layer directory +// (`glpath`) and the currently configured storage driver for the store +func (s *store) getLayerPaths() (rlpath, glpath string, driver drivers.Driver, err error) { + driver, err = s.getGraphDriver() + if err != nil { + return "", "", nil, err + } + driverPrefix := s.graphDriverName + "-" + rlpath = filepath.Join(s.runRoot, driverPrefix+"layers") + if err := os.MkdirAll(rlpath, 0700); err != nil { + return "", "", nil, err + } + glpath = filepath.Join(s.graphRoot, driverPrefix+"layers") + if err := os.MkdirAll(glpath, 0700); err != nil { + return "", "", nil, err + } + return rlpath, glpath, driver, nil +} + +// resetIfNeeded sets the stores memoized graph driver and layer stores back to +// nil if the graph lock has not been touched since it has been loaded. +func (s *store) resetIfNeeded() { + s.graphLock.Lock() + defer s.graphLock.Unlock() + if s.graphLock.TouchedSince(s.lastLoaded) { + s.graphDriver = nil + s.layerStore = nil + s.roLayerStore = nil + s.lastLoaded = time.Now() + } } // ROLayerStores obtains additional read/only layer store objects used by the @@ -847,7 +909,7 @@ func (s *store) ContainerStore() (ContainerStore, error) { func (s *store) PutLayer(id, parent string, names []string, mountLabel string, writeable bool, options *LayerOptions, diff io.Reader) (*Layer, int64, error) { var parentLayer *Layer - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return nil, -1, err } @@ -960,7 +1022,7 @@ func (s *store) CreateImage(id string, names []string, layer, metadata string, o } if layer != "" { - lstore, err := s.LayerStore() + lstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -1137,7 +1199,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat if options.HostGIDMapping { options.GIDMap = nil } - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -1296,7 +1358,7 @@ func (s *store) CreateContainer(id string, names []string, image, layer, metadat } func (s *store) SetMetadata(id, metadata string) error { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -1344,7 +1406,7 @@ func (s *store) SetMetadata(id, metadata string) error { } func (s *store) Metadata(id string) (string, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return "", err } @@ -1534,10 +1596,10 @@ func (s *store) SetImageBigData(id, key string, data []byte, digestManifest func return ristore.SetBigData(id, key, data, digestManifest) } -func (s *store) ImageSize(id string) (int64, error) { +func (s *store) ImageSize(id string) (size int64, err error) { var image *Image - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return -1, errors.Wrapf(err, "error loading primary layer store data") } @@ -1594,7 +1656,6 @@ func (s *store) ImageSize(id string) (int64, error) { } visited := make(map[string]struct{}) // Walk all of the layers. - var size int64 for len(visited) < len(queue) { for layerID := range queue { // Visit each layer only once. @@ -1649,7 +1710,7 @@ func (s *store) ImageSize(id string) (int64, error) { } func (s *store) ContainerSize(id string) (int64, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return -1, err } @@ -1819,7 +1880,7 @@ func (s *store) SetContainerBigData(id, key string, data []byte) error { } func (s *store) Exists(id string) bool { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return false } @@ -1896,7 +1957,7 @@ func dedupeNames(names []string) []string { func (s *store) SetNames(id string, names []string) error { deduped := dedupeNames(names) - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -1944,7 +2005,7 @@ func (s *store) SetNames(id string, names []string) error { } func (s *store) Names(id string) ([]string, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return nil, err } @@ -2006,7 +2067,7 @@ func (s *store) Names(id string) ([]string, error) { } func (s *store) Lookup(name string) (string, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return "", err } @@ -2069,7 +2130,7 @@ func (s *store) Lookup(name string) (string, error) { } func (s *store) DeleteLayer(id string) error { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -2141,7 +2202,7 @@ func (s *store) DeleteLayer(id string) error { } func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -2279,7 +2340,7 @@ func (s *store) DeleteImage(id string, commit bool) (layers []string, err error) } func (s *store) DeleteContainer(id string) error { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -2340,7 +2401,7 @@ func (s *store) DeleteContainer(id string) error { } func (s *store) Delete(id string) error { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -2416,7 +2477,7 @@ func (s *store) Wipe() error { if err != nil { return err } - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return err } @@ -2453,7 +2514,7 @@ func (s *store) Wipe() error { } func (s *store) Status() ([][2]string, error) { - rlstore, err := s.LayerStore() + rlstore, err := s.ROLayerStore() if err != nil { return nil, err } @@ -2475,7 +2536,7 @@ func (s *store) Mount(id, mountLabel string) (string, error) { id = container.LayerID mountOpts = container.MountOpts() } - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return "", err } @@ -2518,7 +2579,7 @@ func (s *store) Mounted(id string) (int, error) { if layerID, err := s.ContainerLayerID(id); err == nil { id = layerID } - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return 0, err } @@ -2537,7 +2598,7 @@ func (s *store) Unmount(id string, force bool) (bool, error) { if layerID, err := s.ContainerLayerID(id); err == nil { id = layerID } - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return false, err } @@ -2555,7 +2616,7 @@ func (s *store) Unmount(id string, force bool) (bool, error) { } func (s *store) Changes(from, to string) ([]archive.Change, error) { - lstore, err := s.LayerStore() + lstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -2580,7 +2641,7 @@ func (s *store) Changes(from, to string) ([]archive.Change, error) { } func (s *store) DiffSize(from, to string) (int64, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return -1, err } @@ -2605,7 +2666,7 @@ func (s *store) DiffSize(from, to string) (int64, error) { } func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, error) { - lstore, err := s.LayerStore() + lstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -2640,7 +2701,7 @@ func (s *store) Diff(from, to string, options *DiffOptions) (io.ReadCloser, erro } func (s *store) ApplyDiff(to string, diff io.Reader) (int64, error) { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return -1, err } @@ -2659,7 +2720,7 @@ func (s *store) ApplyDiff(to string, diff io.Reader) (int64, error) { func (s *store) layersByMappedDigest(m func(ROLayerStore, digest.Digest) ([]Layer, error), d digest.Digest) ([]Layer, error) { var layers []Layer - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return nil, err } @@ -2707,7 +2768,7 @@ func (s *store) LayersByUncompressedDigest(d digest.Digest) ([]Layer, error) { } func (s *store) LayerSize(id string) (int64, error) { - lstore, err := s.LayerStore() + lstore, err := s.ROLayerStore() if err != nil { return -1, err } @@ -2732,7 +2793,7 @@ func (s *store) LayerSize(id string) (int64, error) { } func (s *store) LayerParentOwners(id string) ([]int, []int, error) { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return nil, nil, err } @@ -2750,7 +2811,7 @@ func (s *store) LayerParentOwners(id string) ([]int, []int, error) { } func (s *store) ContainerParentOwners(id string) ([]int, []int, error) { - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return nil, nil, err } @@ -2782,8 +2843,8 @@ func (s *store) ContainerParentOwners(id string) ([]int, []int, error) { return nil, nil, ErrLayerUnknown } -func (s *store) Layers() ([]Layer, error) { - lstore, err := s.LayerStore() +func (s *store) RWLayers() ([]Layer, error) { + lstore, err := s.RWLayerStore() if err != nil { return nil, err } @@ -2795,6 +2856,24 @@ func (s *store) Layers() ([]Layer, error) { return nil, err } + return s.appendROLayers(layers) + +} + +func (s *store) Layers() ([]Layer, error) { + lstore, err := s.ROLayerStore() + if err != nil { + return nil, err + } + layers, err := lstore.Layers() + if err != nil { + return nil, err + } + + return s.appendROLayers(layers) +} + +func (s *store) appendROLayers(layers []Layer) ([]Layer, error) { lstores, err := s.ROLayerStores() if err != nil { return nil, err @@ -2864,11 +2943,27 @@ func (s *store) Containers() ([]Container, error) { return rcstore.Containers() } -func (s *store) Layer(id string) (*Layer, error) { - lstore, err := s.LayerStore() +func (s *store) Layer(id string) (layer *Layer, err error) { + lstore, err := s.ROLayerStore() if err != nil { return nil, err } + return s.layer(lstore, id) +} + +func (s *store) LayerMountpoint(id string) (string, error) { + lstore, err := s.RWLayerStore() + if err != nil { + return "", err + } + l, err := s.layer(lstore, id) + if err != nil { + return "", err + } + return l.MountPoint, nil +} + +func (s *store) layer(lstore ROLayerStore, id string) (layer *Layer, err error) { lstores, err := s.ROLayerStores() if err != nil { return nil, err @@ -3141,10 +3236,26 @@ func (s *store) FromContainerRunDirectory(id, file string) ([]byte, error) { } func (s *store) Shutdown(force bool) ([]string, error) { + if s.layerStore != nil { + return s.ShutdownRW(force) + } + return nil, s.ShutdownRO() +} + +func (s *store) ShutdownRO() error { + s.graphLock.Lock() + defer s.graphLock.Unlock() + + err := s.graphDriver.Cleanup() + s.graphLock.Touch() + return err +} + +func (s *store) ShutdownRW(force bool) ([]string, error) { mounted := []string{} modified := false - rlstore, err := s.LayerStore() + rlstore, err := s.RWLayerStore() if err != nil { return mounted, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 5c2485f38e..67f7bea4cf 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -141,7 +141,7 @@ github.com/containers/psgo/internal/dev github.com/containers/psgo/internal/host github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/process -# github.com/containers/storage v1.15.8 +# github.com/containers/storage v1.15.8 => github.com/saschagrunert/storage v1.12.3-0.20200225133936-b4f34141d69e github.com/containers/storage github.com/containers/storage/drivers github.com/containers/storage/drivers/aufs